2

私が書いているプログラムは、2次元配列にデータを入力して勝利条件を確認するという原則に基づいて動作します。これはゼロとクロスであるため、ボタンをクリックすると2次元配列にデータが入力されます。円の場合は1、円の場合は2です。 cross の場合、checkWin() は実際のコードではなく、この原則に基づいて機能します...

if (myArray[0][0] == 1 && myArray[0][1] == 1 && myArray[0][2] == 1){
    setBoolWinVal = true;
} else {
    if(myArray[0][0] == 2 && myArray[0][1] == 2 && myArray[0][2] == 2){
    setBoolWinVal = true;
}

勝利条件ごとにこれが面倒なことはすぐにわかります。この勝利チェックを書き直して少し短くする方法はありますか?

4

12 に答える 12

7

これは宿題のようですので、完全には手放しません。ただし、いくつかのことに注意してください。

  • 同じものが縦、横、または斜めに 3 つ揃うと勝ちです。

  • 一列に 3 つのゼロまたは 3 つのクロスがあるかどうかをチェックする必要があるということではなく、同じものが 3 つ一列に並んでいるということです。

行、列、または対角線に 3 つの同じ種類のものがあるかどうかを判断する関数を作成することから始めることができます (そして、それは空白のセルではありません)。次に、その関数を行、列、および対角線ごとに 1 回呼び出します。

于 2009-03-18T22:33:40.950 に答える
3

これが(テストされていない)コードです。それは確かに生産品質ではありません:)

他の回答からの最適化のいくつかに注意してください。

  1. forループの使用
  2. 特定のプレーヤーの値ではなく、等しいプレーヤーの値をチェックします
  3. 斜めの勝利はセルを通過する必要があります[1][1]

int find_winner(int[][] arr) {

    // check rows
    for (int i = 0; i < 3; ++i) {
        int player = arr[i][0];
        if (player < 1) continue; // nb: prior version didn't check for empty cells
        if (arr[i][1] == player && arr[i][2] == player) return player;
    }

    // check cols
    for (int i = 0; i < 3; ++i) {
        int player = arr[0][i];
        if (player < 1) continue;
        if (arr[1][i] == player && arr[2][i] == player) return player;
    }

    // check diagonals
    int player = arr[1][1];
    if (player < 1) return -1;

    if ((arr[0][0] == player && arr[2][2] == player) ||
        (arr[2][0] == player && arr[0][2] == player)) return player;

    // no winner found
    return -1;
}
于 2009-03-18T22:43:47.573 に答える
2

明らかな方法は、行、列、または対角線の3つの要素をループして、それらが同じであることを確認することです。

もう1つの方法は、よりコンパクトな表現を使用することです。たとえば、intは、9つのセルがそれぞれ2ビット、または各プレーヤーに1つずつの2つのショートで表されます。次に、ルックアップテーブルまたはビット演算を使用して、勝ち負けの状態をマップします。

1つのビットがセルを表し、1つのパディングビットがある場合、各プレーヤーのタイルは3桁の16進数の0〜7です。

対角線は次のとおりです。

cells & 0x421 == 0x421
cells & 0x124 == 0x124

縦線は次のとおりです。

cells & (cells>>4) & (cells>>8) != 0

水平線

cells & (cells>>1) & (cells>>2) != 0

チェスゲームで可能な動きを表すために、64ビットパターンを使用して同様の手法が使用されます。

于 2009-03-18T22:43:40.567 に答える
1

あなたのための2つの面白いアイデア:(私はそれが人生を楽にするので基礎となる1D配列を仮定します。)

最初に:テストする位置をエンコードします。フィールドを記述する1D配列がある場合のように:

diag[] = { { 0, 1, 2}, {3, 4, 5}, {6, 7, 8},
           { 0, 3, 6}, {1, 4, 7}, {2, 5, 8},
           { 0, 4, 8}, {6, 4, 2}};

次に、diagをループします。そのすべての要素について、対応する3つのフィールドをテストします(diag[i]フィールド配列のインデックスとして使用します)。

