[英]miniMax algorithm in Java
我目前对我正在编程的 AI 不满意。 AI 应该在 3x3 棋盘 (TicTacToe) 中的每一步都获得最高分。
可能的分数是 -1(输)、0(平)和 1(赢)。
首先调用方法makeTurn()
,然后调用包含 miniMax 算法的方法。
public void makeTurn(Button[][] currentBoard) { // Calculating best move using miniMax algorithm
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 Algorithm, calculating score for each branch via recursive execution
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
来确定轮到哪个玩家,因为他们轮流。
然而,人工智能并没有阻止我的胜利,它更像是从一个领域到下一个领域,而不是选择最佳领域。 我怎样才能正确实现 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;
}
我认为问题是calcScore()
中的这一行
if (currentBoard[i][j].getText().equals("")) {
如果板子是空的,你只计算分数,但你总是在调用 function 之前将它设置为“0”,所以 if 的代码块永远不会被执行。
makeTurn()
类似,但我猜你是在转弯之间清理木板? 如果不是,您还需要更新它。
编辑:在主要 function 中:
currentBoard[i][j].setText("O");
int score = calcScore(currentBoard, 0, false);
在计算分数中:
// this will always evaluate to false
if (currentBoard[i][j].getText().equals("")) {
您的bestScore作业有问题。 对于每个空框,您都这样做:
int bestScore = isMax ? Integer.MIN_VALUE : Integer.MAX_VALUE;
如果你这样计算,你总是会得到相同的分数,这可能是它只选择下一个空框的原因。 在极小极大算法中,您需要一种方法来为每个动作分配不同的得分值,以便您可以通过比较找到最佳动作。 在国际象棋游戏或类似的游戏中,这些分数通常是通过一些启发式给出的。 由于您的游戏要简单得多,这应该更容易。 一个简单的解决方案可能是为每个板子 state 分配不同的分数,您可以简单地 select 导致此所需 state 的移动。 您可以轻松地做到这一点,因为这些状态的数量在您的游戏中非常有限。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.