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);
}
Related
I'm trying to create a 2D char array to hold a grid of chars which will be used as a sort of 'map' for a 2D console game.
I am getting a:
IndexOutOfRange exception
..and cannot see why. I've stepped through the code in debug mode and still cannot see the issue.
It steps through the code fine until it hits X = 25 and Y = 1, the upper right boundary of my grid.
I have _gameWidth and _gameHeight created as follows, outside of main but still inside the class:
static int _gameWidth = 25;
static int _gameHeight = 15;
Following is the code that fails, when trying to generate and populate the grid. It fails at this point:
else if (x == _gameWidth && y == 1)
_grid[x, y] = '╕';
static void GenerateGrid()
{
for (int y = 1; y <= _gameHeight; y++)
{
for (int x = 1; x <= _gameWidth; x++)
{
if (x == 1 && y == 1)
_grid[x, y] = '╒';
else if (x == _gameWidth && y == _gameHeight)
_grid[x, y] = '╛';
else if (x == _gameWidth && y == 1)
_grid[x, y] = '╕';
else if (x == 1 && y == _gameHeight)
_grid[x, y] = '╘';
else if ((x != 1 && y == _gameHeight) || (x != _gameWidth && y == 1))
_grid[x, y] = '═';
else if ((x == 1 && y > 1 && y < _gameHeight) || (x == _gameWidth && y > 1 && y < _gameHeight))
_grid[x, y] = '│';
else
_grid[x, y] = 'x';
}
Console.WriteLine("");
}
}
Change
for (int i = 1; i <= gameHeight; i++)
to
for (int i = 0; i < gameHeight; i++)
and do the same for width.
EDIT:
This is because array indexes start at the number 0 and end with the length of the array minus 1.
This exception means that you have accessed an invalid index. From the way you have written the loop I can tell that you think that indexes go from 1 to the length of the array. Arrays are zero-based, though. Use the standard loop form:
for (int i = 0; i < length; i++)
Your loop starts at one. You can use the Visual Studio for loop template. Just type "for<tab><tab>".
Your program might benefit from the Code Review Stack Exchange site.
I have a desktop C# app.
I have a nested loop.
I am comparing values between to multi arrays using the 'if' statement.
this is my code:
for (int x = 0; x < FRAME_HEIGHT; x++)
{
for (int y = 0; y < FRAME_WIDTH; y++)
{
if ((Shared.MotionState[camIndex].PreviousGrid[y, x] != Shared.MotionState[camIndex].DiffCurrentPrevious[y, x]
&& Shared.MotionState[camIndex].DiffCurrentPrevious[y, x] == 1))
{
diffGrids[camIndex][y, x] = 1;
diff++;
}
else
{
diffGrids[camIndex][y, x] = 0;
}
}
}
Now I know I could flatten the arrays but it will still need to use the if statements.
I am not saying there is anything wrong is this I am just asking whether this is the most memory efficient way of doing this.
N.B.
The diff grid is a static modular grid I have created at run-time.
Thanks
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;
I was bored and had only 30 minutes of free time so I decided to have a crack at making the game of life. I followed that rules on wikipedia and it doesn't seem to be working correctly. Could someone please tell me what I would be doing wrong?
Here are the rules:
Any live cell with fewer than two live neighbours dies, as if caused by under-population.
Any live cell with two or three live neighbours lives on to the next generation.
Any live cell with more than three live neighbours dies, as if by overcrowding.
Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
public void PerformLogic()
{
if (in_game)
{
time_elapsed += rate;
if (time_elapsed > frame_rate)
{
time_elapsed = 0;
for (int x = 0; x < board_width; x++)
{
for (int y = 0; y < board_height; y++)
{
if (board[x, y] == alive)
{
int surrounding_cells = 0;
for (int x2 = -1; x2 <= 1; x2++)
{
for (int y2 = -1; y2 <= 1; y2++)
{
if (!(x2 + x <= -1 || y2 + y <= -1 || x + x2 >= board_width || y + y2 >= board_height))
{
if (board[x + x2, y + y2] == alive)
{
surrounding_cells++;
}
}
}
}
if (surrounding_cells < 2)
{
board[x, y] = dead;
}
if (surrounding_cells == 2 ||
surrounding_cells == 3)
{
board[x, y] = alive;
}
if (surrounding_cells > 3)
{
board[x, y] = dead;
}
}
else if (board[x, y] == dead)
{
int surrounding_cells = 0;
for (int x2 = -1; x2 <= 1; x2++)
{
for (int y2 = -1; y2 <= ; y2++)
{
if (!(x2 + x <= -1 || y2 + y <= -1 || x + x2 >= board_width || y + y2 >= board_height))
{
if (board[x + x2, y + y2] == alive)
{
surrounding_cells++;
}
}
}
}
if (surrounding_cells == 3)
{
board[x, y] = alive;
}
}
}
}
}
}
}
Any ideas?
I believe you are updating the board too early. The game of life should update the board after it finishes scanning the whole board, rather than while scanning.
E.g.:
if (surrounding_cells > 3)
{
board[x, y] = dead;
}
After this, for the cell next to it, this cell would be treated as dead.
Marc is right, too.
for (int x2 = -1; x2 <= 1; x2++)
{
for (int y2 = -1; y2 <= 1; y2++)
{
looks to me like you're including the central cell in this loop, so 9 instead of 8.
I'm not sure the nested for is the best option, but if you are using that, add:
if(x2 == 0 && y2 == 0) continue;
at the start of the inner loop (i.e. after the last line that I've posted above)
this code gives output but it has one problem that is when user write 5,6 in textbox1 and 7,8 in textbox3 it output 5,6.i know the problem is that when the elements of an array ends,it doesnt print the rest elements of other array,i commented on line of problem.
edited:i used textbox1 and textbox3 for getting the elements of the arrays that user wants to merge
private void button3_Click(object sender, EventArgs e)
{
string[] source = textBox1.Text.Split(',');
string[] source1 = textBox3.Text.Split(',');
int[] nums2 = new int[8];
int[] nums = new int[source.Length];
for (int i = 0; i < source.Length; i++)
{
nums[i] = Convert.ToInt32(source[i]);
}
int[] nums1 = new int[source1.Length];
for (int j = 0; j < source1.Length; j++)
{
nums1[j] = Convert.ToInt32(source1[j]);
}
int x = 0;
int y = 0;
int z = 0;
while (x < nums.Length && y < nums1.Length)
{
if (nums[x] < nums1[y])
{
nums2[z] = nums[x];
x++;
}
else
{
nums2[z] = nums1[y];
y++;
}
z++;
}////----->>it works untill here
while (x > nums.Length)///this mean when the elements of nums end,out the rest of the elements in other textbox but it doesnt do anything,whats the problem ?
{
if (y <= nums1.Length)
{
nums2[z] = nums1[y];
z++;
y++;
}
}
while (y > nums1.Length)
{
if (x <= nums.Length)
{
nums2[z] = nums[x];
z++;
x++;
}
}
string merge = "";
foreach (var n in nums2)
merge += n.ToString() + ",";
textBox4.Text = merge;
}
Do (remove your last while)
while (x < nums.Length)
{
nums2[z] = nums[x];
z++;
x++;
}
while (y < nums1.Length)
{
nums2[z] = nums1[y];
z++;
y++;
}
because you are not aware which array items remained, also your current code doesn't work anyway, because y is not related to nums and vise verse.
Edit: I copy past first while into second while, fix it, remove your last while loops (2 while with if in them) and replace this.
Both your conditions on while (x > nums.Length) and while (y > nums1.Length) don't make sense, since this will never happen.
In the block before, you increment x and y as long as they are smaller than nums.Length or nums1.Length. Therefore those will never become larger (at most equal), thus both conditions will always be false and the "remaining" items will not be merged in.
Note that there are other things wrong in your mergesort implementation, but that's not in the scope of your specific question I guess.