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

問題は、前の値と次の値(-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

配列は 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

有効なインデックスのみのシーケンスを作成することから始めて、それらの組み合わせを繰り返すことができます。

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 に答える