I have to make a simple windows forms application in which the player takes turns with the computer in taking sticks (which I made out of labels which go invisible), but I am having a problem with the code for the pc as it causes a runtime error "index out of range", and I can't figure it out..
private void pcTake(int x)
{
textBox1.Text = "I take " + x;
for (int i = 0; i < labels.Count; i++)
{
if (labels[i].Visible == false && labels[i + 1].Visible == true)
{
while (x > 0)
{
if (x + i > labels.Count)
break;
labels[i + x].Visible = false;
x--;
}
break;
}
}
}
x is a random number,
labels is a list containing the labels
foreach (Control c in this.Controls)
{
if (c is Label)
{
labels.Add(c);
c.Enabled = true;
}
}
thanks in advance
You are getting the exception beause of your comparison
labels[i + 1].Visible == true
since your loop is based on < labels.Count, that means when the loop index reaches to count - 1, your condition is suppose to check array index on count (because of i + 1), since array's index is 0 based, you are getting the exception.
If you want to check the current index and later index then your loop condition should be i < labels.Count - 1 like:
for (int i = 0; i < labels.Count - 1; i++)
In C#, arrays are 0-indexed, so the last item is labels[labels.Count-1]; you should change this
if (x + i > labels.Count)
break;
into this
if (x + i > labels.Count -1)
break;
Related
I'm using 3 iterators to iterate through an int[] object to find lists containing three int's that all sum to 0, without adding duplicate lists to the final return object. Once the iterators find a valid sequence, each array value that the iterator points to is added to a temporary IList object via syntax such as "tempList.Add(nums[a]);" e.t.c. This tempList is then added to the final IList<IList> return object.
To check for duplicates, I'm using the following sytax:
if ((nums[c] + nums[a] + nums[b] == 0) && !answerList.Contains(tempList))
{
answerList.Add(tempList);
}
This works when the IList<IList> is initially empty, however the second clause evaluated "false" for the following scenario, which is preventing the valid tempList from being added to the IList<IList> answerList :
IList<IList<int>> == [[-1,0,1]]
tempList == [-1,-1,2]
Do I need to extend a Comparable interface to correct this? I've double checked the array values for a, b and c and they collectively sum to 0, so I'm certain that it's the .Contains comparison that is causing issue.
Here is the code:
public IList<IList<int>> ThreeSum(int[] nums) // maybe use three index pointers to fill triplet, one starting at index 0, one
// starting at index nums.Lenght - 1 and one starting near or at middle
// 5 billion possible combinations of triplets among array of 3001 triplets
{
IList<int> tempList = new List<int>();
IList<IList<int>> answerList = new List<IList<int>>();
int countPositive = 0;
int countNegative = 0;
bool addAnswerList = false;
int indexPositive = 0;
int a = 0;
int b = 0;
int c = 0;
bool aExtreme = false;
bool bExtreme = false;
bool cExtreme = false;
if (nums == null)
return answerList;
if (nums.Length == 0 /* || /* nums.Length < 3 */)
return answerList;
if (nums.Length == 1 && nums[0] == 0)
return answerList;
for (int i = 0; i < nums.Length; i++) // corner case where all array values are either postive or negative
// 0 sum triplet not possible
{
if (nums[i] > 0)
countPositive++;
else if (nums[i] < 0)
countNegative++;
}
if ((countPositive == nums.Length || countNegative == nums.Length) || (countNegative == 0 && countPositive == 0))
return answerList;
if (nums.Length < 51)
{
int temp = 0;
for (int i = 1; i < nums.Length; i++) // use recursive sort to go through 3001 elements, use linear if less than 51
{
temp = nums[i];
int j = i;
while (j > 0 && nums[j-1] > temp)
{
nums[j] = nums[j-1];
j--;
}
nums[j] = temp;
}
Console.WriteLine(String.Join(" ", nums));
}
else if (nums.Length > 50) // recursive sort for larger input array
{
mergeSort(nums);
}
// Now nums is storted, 0 sum triplet will most likely be found where entries change from negative to positive
for (int i = 0; i < nums.Length; i++)
{
if (nums[i] > 0)
{
// toPositive = true;
indexPositive = i;
break;
}
}
Console.WriteLine(indexPositive);
if (indexPositive == 0) // case to make sure accessors do not get invalid number
{
a = 0; // initialize other two index accessors in addition to indexPositive
b = 0;
}
else
{
a = indexPositive - 1; // initialize other two index accessors in addition to indexPositive
b = indexPositive - 1;
}
c = indexPositive; // store initial indexPositive value into variable c as indexPositive will change
// throughtout the interation
// if indexPositive is less than (nums.Length / 2), iterate two other accessors towards end of nums
// else, interate two other accessors towards nums[0]
if (c < (nums.Length / 2)) // use iterator c in place of indexPositive
{
while (c < nums.Length && b < nums.Length && a >= 0)
{
if (a == 0 || a == nums.Length - 3)
{
aExtreme = true;
}
else
{
aExtreme = false;
}
if (b == 1 || b == nums.Length - 2)
{
bExtreme = true;
}
else
{
bExtreme = false;
}
if (c == 2 || c == nums.Length - 1)
{
cExtreme = true;
}
else
{
cExtreme = false;
}
if ((c != a && c != b && a != b) && (nums[c] + nums[a] + nums[b] == 0)) // if nums add to 0, add them to tempList
{
tempList.Add(nums[a]);
tempList.Add(nums[b]);
tempList.Add(nums[c]);
}
// need to check if exact triplet is duplicate or if tempList triplet contains same 3 values in different order
// 3 values in different order not an issues since input list is already sorted!!!!
// but need to be aware order accessors are added to temp list. Accessors cannot "crossover" one another!!!
if ((nums[c] + nums[a] + nums[b] == 0) && !answerList.Any(x => x.SequenceEqual(tempList)) /*!answerList.Contains(tempList)*/)
// Having issues, answerList.Contains does not currently do what is desired
{
answerList.Add(tempList); // add tempList to answerList
addAnswerList = true;
}
else
{
addAnswerList = false;
}
tempList.Clear(); // clear tempList to prepare for next entry
// Make changes here to make sure only 1 accessor iterates at a time, to check all possible and logical combinations
// Since array is now sorted, iteration towards sums[0] only has to continue if sum of 3 accessors is greater than 0
// Once active accessor returns a value that results in 0 sum, further iteration is guaranteed to return
// an identical triplet or one that sums to less than 0. At this point, the two accessors that are going in the same
// direction should be iterated by 1 position and the cycle repeated
if (nums[a] + nums[b] + nums[c] < 0) // still have chance to get to 0 value triplet with rightmost accessor
{
c++;
}
else if ((addAnswerList == true) || nums[a] + nums[b] + nums[c] > 0) // no point in further iteration,
// reset 'c' accessor to original starting
// position and decrement other accessors by 1
// towards first array element
{ // to begin cycle again
c = indexPositive - 1;
b--;
a--;
}
}
}
else // a and b accessors are interated towards 0
{
while (c < nums.Length && a >= 0 && b >= 0)
{
if (a == 0 || a == nums.Length - 3)
{
aExtreme = true;
}
else
{
aExtreme = false;
}
if (b == 1 || b == nums.Length - 2)
{
bExtreme = true;
}
else
{
bExtreme = false;
}
if (c == 2 || c == nums.Length - 1)
{
cExtreme = true;
}
else
{
cExtreme = false;
}
if ((c != a && c != b && a != b) && (nums[c] + nums[a] + nums[b] == 0)) // if nums add to 0, add them to tempList
// need to check if exact triplet is duplicate
{
tempList.Add(nums[a]);
tempList.Add(nums[b]);
tempList.Add(nums[c]);
}
Console.WriteLine(String.Join(" ", tempList));
// need to check if exact triplet is duplicate or if tempList triplet contains same 3 values in different order
// 3 values in different order not an issues since input list is already sorted!!!!
// but need to be aware order accessors are added to temp list. Accessors cannot "crossover" one another!!!
if ((nums[c] + nums[a] + nums[b] == 0) && !answerList.Any(x => x.SequenceEqual(tempList)))
// Having issues, answerList.Contains does not currently do what is desired
{
answerList.Add(tempList); // add tempList to answerList
addAnswerList=true;
}
else
{
addAnswerList = false;
}
tempList.Clear(); // clear tempList to prepare for next entry
// Make changes here to make sure only 1 accessor iterates at a time, to check all possible and logical combinations
// Since array is now sorted, iteration towards sums[0] only has to continue if sum of 3 accessors is greater than 0
// Once active accessor returns a value that results in 0 sum, further iteration is guaranteed to return
// an identical triplet or one that sums to less than 0. At this point, the two accessors that are going in the same
// direction should be iterated by 1 position and the cycle repeated
if (nums[a] + nums[b] + nums[c] > 0) // still have chance to get to 0 value triplet with
// leftmost accessor
{
a--;
}
else if ((addAnswerList == true) || nums[a] + nums[b] + nums[c] < 0) // no point in further iteration,
// reset 'a' accessor to original starting
// position and increment other accessors by 1
// towards last array element
{ // to begin cycle again
a = b; // a = indexPositive - 1;
if ((bExtreme == false && b < nums.Length - 2) && (cExtreme == false && c < nums.Length - 1))
// if there is still room to run towards end of array, increment, else decrement
{
b++;
c++;
}
else
{
bExtreme = true;
cExtreme = true;
a -= 2;
b--;
}
}
}
}
Console.WriteLine(String.Join(" ", answerList));
return answerList;
}
public void merge(int[] array1, int[] array2, int[] outArray)
{
int i = 0;
int j = 0;
while (i + j < outArray.Length)
{
if (j == array2.Length || (i < array1.Length && (array1[i] < array2[j])))
{
outArray[i + j] = array1[i++];
}
else
{
outArray[i + j] = array2[j++];
}
}
}
public void mergeSort(int[] inputArray)
{
if (inputArray.Length < 2)
return;
int[] firstHalf = new int[inputArray.Length / 2];
int[] secondHalf = new int[inputArray.Length / 2];
for (int i = 0; i < (inputArray.Length / 2); i++)
{
firstHalf[i] = inputArray[i];
}
for (int i = inputArray.Length / 2; i < inputArray.Length; i++)
{
secondHalf[i] = inputArray[i];
}
mergeSort(firstHalf);
mergeSort(secondHalf);
merge(firstHalf, secondHalf, inputArray);
}
You can replace
answerList.Contains(tempList))
which checks only for reference equality, with
answerList.Any(x => x.SequenceEqual(tempList))
which will run SequenceEqual on the answerList until it finds the first answer that has the same integer elements and returns false if none can be found.
Keep in mind that these functions require System.Linq.
Credit: thanks Hans Kesting for suggesting Any(...) over FirstOrDefault(...) != null
I need to display a Sheet so that the lines are aligned bottom and left. If there are no 10 characters in the word, the number of "+" characters is added so that the total of the line is 10 characters (see my output).
Why, when I print a List, I lose one row?
What's wrong with my piece of code? This matrix should be 10X10.
My output
List<string> filtredList = new List<string>() { "Jacuzzi", "Action", "Chinchilla", "Squeezebox", "Academic", "Abstract" };
int row = 10;
filtredList = Sorting(filtredList); //method is sorting by descending.
foreach (var item in filtredList) Console.WriteLine("Item: " + item + " length: " + item.Length);
Console.WriteLine("-------------------------------------");
//AFTER SORTING IN LIST:
//1)Squeezebox 2)Chinchilla 3)Academic 4)Abstract 5)Jacuzzi 6)Action
for (int i = 10; i > 0; i--)
{
try
{
if (filtredList[i].Length != 10)
{
Console.Write(filtredList[i]);
row = 10 - filtredList[i].Length;
Console.WriteLine(string.Concat(Enumerable.Repeat("+", row)));
}
else Console.WriteLine(filtredList[i]);
}
catch (SystemException)
{
row = 10;
Console.WriteLine(string.Concat(Enumerable.Repeat("+", row)));
}
}
Because your for loop is never gets to 0:
for (int i = 10; i > 0; i--)
i goes from 10 to 1 and that's why the first item of your list never prints.
Note:
Index of first item of an array or a list is 0
The better code would be:
for (int i = 9; i >= 0; i--)
Although you can use better alternatives for some of your code, but this will solve your problem.
EDIT:
You can use this approach (just change the for part to this) to not raise any exceptions (because its not normally a use case for try-catch)and also get faster results:
for (int i = 9; i >= 0; i--)
{
if (i < filtredList.Count)
{
if (filtredList[i].Length != 10)
{
Console.Write(filtredList[i]);
row = 10 - filtredList[i].Length;
Console.WriteLine(new string('+', row));
}
else Console.WriteLine(filtredList[i]);
}
else
{
row = 10;
Console.WriteLine(new string('+', row));
}
}
I am looping through a List<List<Shape>> object and checking if the horizontally and vertically adjacent objects are the same:
for (int x = 0; x < grid.Columns.Count; x++)
{
for (int y = 0; y < grid.Columns[x].Count; y++)
{
if (y != grid.Columns[x].Count - 1)
{
if (grid.Columns[x][y].Column == grid.Columns[x][y + 1].Column)
{
if (!shapesToDestroy.Contains(grid.Columns[x][y]))
{
shapesToDestroy.Add(grid.Columns[x][y]);
}
if (!shapesToDestroy.Contains(grid.Columns[x][y + 1]))
{
shapesToDestroy.Add(grid.Columns[x][y + 1]);
}
}
}
if (x != grid.Columns.Count - 1)
{
if (grid.Columns[x][y].Column == grid.Columns[x + 1][y].Column)
{
if (!shapesToDestroy.Contains(grid.Columns[x][y]))
{
shapesToDestroy.Add(grid.Columns[x][y]);
}
if (!shapesToDestroy.Contains(grid.Columns[x + 1][y]))
{
shapesToDestroy.Add(grid.Columns[x + 1][y]);
}
}
}
}
}
However, I always seem to get a ArgumentOutOfRange on
if (grid.Columns[x][y].Column == grid.Columns[x][y + 1].Column)
and
if (grid.Columns[x][y].Column == grid.Columns[x + 1][y].Column)
Before indexing these, I am performing a check as you can see to make sure that I do not get a ArgumentOutOfRange, but here I am. When I look at the index which is being + 1, it appears to be well under the size of the collection.
Can anyone see the obvious mistake and where I am going horribly wrong?
UPDATE
I updated the code by changing the checks for X and Y to:
if (x < grid.Columns.Count - 1)
and
if (y < grid.Columns[x].Count - 1)
I still get the same error.
FYI - The size of the collection is always the same. The size is: X = 5 and Y = 10
if (x != grid.Columns.Count - 1)
should be
if (x < grid.Columns.Count - 1)
since y is iterated from 0 to the maximum index of the list the operation
grid.Columns[x][y + 1]
will attempt to access an element with a higher index than what is currently in the list. If you want to keep the code above you should change the loop to only iterate to
for (int x = 0; x < grid.Columns.Count-1; x++)
{
for (int y = 0; y < grid.Columns[x].Count-1; y++)
{
}
}
I tried running your code, and i think you could get the functionality that you are looking for stripping it down to:
for (int x = 0; x < grid.Count; x++)
{
for (int y = 0; y < grid[x].Count; y++)
{
if (grid[x].Count > y && grid[x][y] == grid[x][y + 1])
{
if (!shapesToDestroy.Contains(grid[x][y]))
{
shapesToDestroy.Add(grid[x][y]);
}
if (!shapesToDestroy.Contains(grid[x][y + 1]))
{
shapesToDestroy.Add(grid[x][y + 1]);
}
}
if (grid.Count > x && grid[x+1].Count > y && grid[x][y] == grid[x + 1][y])
{
if (!shapesToDestroy.Contains(grid[x][y]))
{
shapesToDestroy.Add(grid[x][y]);
}
if (!shapesToDestroy.Contains(grid[x + 1][y]))
{
shapesToDestroy.Add(grid[x + 1][y]);
}
}
}
}
EDIT
Could also remove the second if in both of the cases since you have already tested that they are equal, doesn't really matter though since it won't change the result. Would just improve performance a tiny bit
it seems that your if condition does not seems correct
Try this
if (y < grid.Columns[x].Count - 1)
instead of
if (y != grid.Columns[x].Count - 1)
Probably your arrays are jagged. And the individual subarrays do not have the same length.
That could be a reason for getting an ArgumentOutOfRange-Exception in:
if (grid.Columns[x][y].Column == grid.Columns[x + 1][y].Column)
Why not use a foreach loop? then you won't have problems with the array out of bounds? Unless you are going for speed. You can use and then nest them as above.
foreach (int key in values.Keys)
{
Console.WriteLine("{0} is assigned to key: {1}", values[key], key);
}
if (theArray[i-1] < theArray.Length && theArray[i-1] != null)
Is what i got after some research. But it gives just gives me out of index error, because i do i-1.
But i want the if statement to check whether the key/index on i-1 exists, then do something..
See what i want to do is plus the values of the indexes next to the current index.
for (int i = 0; i < theArray.Length; i++)
{
Left = 0;
Right = 0;
if (i != 0)
{
Left = theArray[i - 1];
}
if (theArray[i + 1] < theArray.Length)
{
Right = theArray[i + 1];
}
calc = Left + Right;
output2.Text += calc + ", ";
}
So if the left is there then change the left value (default is 0, right and left), and if right is there then change the right value. And then calculate both values taken from theArray[].
E.g if its on theArray[16] it should take the left, theArray[15] and theArray[17] and plus together.
I think you are looking for:
if(i < theArray.Length)
Or possibly:
if(i < theArray.Length && theArray[i] != null)
I would normally be using i in a loop like this:
for(int i = 0; i < theArray.Length; i++)
Update:
You can't use i-1, because on the first iteration, when i == 0, this would evaluate to -1. This is an illegal index in an array.
Update 2:
I think I understand what you are trying to do now. Here is one way to do it:
for (int i = 0; i < theArray.Length; i++)
{
Left = 0;
Right = 0;
if (i > 0)
{
Left = theArray[i-1];
}
if (i < theArray.Length - 1)
{
Right = theArray[i+1];
}
calc = Left + Right;
output2.Text += calc + ", ";
}
To check if i is a valid array index, you can do this:
if(i >= theArray.GetLowerBound(0) && i <= theArray.GetUpperBound(0))
That will only be necessary in rare edge cases, however, so it's more practical to do this:
if(i >= 0 && i < theArray.Length)
Once you know that it's a valid index, you can check for null if need be.
Is your question whether the index or the array value with given index exists?
In case of array you can always be sure that index n "exists" if 0 < n < array.Length.
If you want to check for the array value, first check for (n > 0) for the index "under" and (n < array.Length) for the index "over"
I think in addition to what Oded said, the correct expression might be:
if (i < theArray.Length && i > 0 && theArray[i-1] != null)
because you are checking value at i-1 index.
From your code, it appears that "i" is one-based and your array indexes are zero-based. So you could use:
if ( (i > 0) && (i <= theArray.Length) && (theArray[i-1] != null) )
may be the title of the question is not adequate, here is my problem, i'll start with giving you an example :
Original Sequence :
0. Item_105
1. Item_13
2. Item_6
3. Item_14
4. Item_106
Modified Sequence :
0. Item_105
1. Item_14
2. Item_13
3. Item_6
4. Item_106
Here i must have 2 indexes :
Index1 = 3
Index2 = 1
which means that the old element 3 went to the new position 1
i'm actually working with C# language and when i drag an item to drop it in a new position sometime it gives me good indexes, sometimes not!!
this is the "for" loop i used to get the indexes :
for (int i = 0; i < stops.Count - 1; i++)
{
if (originalOrder[i] != modifiedOrder[i])
{
if (originalOrder[i] == modifiedOrder[i + 1] && index2 == -1)
index2 = i;
else if (modifiedOrder[i] == originalOrder[i + 1] && index2 == -1)
index2 = i;
if (originalOrder[i] != modifiedOrder[i + 1] && index1 == -1)
index1 = i;
}
}
So this is my problem : How to get the right indexes 1 and 2 ? I need the to do some staff later in the code, if i have the right indexes all the rest is OK!!
please can anyone help me?
For starters, the assymetry in your code looks suspicious. Without looking very much at your current code, I would assume that it might be giving you the right answer when you drag an item in one direction but not the other.
index1 = -1;
index2 = stops.Count; // This could be off by one
for (int i = 0; i < stops.Count - 1; i++)
{
// First, find the bounds of what was moved
if (originalOrder[i] != modifiedOrder[i] && index1 == -1)
{
index1 = i;
}
if (index1 != -1 && originalOrder[i] == modifiedOrder[i])
{
index2 = i-1;
// No need to look at any more items
break;
}
}
// Swap indices depending on which direction item was moved
if (originalOrder[index1] != modifiedOrder[index2])
{
int temp = index1;
index1 = index2;
index2 = temp;
}
I can't tell from your example what stops.Count represents. You'll need to ensure that index 2 is initialized to the last index.