我目前对自己编写的AI不满意。这个AI应该在3×3的棋盘(井字游戏)中为每一步选择最佳得分。
可能的得分有-1(输),0(平局)和1(赢)。
首先调用makeTurn()
方法,然后该方法会调用包含miniMax算法的方法。
public void makeTurn(Button[][] currentBoard) { // 使用miniMax算法计算最佳移动
AIcheck = new Check(currentBoard);
int bestScore = Integer.MIN_VALUE;
int[] bestMove = new int[2];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (currentBoard[i][j].getText().equals("")) {
currentBoard[i][j].setText("O");
int score = calcScore(currentBoard, 0, false);
System.out.println(score);
currentBoard[i][j].setText("");
if (score > bestScore) {
bestScore = score;
bestMove = new int[]{i, j};
}
}
}
}
Board.getInstance().getField(bestMove[0], bestMove[1]).performClick();
}
private int calcScore(Button[][] currentBoard, int depth, boolean isMax) { // MiniMax算法,通过递归执行计算每个分支的得分
int score;
if (AIcheck.checkWin()) {
return (Util.getInstance().getTurnCounter() % 2) == 0 ? 1 : -1;
} else if (AIcheck.checkTie()) {
return 0;
}
int bestScore = isMax ? Integer.MIN_VALUE : Integer.MAX_VALUE;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (currentBoard[i][j].getText().equals("")) {
if (isMax) {
currentBoard[i][j].setText("O");
} else {
currentBoard[i][j].setText("X");
}
score = calcScore(currentBoard, depth + 1, !isMax);
currentBoard[i][j].setText("");
bestScore = isMax ? Math.max(bestScore, score) : Math.min(bestScore, score);
}
}
}
return bestScore;
}
我使用isMax
来判断是否是最大化者的回合,同时使用turnCounter % 2
来判断轮到哪个玩家,因为他们轮流进行游戏。
然而,AI仍然无法阻止我获胜,它似乎只是从一个位置移动到下一个位置,而不是选择最佳位置。我该如何正确实现miniMax算法?非常感谢!
示例:
[]|[]|[]
[]|[]|[]
[X]|[]|[]
[O]|[]|[]
[]|[]|[]
[X]|[]|[]
[O]|[]|[]
[]|[]|[]
[X]|[]|[X]
[O]|[O]|[]
[]|[]|[]
[X]|[]|[X]
[O]|[O]|[X]
[]|[]|[]
[X]|[]|[X]
[O]|[O]|[X]
[O]|[]|[]
[X]|[]|[X]
[O]|[O]|[X]
[O]|[X]|[] 我赢了,这也显示了AI似乎只是选择下一个位置(从左到右)
[X]|[]|[X]
回答:
我认为问题出在calcScore
中如何判断谁赢了。你使用了Util.getInstance().getTurnCounter()
,但在递归调用中似乎没有更新计数器。你可以改用depth % 2
或isMax
来代替:
if (AIcheck.checkWin()) { return isMax ? -1 : 1;}