我正在使用minimax编写一个带有alpha-beta修剪的奥赛罗引擎。 它工作正常,但我发现了以下问题:
当算法发现某个位置丢失时,它会按预期返回-INFINITY,但是 这种情况我无法追踪'最佳'移动......位置已经丢失,但它应该返回一个有效的移动(最好是一个存活时间更长的移动,就像好的国际象棋引擎那样)。
以下是代码:
private float minimax(OthelloBoard board, OthelloMove best, float alpha, float beta, int depth)
{
OthelloMove garbage = new OthelloMove();
int currentPlayer = board.getCurrentPlayer();
if (board.checkEnd())
{
int bd = board.countDiscs(OthelloBoard.BLACK);
int wd = board.countDiscs(OthelloBoard.WHITE);
if ((bd > wd) && currentPlayer == OthelloBoard.BLACK)
return INFINITY;
else if ((bd < wd) && currentPlayer == OthelloBoard.BLACK)
return -INFINITY;
else if ((bd > wd) && currentPlayer == OthelloBoard.WHITE)
return -INFINITY;
else if ((bd < wd) && currentPlayer == OthelloBoard.WHITE)
return INFINITY;
else
return 0.0f;
}
//search until the end? (true during end game phase)
if (!solveTillEnd )
{
if (depth == maxDepth)
return OthelloHeuristics.eval(currentPlayer, board);
}
ArrayList<OthelloMove> moves = board.getAllMoves(currentPlayer);
for (OthelloMove mv : moves)
{
board.makeMove(mv);
float score = - minimax(board, garbage, -beta, -alpha, depth + 1);
board.undoMove(mv);
if(score > alpha)
{
//Set Best move here
alpha = score;
best.setFlipSquares(mv.getFlipSquares());
best.setIdx(mv.getIdx());
best.setPlayer(mv.getPlayer());
}
if (alpha >= beta)
break;
}
return alpha;
}
我用它来打电话:
AI ai = new AI(board, maxDepth, solveTillEnd);
//create empty (invalid) move to hold best move
OthelloMove bestMove = new OthelloMove();
ai.bestFound = bestMove;
ai.minimax(board, bestMove, -INFINITY, INFINITY, 0);
//dipatch a Thread
new Thread(ai).start();
//wait for thread to finish
OthelloMove best = ai.bestFound();
当一个失去的位置(想象它之后丢失10次,例如)被搜索时,上面的最佳变量等于作为参数传递的空无效移动...为什么??
感谢您的帮助!
答案 0 :(得分:3)
您的问题是您使用-INFINITY和+ INFINITY作为赢/输分数。您的赢/输分数应高于/低于任何其他位置评估分数,但不等于您的无穷大值。这将保证即使在无可救药地失去的位置也会选择一个移动。
答案 1 :(得分:2)
我实施minimax已经很长时间了,所以我可能错了,但在我看来,如果遇到输赢的动作,你的代码不会更新最佳变量(这种情况发生在(电路板上)。方法顶部的checkEnd())语句。
另外,如果您希望算法尽可能地尝试获胜,或者如果无法获胜则尽可能少地输掉,我建议您更新您的评估功能。在胜利的情况下,它应该返回一个大的值(大于任何非赢的情况),你越多赢得了laregr值。在失败的情况下,它应该返回一个很大的负值(小于任何非损失情况),你输的越多,价值越小。
在我看来(没有尝试),如果你以这种方式更新你的eval函数并完全跳过检查if(board.checkEnd()),你的算法应该正常工作(除非它有其他问题)。祝你好运!
答案 2 :(得分:0)
如果你能够发现一个位置真正赢了或输了,那就意味着你正在解决最后阶段。在这种情况下,您的评估函数应该返回游戏的最终得分(例如,总胜利为64,窄幅损失为31),因为这可以准确计算,与您在中期评估的估计不同。 / p>