【发布时间】:2019-04-07 20:40:30
【问题描述】:
我正在为一个简单的国际象棋引擎制作一个极小极大算法,但是遇到了一些困难。我已经运行了几个小时的代码,但无济于事,它似乎仍然输出错误的结果;当我威胁它的一个棋子并且它有一个可以保存棋子的有效动作时,它会忽略该动作。
下面,我已经尽可能简化了 minimax 算法方法的代码,以尝试展示我试图实现的目标,并希望让错误可见。它最初是用 minimax(2,true); 调用的;
public static int[] minimax(int depth, boolean max) {
int piece = 0;
int square = 0;
int boardScore = 0;
int bestScore = -9999;
if (!max) {
bestScore = 9999;
}
for (int a = 0; a < 64; a++) {
for (int b = 0; b < 64; b++) {
boardScore = 0;
boolean valid = false;
if (max) {
valid = Board[a].validate(b, aiColor);
} else {
valid = Board[a].validate(b, playerColor);
}
if (valid) {
storePosition(depth-1);
if (max) {
Board[a].move(b,aiColor);
} else {
Board[a].move(b,playerColor);
}
boardScore = calculateScore();
if (depth != 1) {
if (max) {
int[] minimaxArray = minimax(depth-1, false);
boardScore = minimaxArray[2];
} else {
int[] minimaxArray = minimax(depth-1, true);
boardScore = minimaxArray[2];
}
}
if (boardScore > bestScore && max) {
piece = a;
square = b;
bestScore = boardScore;
}
if (boardScore < bestScore && !max) {
piece = a;
square = b;
bestScore = boardScore;
}
resetPosition(depth-1);
}
}
}
int[] returnVars = new int[3];
returnVars[0] = piece;
returnVars[1] = square;
returnVars[2] = bestScore;
return returnVars;
}
我确信其他方法可以完美运行,因为 move() 只是改变了棋子,validate() 是正确的,因为它显示了玩家可以进行的所有移动,calculateScore() 是正确的,因为它只是计算碎片的实例并根据它们的颜色总计分数。 (如果ai是前面的马,则得分为3;如果玩家是前面的棋子,则得分为-1)。
该程序似乎仍然没有遵循我希望它遵循的逻辑,并且在受到威胁时不会将其碎片移开。例如,我移动了一个棋子以便它可以带走机器人的马,但它未能将马移开。
这是它错误的一个例子,让我相信我的逻辑在计算最佳移动/它的递归执行不正确时存在问题,但它可能是 calculateScore(),所以我也会添加它。
public static int calculateScore() {
int boardScore = 0;
for (int c = 0; c < 64; c++) {
if (Board[c].color.equals(aiColor)) {
boardScore += Board[c].points;
} else {
boardScore -= Board[c].points;
}
}
return boardScore;
}
【问题讨论】:
-
您似乎正在更改
Board,而不是对其进行复制或回滚。 -
在 resetPosition(depth-1) 中,它将棋盘重置回移动之前的状态。它“撤消”了为测试其值而进行的移动,以继续到算法的下一个深度。为了尝试简化代码,我删除了 storePosition(depth-1) 方法,因为我看到其他人只是使用 game.undo(),但我会添加它以减少混淆