Minimax算法逻辑输出意外结果

时间:2019-04-07 20:40:30

标签: java chess minimax

我正在为一个简单的国际象棋引擎制作minimax算法,但是遇到了一些困难。我已经运行了几个小时的代码,但无济于事,它似乎仍然输出错误的结果;当我威胁它的一个碎片并且它具有可以保存该碎片的有效举动时,它会忽略此举。

下面,我尽可能简化了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()在显示玩家可以做出的所有动作时是正确的,computeScore()就是正确的计算片段的实例,并根据片段的颜色总计分数。 (如果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;
}

1 个答案:

答案 0 :(得分:0)

事实证明,即使我发表了“我确信其他方法都能正常工作”的声明,该错误也不是逻辑问题,而是我的方法问题。事实证明,问题出在验证移动的零件。

在国际象棋中,有一个模糊的“过客”规则,即刚刚向前移动的棋子向前移动两个动作,而不仅仅是向前移动的棋子向前移动两个格。出于这个原因,我为这些零件创建了一个类,并在常规移动的末尾用常规棋子替换了它们的实例,但是由于这些测试移动不是常规移动,因此它没有删除movetwoTwoPawn,并认为它不能移动,就像常规播放中的moveTwoPawn一样,永远也不会移动。

为解决此问题,我添加了用常规Pawns替换movedTwoPawns的方法,并且效果很好。