java - Minimax 算法逻辑输出意想不到的结果

标签 java chess 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;
}

最佳答案

事实证明,这个错误不是逻辑问题,而是我的方法问题,即使在我声明“我确信其他方法可以完美工作”之后也是如此。事实证明,问题是由于验证棋子移动造成的。

在国际象棋中,有一条模糊的“en passant”规则,即刚刚向前移动两格的棋子与刚刚向前移动两格的棋子的行为不同。出于这个原因,我为这些棋子创建了一个类,并在常规移动结束时用常规 pawn 替换了它们的实例,但是由于这些测试移动不是常规移动,因此它没有删除 movingTwoPawn,并认为它无法移动,因为在常规游戏中 movingTwoPawn 永远无法移动。

为了解决这个问题,我添加了用常规 Pawn 替换 movingTwoPawns,效果非常好。

关于java - Minimax 算法逻辑输出意想不到的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55563489/

相关文章:

python - 如何让 minimax 算法返回实际移动?

java - 如何在java中使用while循环反转字符串?

java - JVM 会乱序执行字节码吗?

java - 如何设置网站上下文路径

java - <Java> 国际象棋棋子移动问题

java - 通过引用传递会毁掉一切 :(

lisp - 用 lisp 实现的井字游戏是完成游戏而不是一步一步

java - Jogl 中的 ReadPixel

C++ - 有没有办法只继承一些函数一次,而其他函数在多重继承中多次继承?

python - 从 Python 上的 pgn 文件中提取移动信息