0

未处理的异常:System.IndexOutOfRangeException:索引超出了数组的范围(在第一个 if 语句中)

    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++;
            }
    }

我唯一能想到的是我的程序正在检查 < 0 的坐标?我该如何解决这个问题?

4

5 回答 5

9

你的第一个坐标是 parentGen[-1, -1],这总是会抛出异常。

您需要检查您所在的单元格的左侧、右侧、顶部或底部是否有任何邻居。例如,x = 0 左侧没有邻居,y = 20 底部没有邻居。您可能希望将其分解为其他函数,例如 HasNeighborsLeft(int x) 等。

编辑:示例代码

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

不过,您可以将其分解为它自己的功能,并且您可以将这种逻辑包装在所有涉及 x - 1 的检查中。

于 2010-09-13T15:20:28.420 回答
1

您需要在其范围的顶部和底部对 x 和 y 进行边界条件检查。您不能使用 +1 和 -1 偏移量合法地索引整个数组。将您的检查分解为边界条件情况x == 0, x == arrayRows-1(通过不在这里检查无效的相对偏移量),然后检查x+1x-1在 中始终有效的情况else。与 y 类似。

于 2010-09-13T15:26:16.750 回答
0

你的数组从 0->21 开始。同样,您正在测试 [-1, -1] 和 [22, 22] 的值,您可以通过将 for 语句链接到

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

此外,循环问题几乎总是由少数情况引起的,您可以随时检查:

  1. 您的 for 语句 a) 从数组的下限开始,或 b) 在数组的上限结束 a) for (int x = -1; b) for (int x = 0; x <= array.Length

  2. 循环中的代码访问索引器范围之外的值 (int x = 0... array[x-1, ...

  3. 您的收藏集未初始化

在这种情况下,您的问题 2。

于 2010-09-13T15:28:24.047 回答
0

问题是您正在查看前一个值和下一个值(-1 和 +1),这些值显然会超出数组两端的数组边界。

有几个选项可以解决这个问题:

  • 创建一个更大的数组,其边缘周围有一个虚拟“边框”,您不将其用于您的电路板,但允许您使用与您现在拥有的代码非常相似的代码(使用您的 -1 和 +1 上一个和下一个单元逻辑) . (想象一个 10x10 的棋盘,你不能在最外面的方格下棋)。
  • 分散大量“if”语句以检查您是否位于数组中的第一项或最后一项,从而避免进行任何无效的数组访问。
  • 创建一个函数以在特定单元格中检索项目,并将条件逻辑放入此函数中以处理数组边界。

就我个人而言,我会选择最后一个选项,为自己构建一个获取指定单元格状态的函数,检查索引是否有效,如果不是则返回默认值。例如:

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];
}

然后,只需将您的直接访问权限parentGen与对函数的调用进行交换即可。

于 2010-09-13T15:36:44.383 回答
0

您可以首先创建一个仅包含有效索引的序列,然后迭代它们的组合:

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();

}
于 2010-09-13T18:21:28.387 回答