开发者

Index was outside of the bounds of the array [duplicate]

This question already has answers here: What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it? (5 answers) Closed 7 years ago.

Unhandled Exception: System.IndexOutOfRangeException: Index was outside of the bounds of the array (at the first if statements)

    static int arrayRows = 20;
    static int arrayCols = 20;

    public void printBoard()
    {
        int neighbours;
        for (y = 0; y < arrayCols; y++)
            for (x = 0; x < arrayRows; x++)
            {
                neighbours = 0;
                /开发者_开发技巧/ Count number of neighbours surrounding live cell
                if (parentGen[x-1, y-1] == 1) // top left 
                    neighbours++;
                if (parentGen[x-1, y] == 1)  // left
                    neighbours++;
                if (parentGen[x-1, y+1] == 1) // bottom left
                    neighbours++;
                if (parentGen[x, y-1] == 1)  // middle top
                    neighbours++;
                if (parentGen[x, y+1] == 1)  // middle bottom
                    neighbours++;
                if (parentGen[x+1, y-1] == 1) // top right
                    neighbours++;
                if (parentGen[x+1, y] == 1)  // right
                    neighbours++;
                if (parentGen[x+1, y+1] == 1) // bottom right
                    neighbours++;
            }
    }

The only thing I can think of is that my program is checking coordinates of < 0? How do I go about fixing this?


Your first coordinates are parentGen[-1, -1], this will always throw the exception.

You need to check if the cell you're on has any neighbors to the left, right, top, or bottom. For example, x = 0 has no neighbors to the left and y = 20 has no neighbors to the bottom. You may wish to break this out to other functions, such as HasNeighborsLeft(int x), etc.

edit: sample code

if(x > 0 && y > 0 && parentGen[x - 1, y - 1] == 1)
{
    neighbors++;
}

You can factor this out to it's own functions though, and you can wrap this kind of logic around all of the checks that involve x - 1 for example.


You need boundary condition checks on both x and y at top and bottom of their range. You cannot legally index the entire array using +1 and -1 offsets. Break up your check into boundary condition cases where x == 0, x == arrayRows-1 (by not checking the invalid relative offsets here), and then check cases where x+1 and x-1 are always valid in an else. Similarly with y.


You're array goes from 0->21. As well, you're testing values at [-1, -1] and [22, 22]You can fix it by chainging your for statement(s) to

for (int x = 1; x <= arrayCols - 1; x++)
    for (int y = 1; y <= arrayRows - 1; y++)

In addition, problems with loops are almost always caused by a small number of cases that you can always check for:

  1. Your for statement a) starts at a lower bound than the array, or b) finishes at a higher one a) for (int x = -1; b) for (int x = 0; x <= array.Length

  2. Your code in the loop accesses values outside of your indexer range for (int x = 0... array[x-1, ...

  3. Your collection isn't initialized

In this case, your problem 2.


The problem is that you are looking at the previous and next values (-1 and +1) which will obviously go outside the array bounds at either ends of the array.

There are a few options solving this:

  • Create a bigger array with a dummy 'border' around the edge which you don't use for your board but allows you to use code very similar to that which you have now (with your -1 and +1 previous and next cell logic). (Imagine a chess board that is 10x10 where you are not allowed to play in the outermost squares).
  • Scatter loads of 'if' statements to check if you're at the first or last item in the array and thus avoid making any array accesses that are invalid.
  • Create a function to retrieve an item at a particular cell and put conditional logic in this function for dealing with the array bounds.

Personally I would go with the last option, build yourself a function which gets the state of the specified cell, checks that the indices are valid and returns a default value if they are not. For example:

private const int EMPTY_CELL = 0;
private const int INVALID_CELL = EMPTY_CELL; // for now the same, but gives scope to handle separately

private int GetCellState(int row, int column)
{
    if (row < 0) return INVALID_CELL;
    if (column < 0) return INVALID_CELL;
    if (row >= arrayRows) return INVALID_CELL;
    if (column >= arrayColumns) return INVALID_CELL;

    return parentGen[row, column];
}

It is then simply a matter of swapping your direct accesses to parentGen with calls to the function.


you could start by creating a sequence of only the valid indices and then iterate the combinations of those:

static int arrayRows = 20;
static int arrayCols = 20;

public void printBoard()
{
    var sequences = from row in Enumerable.Range(0, arrayRows)
                    from column in Enumerable.Range(0, arrayCols)
                    select new
                    {
                        Rows = (from xs in new[] { row - 1, row, row + 1 }
                                where xs >= 0 && xs < 20
                                select xs),
                        Columns = (from ys in new[] { column - 1, column, column + 1 }
                                   where ys >= 0 && ys < 20
                                   select ys)
                    };
    //now that we have a sequence with all the needed (valid) indices 
    //iterate through the combinations of those
    var neighbours = (from seq in sequences
                      from row in seq.Rows
                      from column in seq.Columns
                      where row != column && parentGen[row, column] == 1
                      select 1).Count();

}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