2番目:ビットフィールドを使用してフィールドを表します。java.util.BitSetのように。次に、ソリューションを{1、1、1、0、0、0、0、0、0}、{0、0、0、1、1、1、0、0、0}などのビットフィールドにエンコードします。次に、次の場合にテスト(ループオーバー)でき(field & solution[i] == solution[i])ます。2番目のプレーヤー!fieldの場合は、ifステートメントで使用します。

楽しいですね。ps:これから動作するJavaコードを作成するのはあなた次第です!

于 2009-03-18T22:45:19.800 に答える
0

宿題のにおい。

小さなヒント-forループを使用すると、任意のサイズで機能します。代わりに再帰を使用するとボーナスポイントが得られます。

定義:再帰->再帰を参照

于 2009-03-18T22:36:43.080 に答える
0

したがって、それについて考えると、次のような条件をチェックしています。

www   xxx   xxx  wxx
xxx   www   xxx  xwx
xxx   xxx   www  xxw

ここで、wは勝利をチェックするものであり、xは無視するものです。

(0,0)、(0,1)、(0,2)は、最初の正しい解の「w」の位置です。1,0、1、1、1、2は2番目などです。

これは、コードではなくデータである必要があるように私には見えます。秘訣は、データをどのように効率的に入力および保存するかです。

このデータは配列インデックスのように見え始めていることに注意してください。

それで、8つのx、yペアを含む「ソリューション」の配列があったとしましょう(それぞれが勝利のソリューションの組み合わせを示します)

次に、このコレクションを繰り返し処理し、3つのx、yペアを抽出して、それらをテストするだけです。したがって、それはあなたが持っているものと似ていますが、あなたが数字を持っているところで変数を使用してください。

