0

2 つの for ループがあり、1 つは別のループにネストされています。ボタンの 2D 配列をループして、アクション リスナーを使用してクリックされた各ボタンのソースを取得します。

ボタンが見つかったら、ボタンの位置/配列インデックスを外部メソッドに渡します。ただし、ボタンの配列からボタンが見つかった場合、最初の for ループはその終了条件を FALSE と評価しますが、i の値をインクリメントします。1エラーでオフにつながります。私のコードは、「イベント」が ActionEvent である標準アクション実行メソッドにあります。buttons[][] は、インスタンス変数として定義された JButton 配列です。サイズは 10 x 10 で、既にパネルに追加されています。

int i = 0; //this will loop through the columns in the array
int j  = 0; //loop through the rows
boolean locatedSource = false; //allows me to escape both loops

for(i = 0; !(locatedSource) && i < buttons.length; i++) //problem here, when i < buttons.length is FALSE i still gets incremented, leading to an off by one error
{
  for(j = 0; !(locatedSource) && j < buttons.length; j++)
  {
    if(event.getSource() == buttons[i][j])
    {
      locatedSource = true;
      break;
    }
  }
}
//do stuff with i and j in another method. Leads to array out of bounds error / off by one error
}

私は、ラベルを使用してこの問題を解決しようとしているわけではありません。彼らは落胆しているようです。

4

4 に答える 4

1

ブール値フラグを使用して内側のループに設定し、外側のループの先頭でチェックします。

コードは次のとおりです。

    boolean found = false;
    for (i = 0; i < 10; i++) // problem here, when i < buttons.length is FALSE i still gets
                             // incremented, leading to an off by one error
    {
        if (found) {
            i--;
            break;
        }
        for (j = 0; j < 5; j++) {
            if (i == 5 && j == 3) {
                found = true;
                break;
            }
        }
        //if (found) {               
        //    break;
        //}
    }
于 2014-03-09T15:31:16.680 に答える
1

考えられる解決策は次の 3 つです。

  1. for「見つかった」インデックスを明示的に設定し、ループ インデックスを再利用しないでください。
  2. return独自のメソッドでループから直接検索を因数分解します。
  3. iループが終了したら、1ずつ減らします。
于 2014-03-09T15:31:22.947 に答える
1

あなたのコードには、「ここで問題があります.i <buttons.lengthがFALSEの場合、私はまだインクリメントされ、1つのエラーでオフになります」というコメントが含まれていますが、これはイベントの順序が間違っています.

まず、サイクル更新ブロックが実行されi++)ます (その後、条件がチェックされます (`i < buttons.length' など))。

つまりi == buttons.length、条件をトリガーせずにサイクルが終了した後の正しい状態locatedSourceです。

于 2014-03-09T15:53:25.363 に答える
1

問題の説明

for ループのインクリメント式は、各ループ反復の前ではなく後に実行されます。Oracle Java チュートリアルからの次の引用を参照してください。

for ステートメントは、値の範囲を反復処理するためのコンパクトな方法を提供します。プログラマーは、特定の条件が満たされるまで繰り返しループする方法から、これを「for ループ」と呼ぶことがよくあります。for ステートメントの一般的な形式は、次のように表すことができます。

for (initialization; termination;
     increment) {
    statement(s)
}

When using this version of the for statement, keep in mind that:

  1. The initialization expression initializes the loop; it's executed once, as the loop begins.
  2. When the termination expression evaluates to false, the loop terminates.
  3. The increment expression is invoked after each iteration through the loop; it is perfectly acceptable for this expression to increment or decrement a value.

For loop solution

You can re-write your loop so that the increment is the first statement inside the loop.

    for (i = 0; !(locatedSource) && i < buttons.length;) {
        i++;
        for (j = 0; !(locatedSource) && j < buttons.length;) {
            j++;
            if (event.getSource() == buttons[i][j]) {
                locatedSource = true;
            }
        }
    }

While Loop Version

Given that the loop variables are both initialised outside of the loop and you don't want to use a for-loop increment expression it might be clearer to rewrite the code to use while-loops as follows:

    while (!(locatedSource) && i < buttons.length) {
        i++;
        while (!(locatedSource) && j < buttons.length) {
            j++;
            if (event.getSource() == buttons[i][j]) {
                locatedSource = true;
            }
        }
    }
于 2014-03-09T15:59:50.157 に答える