0

Javaでボードゲーム「囲碁」を再現しようとしています。私は現在、キャプチャシステムに取り組んでいます。基本的に、石が 4 つの側面すべて (対角線はカウントされません) で敵の石に囲まれたら、その石を取り除きます。下のスクリーンショットのように。

ここに画像の説明を入力

または、複数の同じ石が接続されている場合は、すべての開いた側面を囲む必要があります。下のスクリーンショットのように。

ここに画像の説明を入力

どちらの場合も、この時点で黒い石を取り除く必要があります。このリンクでは、石をキャプチャするルールについて詳しく説明しています。社会.cam。交流。イギリス /cugos/go/rules_03.html

これを行うには再帰を使用するのが最善だと言われました。再帰に関する調査を行った後、コードを書くことができました。しかし、それは機能していません。ゲームの2手目で敵の石を検出するだけのようです。mouseReleased に石が置かれるたびにメソッドを呼び出します。

public static boolean checkCapture(int x, int y)
{
    {
        if ((board[x][y + 1] != move) && (board[x][y + 1] != 0)) //bellow
        {
            System.out.println("enemy is bellow");
            if (checkCapture(x, y + 1))
                board[x][y] = 0;
        } else if (board[x][y + 1] == 0)
        {
            return false;
        }

        if ((board[x][y - 1] != move) && (board[x][y - 1] != 0)) //above
        {
            System.out.println("enemy is above");
            if (checkCapture(x, y - 1))
                board[x][y] = 0;
        } else if (board[x][y - 1] == 0)
        {
            return false;
        }

        if ((board[x + 1][y] != move) && (board[x + 1][y] != 0)) // right
        {
            System.out.println("enemy is right");
            if (checkCapture(x + 1, y))
                board[x][y] = 0;
        } else if (board[x + 1][y] == 0)
        {
            return false;
        }

        if ((board[x - 1][y] != move) && (board[x - 1][y] != 0)) //left
        {
            System.out.println("enemy is left");
            if (checkCapture(x - 1, y))
                board[x][y] = 0;
        } else if (board[x - 1][y] == 0)
        {
            return false;
        }
    }
    return true;
}

私の int x は私の列で、私の int y は私の行です。 move は、誰の番かを保持する変数です (1 = 黒 , 2 = 白) board は、ボード上のすべての石の位置を保持する 2 次元配列です。

4

4 に答える 4

1

まず、関数が何をするかを明確にすることから始めます。

/**
 *  Checks to see if the grid point passed in is captured.
 *  @param...(you should say what your params are here
 **/
public static boolean checkCapture(int x, int y) {
   //some code
}

これは重要です。この関数が、グリッド ポイントが他の任意のポイントをキャプチャしているかどうかをチェックするとどうなるでしょうか? さらに、問題がすぐにわかります...誰によってキャプチャされましたか? 再帰的な問題を解決するときはいつでも、基本的なケースを理解する必要があります。ここでは、敵が占めていない垂直または水平の隣接エリアがないということです。

したがって、特定の色に関して確認する必要があります。

/**
 *  Checks to see if the grid point passed in is captured.
 *  @param...(you should say what your params are here
 **/
public static boolean checkCapture(int x, int y) {
   if (!isOccupied(x,y)) {//writing this function should be trivial
     return false;//can't be captured; no one is there!
   }

   Color color = getColor(x,y);//similarly, get the color of whoever is there.
   Status status = checkFlanked(x, y, color);
   if (status = Status.FLANKED) {
     return true;
   }
}

private static Status checkFlanked(int x, int y, Color color) {
   //check to see that this location is valid for the board
   //check to see if this square is occupied at all
     //if it is not, return LIBERTY (an empty space means no capture, right?)
     //if it is, is it occupied by the opposite color? --> Return a FLANKED result!
     //if it is, is it occupied by the same color? --> recurse!
}

ここで、問題を少し分解しました。また、基本ケースがどのように解決されるかは簡単にわかります。正方形が占有されていない場合、隣接することはできません...したがって、LIBERTY結果が返されます。それが反対の色で占有されている場合、この正方形は最初にチェックしていた人に隣接しています. 唯一難しいのは、これが元の色で占められている場合に、他の場所に自由があるかどうかを確認することです。

 //get all valid adjacent locations
 //call checkFlanked on those locations.
 //If any return LIBERTY, return LIBERTY. Otherwise return FLANKED.

(注:私は、明確にするために列挙型として定義されていると想定LIBERTYしています。)FLANKED

これが、より賢明な方法で問題を解決するのに役立つことを願っています。覚えておいてください: 再帰を使用している場合、基本ケースと「+1 反復」ケースの 2 つのケースに注意してください。上記の場合でも、いくつかの問題を解決する必要があることに注意してください。

  • すでに訪れたマス目には賢く再帰しないようにする必要があります。(末尾再帰を調べますが、既にチェックされている正方形を示す追加の状態を渡すこともできます。)
  • ボードから落ちないようにし、落ちた場合は適切な結果を返す必要があります。基本的に、「有効な場所とは?」を解決する必要があります。問題。

その他の興味深い質問は次のとおりです。

  • 幅で検索しますか、それとも深さで検索しますか?
  • これは静的メソッドとして適切ですか、それともクラスでキャプチャする必要がありますか?
于 2013-06-12T00:14:52.333 に答える
-3

この場合の再帰の問題は、無限ループに陥りやすいことです。2つの石をチェックし、右の石をチェックすると左の石が再び右の石をチェックするなど、すでにチェックした石を追跡する必要があります。すでにチェックした石の状態を渡す必要があります。

于 2013-06-12T00:17:29.140 に答える