if(myArray[x0][y0] == 2 && myArray[x1][y1] == 2 && myArray[x2][y2] == 2){
    win();

繰り返し処理すると、インデックス変数はデータの次の行に置き換えられます。

勝った後に損失を報告したくないので、ループが停止することを確認するためにロジックを少し試してみる必要がありますが、これはおそらく宿題スタイルの問題にはすでにあまりにも多くの助けになります。

于 2009-03-18T22:52:34.367 に答える
0

これは本当に宿題のように聞こえますが、行と列を調べて、それらがすべていっぱいになっているかどうかを確認するという簡単な質問を手伝います。対角線は少し難しいので、あなたに任せます。繰り返しますが、ネストされた for ループが最良のアイデアになると思います。

java.util.Arrays;

public yourClass{

public void findAnswer{

int initialVal = 0;

int copy = 0;

int column = 0;

boolean columnVal = true;

boolean rowVal = false;

for (int j = 0; j< myArray.length; j++){ //presuming myArray and myArray[] are same length

boolean firstRun = true;

    for (int i = 0; i <myArray.length; i++){

        initialVal = myArray[i][column];
        if (firstRun == true){
            copy = intialVal; //makes a copy for the first time, to compare
            firstRun = false;
        }
        if (intialVal != copy){
            columnVal = false; //realises this column isnt a full column i.e. 3 1's or 2's in column
            return;
        }else
            columnVal = true;

        }//end nested for loop

    rowVal = findRow(j); 
    if(rowVal = true)
    return;
}

public boolean findRow(int row){

    int[] tempRow1, tempRow2;
    Arrays.fill(tempRow1, 1); 
    Arrays.fill(tempRow2, 2); //fills temp arrays for comparison
    boolean answer = false;
    if (Arrays.equals(myArray[], tempRow1) || Arrays.equals(myArray[], tempRow2) //this tests either, || being logical OR
        answer = true;
    return answer;
}
}

nbこのコードはテストされておらず、すぐにコード化されたので、見栄えがよくなく、洗練することができ、対角線も実装していません。ps宿題の場合は、他の人に頼んで助けを求めるのではなく、インターネットで調べて、自分で解決しようとするのがおそらく最善です.

于 2009-03-19T01:41:38.673 に答える
0

これを繰り返し解決することもできます。

  1. 列、行、対角線ごとにマーカーの種類ごとに配列を生成します。ゼロに初期化します。
  2. グリッド内の各エントリについて、マーカーがある場合は、そのマーカーの適切な列、行、および対角線のエントリをインクリメントします。
  3. これらのエントリのいずれかがボードの寸法と等しい場合、そのマーカーが勝ちます。
于 2009-03-19T04:22:46.243 に答える
0

n X n 行列の場合...

//Check all horizontal rows
for(i=0; i<n && !setBoolWinVal; i++) //row
{
    setBoolWinVal = true;
    for(j=0; j<n-1; j++)
    {
        if( myArray[i][j] != myArray[i][j+1] ) //column
        {
            setBoolWinVal = false;
            break;
        }
    }

    if(setBoolWinVal) declareWinner(myArray[i][0]);
}

//Check all vertical columns
if(!setBoolWinVal)
{
    for(i=0; i<n && !setBoolWinVal; i++) //column
    {
        setBoolWinVal = true;
        for(j=0; j<n-1; j++) //row
        {
            if( myArray[j][i] != myArray[j+1][i] ) 
            {
                setBoolWinVal = false;
                break;
            }
        }
    }

    if(setBoolWinVal) declareWinner(myArray[0][i]);
}


//Check forward diagonal
if(!setBoolWinVal)
{
    setBoolWinVal = true;
    for(i=0; i<n-1; i++)
    {
        if( myArray[i][i] != myArray[i+1][i+1])
        {
            setBoolWinVal = false;
            break;
        }
    }

    if(setBoolWinVal) declareWinner(myArray[0][0]);
}

//Check reverse diagonal
if(!setBoolWinVal)
{
    setBoolWinVal = true;
    for(i=0, j=n-1; i<n-1 && j>0; i++, j--)
    {
        if( myArray[i][j] != myArray[i+1][j-1])
        {
            setBoolWinVal = false;
            break;
        }
    }

    if(setBoolWinVal) declareWinner(myArray[0][n-1]);
}
于 2009-03-19T03:46:49.607 に答える
0

シンプルかつ洗練されたソリューション - 次の方法で 1 から 9 までの数字をボードに割り当てます。

8 1 6
3 5 7
4 9 2

この正方形には、すべての行、列、および対角線の合計が 15 になるという固有の特性があり 、行、列、または対角線を共有しない限り、3 つのセルから合計 15 を取得する方法はありません。

プレイヤーごとに、2 つのブール配列を保持します。

boolean squarePairs[PAIRSMAXSUM+1];
boolean chosenSquares[NUMSQUARES+1];

PAIRSMAXSUM = 9+8 および NUMSQUARES = 9

次に、この関数を呼び出すことで、勝利の動きを簡単に確認できます。

boolean hasWon(int squareIndex) {
    return squarePairs[WINNINGSUM - squareIndex];
}

ここで、WINNINGSUM は 15 です。その関数が false を返す場合は、次の関数を呼び出してブール配列を更新します。

void update(int squareIndex) {
    for (int i = 1; i <= NUMSQUARES; i++) {
        if (chosenSquares[i]) {     {
            squarePairs[i + squareIndex] = true;
        }
    }
    chosenSquares[squareIndex] = true;
}


そのような単純な!

于 2009-03-19T04:35:43.233 に答える
0
  1. ボードを 0..19683 (3 から 9 まで) の int として表す
  2. 勝利ボードを事前に生成し、各ボードの勝者をおそらく手動で特定する
  3. 実行時に、事前に計算されたマップで現在のボードを探します
于 2009-03-19T02:11:23.050 に答える
-1

配列がすべて同じ長さである場合は、次のことが役立つはずです。

Arrays.equals(myArray[0], {1,1,1})

それ以外の場合は、のすべての値をループする関数を記述しますmyArray[0]

于 2009-03-18T22:39:15.773 に答える