Global array not being accessed correctly - c#

Below is my current code:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public int[] trialArray = new int[10];
public int trialCounter = -1;
private void button1_Click(object sender, EventArgs e)
{
bool button1Click = true;
if (button1Click == true)
{
ITIpanel.Visible = true;
for (int i = 0; i < trialArray.Length; i++) { trialArray[i] = -1; } // Set default value through array
int counter = 0;
Random rnd = new Random();
while (counter < 10 / 2)
{ // Red trials, fill half array
int index = rnd.Next(0, 10 - 1);
if (trialArray[index] == -1) { trialArray[index] = 1; ++counter; } //if unchanged value, change it
}
while (counter < 10)
{
int index = rnd.Next(0, 10);
if (trialArray[index] == -1) { trialArray[index] = 2; ++counter; }
}
}
}
private void ITIpanel_Paint(object sender, PaintEventArgs e)
{
if (ITIpanel.Visible == true)
{
trialCounter += 1;
timer1.Enabled = true;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
ITIpanel.Visible = false;
timer1.Enabled = false;
if (trialArray[trialCounter] == 1) { redstimPanel.Visible = true; }
else { bluestimPanel.Visible = true;}
if (trialCounter == 9) { Application.Exit(); }
}
public int counter = 0;
public event EventHandler Clicked5TimesEvent;
private void OnClicked5TimesEvent()
{ if (Clicked5TimesEvent != null) { Clicked5TimesEvent(this, EventArgs.Empty); } }
private void bluestimPanel_MouseDown(object sender, EventArgs e)
{
//FR requirement
counter++; if (counter % 5 == 0) { redstimPanel.Visible = false; ITIpanel.Visible = true; }
}
private void redstimPanel_MouseDown(object sender, EventArgs e)
{
//FR requirement
counter++; if (counter % 5 == 0) { redstimPanel.Visible = false; ITIpanel.Visible = true; }
}
}
}
As you can see, I am attempting to make a global array with 10 items. On the button click the 10 items are supposed to be altered such that half contain the value 1 and the other half contain the value 2.
Then, on the timer tick, depending on the value in the trialCounter, which determines the part of the array to be accessed, it should display either the redstimPanel or the bluestimPanel.
Therefore, if the 'trialCounter' is equal to 8, and 8 in the TrialArray is equal 1, the 'redstimPanel' should become Visible. Alternatively, if 8 in the 'TrialArray' is equal to 2, the 'bluestimPanel' should become Visible.
This, however, is not working as I would like it to. Thus, there are clearly some issues with my code. Do you all have any suggestions?

You never reset counter, or have the second loop (the one setting the 2s) be the full array.
There is also an error with the random number, rnd.Next(a,b) a - lower bound (inclusive), b - upper bound (exclusive). So it should be rnd.Next(0,10); so you have a chance of populating the last array position.
while (counter < 10 / 2) { // Red trials, fill half array
int index = rnd.Next(0, 10);
if (trialArray[index] == -1) { trialArray[index] = 1; ++counter; } //if unchanged value, change it
}
//Counter on the first loop here is already 5 (it exited the previous loop)
//So allow it to get to 10, and populate the FULL array.
while (counter < 10) {
int index = rnd.Next(0, 10);
if (trialArray[index] == -1) { trialArray[index] = 2; ++counter; }
}

