[英]Why is my Minimax algorithm for chess taking so long to evaluate a move?
我正在尝试在 C# 中创建一个简单的国际象棋 AI,到目前为止,使用带有 alpha-beta 修剪的极小极大算法在一定程度上取得了成功。 但是,使用下面的代码,它实际上需要大约 5 秒的时间来评估深度 3 的移动,如果可能的话,我希望它更快。 我已经对它进行了几个小时的修补,我对它所做的任何更改似乎都会破坏 ai。 任何帮助是极大的赞赏!
private void makeAIMove(Piece[,] board)
{
Move bestMove;
int score;
List<Piece[,]> possiblePositions = getAllPossiblePositions(board, Team.Black);
List<Move> possibleMoves = getAllPossibleMoves(board, Team.Black);
bestMove = possibleMoves[0];
score = evaluatePosition(possiblePositions[0], int.MinValue, int.MaxValue, DEPTH, Team.White);
if (numTurns > 0)
{
for (int i = 1; i < possiblePositions.Count; i++)
{
int pos = evaluatePosition(possiblePositions[i], int.MinValue, int.MaxValue, DEPTH, Team.White);
if (pos >= score)
{
bestMove = possibleMoves[i];
score = pos;
}
}
}
else
{
bestMove = possibleMoves[Random.Range(0, possibleMoves.Count)];
}
numTurns += 1;
updateBoard(bestMove);
}
private int evaluatePosition(Piece[,] board1, int alpha, int beta, int depth, int team)
{
Piece[,] board = (Piece[,])board1.Clone();
if (depth == 0)
{
return evaluate(board);
}
if (team == Team.White)
{
List<Move> moves = getAllPossibleMoves(board, team);
int newBeta = beta;
foreach (Move moveName in moves)
{
fastMove(board, board[moveName.start.y, moveName.start.x], moveName);
newBeta = Mathf.Min(newBeta, evaluatePosition(board, alpha, beta, depth - 1, oppositeTeam(team)));
if (newBeta <= alpha) break;
}
return newBeta;
}
else
{
List<Move> moves = getAllPossibleMoves(board, team);
int newAlpha = alpha;
foreach (Move moveName in moves)
{
fastMove(board, board[moveName.start.y, moveName.start.x], moveName);
newAlpha = Mathf.Max(newAlpha, evaluatePosition(board, alpha, beta, depth - 1, oppositeTeam(team)));
if (beta <= newAlpha) break;
}
return newAlpha;
}
}
很难确切地说出原因,因为我们没有看到您的全部代码,但这里有一些关于从哪里开始寻找的建议:
您的移动生成代码可能很慢。 尝试对某些位置进行性能测试,看看你得到了多少个节点。 如果你有一个写得很好的代码,它应该是数百万。
您的评估可能很慢。 尝试先做一个简单的评估,您只计算每一面的材料。
奇怪的是你有“if team == Team.White”。 这是否意味着你总是有 AI 来扮演黑人? 在伪代码中使用 as 而不是 alpha/beta,在 if 语句中使用最大化播放器。
您在最小化播放器循环(第一个 if 语句)中设置 newBeta = beta。 在这里你应该设置 newBeta = someLargeValue。 else 语句中的 alpha 也是如此。 另外,我认为在这两种情况下都使用术语分数会更好,以使其更清楚。
您忘记设置新的 alpha 和 beta 值。 在第一种情况下,它应该是这样的:
newBeta = Mathf.Min(newBeta, evaluatePosition(board, alpha, beta, depth - 1, oppositeTeam(team))); if (newBeta <= alpha) break; beta = Mathf.Min(beta, newBeta);
请查看伪代码并尝试尽可能接近地实现,这将使它更简单: https://en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning 。 还可以考虑改为使用 Negamax,这将进一步简化逻辑: https://en.wikipedia.org/wiki/Negamax 。 这是进一步优化的必要条件。
当你让一切都按预期工作时,你可以开始做其他事情来提高性能,例如移动顺序和不同的修剪技术。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.