私はボード ゲームを持っており、現在 Negamax を使用してポジションを検索する AI を実装しています。新しい検索を開始するときは、ボード オブジェクトをクラスに渡し、そのコピーを作成します。コピーは、クラス内のプライベート変数です。私がこれを行うのは、Java が参照によってオブジェクトを渡さないためです (私が最近学んだように)。
検索クラスには、次の 2 つの関数があります。
NegamaxRoot これがルートです。最初の移動を取得し、移動を実行し、再帰的な negamax 関数 (2) を呼び出してから、移動を元に戻します。
NegamaxRecur この関数は、メインの再帰関数です。ここでは、(同じボード コピーの) 移動を取得し、移動を行い、それ自体を再帰的に呼び出してから移動を元に戻します。
このプロセスは基本的に機能していません。デバッガーをステップスルーするときに、移動/元に戻すときにオブジェクト変数が同期していないことに気付いたからです。
再帰関数でも undo を呼び出す必要がありますか?
これはネガマックスクラスです:
public class Negamax
{
private IBoard board;
public Negamax() {}
public Move NegamaxRoot(IBoard board, int depth)
{
this.board = board.copy();
int alpha = -999999999, beta = 999999999;
int val = 0;
//The move that will be returned
Move bestMove = null;
List<Move> moves = this.board.getMoves();
for (Move move : moves)
{
//IBoard newBoard = board.copy();
//Make the move
this.board.make(move, true);
val = -negamaxRecur(depth - 1, -beta, -alpha);
//Undo the move
this.board.undo(move);
//Keep best move
if (val > alpha)
{
alpha = val;
bestMove = move;
}
}
//Return the move
return bestMove;
}
private int negamaxRecur(int depth, int alpha, int beta)
{
if (depth == 0 || this.board.getWon() != 0)
return this.board.getScore();
int val;
List<Move> moves = this.board.getMoves();
for (Move move : moves)
{
//Make the move
this.board.make(move, true);
val = -negamaxRecur(depth - 1, -beta, -alpha);
this.board.undo(move);
//Alpha-Beta pruning
if (val > alpha)
alpha = val;
if (alpha >= beta)
return alpha;
}
return alpha;
}
}