Allow me to give you some tips and some explanations regarding your code:
First of all, you probably wanted that local button1Click variable to know later on whether the button has been clicked or not. For that to work, you should place it outside that function, otherwise it's never going to be used, and will be true with every button click, something like this:
bool button1Click = false;
private void button1_Click(object sender, EventArgs e)
{
if (!button1Click)
{
When you have a condition, you want the code to decide, whether an expression is true or false you may omit the part "== true" because it doesn't add anything new.
You have two whiles. Your idea was to run the counter until 5, with the first piece of code, and then from 5 to 10 the second piece of code. Now let me try to explain what is actually going on. The counter will go on until 5 filling 1s at random indices. Then at 5, the expression in the while will become false and it breaks out from the loop. Since the second while has the very same expression, it simply avoids it and goes on. One of the many solutions would be to have an if in the loop like this:
while (counter < 10)
{
if (counter<5)
{
// fill red
}
else
{
// fill blue
}
}
The way you fill up the values in your array. Have you thought about what's going to happen when the same index will be generated several times? It means it'll overwrite the previous value while certain index will remain -1.

Related

How to check range in checkedlistbox c# winforms?

I have a checkeboxlist with 100 items. Obviously user can check items one by one as many as he need, but I would like to give to user option check range of items (let's say with Shift hold button). So, user check one of the items (let's say item index 5) and then press and hold shift button and check next item (index 10), so I range of the items should be checked from 5...10
I have not found anything about such implementation, looks like it doesn't exist and no one did such kind of things.
How to do it?
Keep track of your last index:
int lastIndex = -1;
In your form's constructor, wire things up:
public Form1() {
InitializeComponent();
checkedListBox1.CheckOnClick = true;
checkedListBox1.SelectedIndexChanged += CheckedListBox1_SelectedIndexChanged;
checkedListBox1.MouseDown += CheckedListBox1_MouseDown;
}
And then use these methods to change the items in the range:
private void CheckedListBox1_SelectedIndexChanged(object sender, EventArgs e) {
lastIndex = checkedListBox1.SelectedIndex;
}
private void CheckedListBox1_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left && Control.ModifierKeys == Keys.Shift) {
var useIndex = Math.Max(lastIndex, 0);
var x = checkedListBox1.IndexFromPoint(e.Location);
if (x > -1 && x != useIndex) {
if (useIndex > x) {
for (int i = useIndex - 1; i > x; i--) {
checkedListBox1.SetItemChecked(i, !checkedListBox1.GetItemChecked(i));
}
} else {
for (int i = useIndex + 1; i < x; i++) {
checkedListBox1.SetItemChecked(i, !checkedListBox1.GetItemChecked(i));
}
}
}
}
}

Assigning unique values to the index of an array

I am trying to make my button take input from a textbox and add it to the index. The problem is that with everything I have tried, I cannot get it to give a unique value to each position in the index.
private void addBtn_Click(object sender, EventArgs e)
{
for (int i = 0; i < nums.Length; i++)
{
if (nums[0] == 0)
{
nums[0] = int.Parse(inputText.Text);
i++;
}
if (nums[1] == 0)
{
nums[1] = int.Parse(inputText.Text);
i++;
}
}
MessageBox.Show(nums[i].ToString());
}
Right now my code inserts the value to both index positions instead of assigning a value to position 0 and then allowing the user to insert a different value into position 1 and so on and so on.
It's not clear what your intent is, but it looks like you might be trying to add numbers to an array. This code will assign the parsed string to the first item in the array that isn't zero.
private void addBtn_Click(object sender, EventArgs e)
{
int i = 0;
for (; i < nums.Length; i++)
{
if (nums[i] == 0)
{
nums[i] = int.Parse(inputText.Text);
break;
}
}
MessageBox.Show(nums[i].ToString());
}
But this would be a better way, because the user might type "0":
private int _lastUsedIndex = -1;
private void addBtn_Click(object sender, EventArgs e)
{
var number = int.Parse(inputText.Text);
// Increment by one
++_lastUsedIndex;
nums[_lastUsedIndex] = number;
MessageBox.Show(number.ToString());
}
But still, arrays aren't a great idea: They can't grow as you add things. First they're bigger than you need, then suddenly they're too small and you crash. We have better options now. Unless your teacher insists that you must use an array, use List<int> instead. In this version, we'll also use a different way to parse the number, which won't crash if the user types "LOLWUT?!?!" instead of a number:
private List<int> nums = new List<int>();
private void addBtn_Click(object sender, EventArgs e)
{
int number;
if (int.TryParse(inputText.Text, out number))
{
nums.Add(number);
MessageBox.Show(number.ToString());
}
else
{
MessageBox.Show(inputText.Text + " isn't a number, smart guy.");
}
}

