【问题标题】:Minimax algorithm logic outputting unexpected resultsMinimax 算法逻辑输出意外结果
【发布时间】: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(),但我会添加它以减少混淆

标签: java chess minimax


【解决方案1】:

事实证明,这个错误不是逻辑问题,而是我的方法有问题,即使在我声明“我确信其他方法可以完美运行”之后也是如此。事实证明,问题是由于验证了移动的部分。

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

为了解决这个问题,我添加了将movedTwoPawns替换为常规Pawns,并且效果很好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-03
    • 2017-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多