Javaのチェッカーゲームでalpha-betaプルーニングを使ってminimaxを実装しようとしています。私のミニマックスアルゴリズムは完全に機能します。私のコードは、アルファベットコードで実行されます。残念ながら、私が1000のゲームと標準的なミニマックスのアルゴリズムを比較すると、アルファベットアルゴリズムは常に50ゲーム程度遅れることになります。Java Minimax Alpha-Beta Pruning Recursion Return
アルファベータプルーニングは、ムーブメントの品質を低下させるべきではないため、達成にかかる時間が間違っている必要があります。しかし、私はペンと紙を取り出し、仮説的な葉ノードの値を引いて、アルゴリズムを使って正しい最良の移動を計算するかどうかを予測し、論理エラーはないように見せました。このビデオのツリーを使用して:Alpha-Beta Pruning私のアルゴリズムをトレースします。それは論理的に同じ選択肢のすべてを作るべきであり、したがって機能する実装であるべきです。
私もprintステートメントをコードに入れました(クラッタを減らすために削除されています)、値が正しく返されていて、プルーニングが行われます。私の最善の努力にもかかわらず、私は論理エラーがどこにあるのか見つけることができませんでした。これはこれを実装する私の3番目の試みであり、それらのすべてが同じ問題を抱えています。
ここで完全なコードを投稿することはできません。時間がかかりすぎるため、エラーに関連するメソッドが含まれています。私は確信していませんが、問題はおそらく非再帰的move()メソッドにあると思われますが、論理的なエラーが見つからないので、おそらくそれをもっとスリルして、おそらく韻や理性を持たない方が良いというよりは悪い。
forループで再帰呼び出しから複数の整数値を回復するというトリックはありますか?私のminimaxとnegamaxの両方の実装でうまく動作しますが、アルファベットプルーニングは奇妙な結果を招くようです。
@Override
public GameState move(GameState state)
{
int alpha = -INFINITY;
int beta = INFINITY;
int bestScore = -Integer.MAX_VALUE;
GameTreeNode gameTreeRoot = new GameTreeNode(state);
GameState bestMove = null;
for(GameTreeNode child: gameTreeRoot.getChildren())
{
if(bestMove == null)
{
bestMove = child.getState();
}
alpha = Math.max(alpha, miniMax(child, plyDepth - 1, alpha, beta));
if(alpha > bestScore)
{
bestMove = child.getState();
bestScore = alpha;
}
}
return bestMove;
}
private int miniMax(GameTreeNode currentNode, int depth, int alpha, int beta)
{
if(depth <= 0 || terminalNode(currentNode.getState()))
{
return getHeuristic(currentNode.getState());
}
if(currentNode.getState().getCurrentPlayer().equals(selfColor))
{
for(GameTreeNode child: currentNode.getChildren())
{
alpha = Math.max(alpha, miniMax(child, depth - 1, alpha, beta));
if(alpha >= beta)
{
return beta;
}
}
return alpha;
}
else
{
for(GameTreeNode child: currentNode.getChildren())
{
beta = Math.min(beta, miniMax(child, depth - 1, alpha, beta));
if(alpha >= beta)
{
return alpha;
}
}
return beta;
}
}
//Checks to see if the node is terminal
private boolean terminalNode(GameState state)
{
if(state.getStatus().equals(win) || state.getStatus().equals(lose) || state.getStatus().equals(draw))
{
return true;
}
else
{
return false;
}
}
チェッカーは、あなたがどこかにランダム性を導入していない限り決定的アルゴリズムは、そのすべてのゲームは、同一のプレイアウトする必要がありますされている標準的な開始位置とアルファ・ベータ法との両方のミニマックスとミニマックスを持っています。多分、このランダム性は結果に相違を生み出しています。 –
Minimaxとalpha-betaのminimaxは同じ結果を出すはずですが、alpha-beta pruningだけで結果がやや速くなります。だから、あなたのアルファベットの実装をテストする方法は、大きな位置のセットを使ってミニマックスを実行するかどうかにかかわらず、両方のバージョンで同じ結果が生成されることを確認することです。 –
@Kyle私が実際に実現したのは、私のminimaxアルゴリズムが等価な最良の動きの中からランダムな動きを返すため、私のアルファベータプルーニングアルゴリズムは最初の最良の動きを返すからです。動き)。開始時に、ボードの側への移動はプライ3で同じになりますが、実際には悪くなりますが、アルファベータプルーニングによって考慮される最初のものであるため、戻されます。この場合、最初のものを選ぶよりも、最良の動きの中からランダムな動きを選ぶほうが良いでしょう。助けてくれてありがとう。 – sage88