Circular show with previous and next buttons

Say I have a list: 1 5 6 10
When I click on next and the List item showed is already 10.. I want to bring the user back to 1 and same in the other way when I click previous and the List item showed is already 1.. I want to bring the user back to 10.. Here is what I tried but I always get that the "i (contor) can't be negative or greater than List.Count" :
public int i = 0;
private void nextbutton_Click(object sender, EventArgs e)
{
++i;
if (sweaterclicked)
{
if(SweatersList.Count != 1)
if (i >= SweatersList.Count - 1)
{
i = 0;
pictureBox1.Image = SweatersList[i];
}
else pictureBox1.Image = SweatersList[i];
}
}
private void previousbutton_Click(object sender, EventArgs e)
{
--i;
if (sweaterclicked)
{
if (SweatersList.Count != 1)
{
if (i < 0)
{
i = SweatersList.Count;
pictureBox1.Image = SweatersList[i];
}
else pictureBox1.Image = SweatersList[i];
}
}
}
Array or list indexes in C# start at zero, so the largest in-range index is one less than the count of items in the collection. Therefore, SweatersList.Count, hence i, is out of range here:
i = SweatersList.Count;
pictureBox1.Image = SweatersList[i];
So when you want to start over at the last valid index, you need to subtract one from SweatersList.Count:
i = SweatersList.Count - 1;
I don't know why you're incrementing and decrementing outside the if (sweaterclicked) blocks, but I presume you do.

Min and max button and label

I'm trying to build a exam grader using C#. I'm new to this and don't know very much. What code would I use to add min and max buttons and to add a label stating whether it's a min or max?
private void btnAdd_Click(object sender, EventArgs e)
{
int points;
try
{
points = int.Parse(txtPoints.Text);
lstPoints.Items.Add(points);
txtPoints.Clear();
txtPoints.Focus();
if (lstPoints.Items.Count == 12)
{
txtPoints.Enabled = false;
btnAdd.Enabled = false;
}
if (lblResult.Text != "")
{
lblResult.Text = "";
}
}
catch
{
MessageBox.Show("Please enter only whole numbers");
txtPoints.Clear();
txtPoints.Focus();
}
}
private void btnAvg_Click(object sender, EventArgs e)
{
double total = 0;
for (int i = 0; i < lstPoints.Items.Count; i++)
{
total += (int)lstPoints.Items[i];
}
total /= lstPoints.Items.Count;
lblResult.Text = total.ToString();
}
private void btnClear_Click(object sender, EventArgs e)
{
lstPoints.Items.Clear();
txtPoints.Enabled = true;
btnAdd.Enabled = true;
}
}
}
hope this works
private void getMax()
{
int max=0;
for (int i = 0; i < lstPoints.Items.Count; i++)
{
if(max<(int)lstPoints.Items[i])
{
max=(int)lstPoints.Items[i];
}
}
lblResult.Text = max.ToString();
}
}
private void getMin()
{
int min=(int)lstPoints.Items[0];
for (int i = 1; i < lstPoints.Items.Count; i++)
{
if(min>(int)lstPoints.Items[i])
{
min=(int)lstPoints.Items[i];
}
}
lblResult.Text = min.ToString();
}
}
There are two possiblities as I see:
1) When you are writing this:
lstPoints.Items.Add(points);
Instead of adding to List(Of Integer) use SortedList. So the
list will always have the sorted result sets.
2) Use Array.Sort() to sort the records.
Once you have sorted records the first one is the minimum and the last one is the maximum (Assuming sorted in ascending order).
Take out two buttons and placed on the form, set Text Property from property window to Min and Max respectively and in event handler handle the Click event and pick the relevant resultset from lstPoints array.
Hope it helps!

How to run a for loop after a for loop?

I have a variable 'start' that initializes with a value 0.
How can i switch to a different loop when 1 argument becomes true.
So here is what i am trying to accomplish
when I click the button
1st Loop start with textBlock 1 containing "XXXX"
and Variable'Start' increment's by 1 everytime i click/touch till it reaches 34 . So when the counter reaches 34, the text changes to 'YYYY'
2nd Loop is when the counter resets and starts from 0 again but this time it only needs to go up till 33 . As soon as it reaches 33 the text changes to 'ZZZZ'.
Last Loop: The counter resets agains goes up till 33 . But this time when it finishes. It goes back to loop 1.
Here is the code that i have right now and I cannot seem to figure out how to do the last loop.
public partial class MainPage : PhoneApplicationPage
{
private int start = 0;
private bool sw = false;
// Constructor
public MainPage()
{
InitializeComponent();
int start = 0;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
tasbih();
}
public void tasbih()
{
if (sw == false)
{
textBlock1.Text = "TEXTBX 1";
}
start++;
String text1 = Convert.ToString(start);
textBlock2.Text = text1;
if (start >= 35)
{
textBlock1.Text = "TEXTBX 2";
start = 0;
String text2 = Convert.ToString(start);
textBlock2.Text = text2;
sw = true;
}
}
private void button2_Click(object sender, RoutedEventArgs e)
{
textBlock1.Text = "Reset";
tasbih();
}
Also i have a reset button that starts everything all over no matter where you are in the counter. Any pointers as to how i can do that ?
I suggest you have a more explicit state variable, and key off of that for all your logic. You're currently keying off of start only for the transition to sw = true, it'll be easier if you have an explicit state.
enum MyState { Part1, Part2, Part3 }
MyState currentState = Part1;
int clickCount = 0;
public void tasbih()
{
clickCount++;
// First, do state transitions.
switch(currentState)
{
case MyState.Part1:
if(clickCount >= 34) { currentState = MyState.Part2; clickCount = 0; }
break;
case MyState.Part2:
if(clickCount >= 33) { currentState = MyState.Part3; clickCount = 0; }
break;
case MyState.Part3:
if(clickCount >= 33) { currentState = MyState.Part1; clickCount = 0; }
break;
}
// Now, act on the current (or new) state.
switch(currentState)
{
case MyState.Part1:
textBlock1.Text = "TEXTBX 1";
textBlock2.Text = clickCount.ToString();
break;
case MyState.Part2:
textBlock1.Text = "TEXTBX 2";
textBlock2.Text = clickCount.ToString();
break;
case MyState.Part3:
textBlock1.Text = "ZZZZ";
textBlock2.Text = clickCount.ToString();
break;
}
}
private void button2_Click(object sender, RoutedEventArgs e)
{
currentState = MyState.Part1;
clickCount = 0;
tasbih();
}
// these have to be member variables, or you'll never be able to reset
// or even remember the counter between calls
private int clicks = 0; // the number of clicks in the current loop
private int state = 0; // which loop we're in
// these are just so we don't have to repeat ourselves.
// each element corresponds to a possible value of `state`.
// both arrays should have the same number of elements.
// alternatively, you could have a type containing the label and max together,
// and just have an array of those.
private string[] labels = { "TEXTBX 1", "TEXTBX 2", "ZZZZ" };
private int[] max = { 34, 33, 33 };
public void reset() {
clicks = 0;
state = 0;
// probably reset text boxes here too. If you don't want to, then delete
updateTextBoxes();
}
public void bump()
{
// bump the counter, and if it's high enough, switch to the next state
// and reset the counter
// (the "% max.Length" causes 3 to be 0, so states wrap around)
if (++clicks > max[state])
{
state = (state + 1) % max.Length;
clicks = 0;
}
updateTextBoxes();
}
private void updateTextBoxes() {
textBlock1.Text = labels[state];
textBlock2.Text = clicks.ToString();
}

Categories

Resources