当前位置: 首页 > 知识库问答 >
问题:

输出意外结果的极小极大算法逻辑

戚宏浚
2023-03-14

我正在为一个简单的国际象棋引擎做一个极大极小算法,但是遇到了一些困难。我已经运行了几个小时的代码,但没有结果,它似乎仍然输出错误的结果;当我威胁它的一个棋子,而它有一个有效的动作可以拯救它时,它会忽略这个动作。

下面,我尽可能简化了极小极大算法方法的代码,以尝试并展示我试图实现的目标,并希望使错误可见。它最初用极小极大(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;
}

我确信其他方法工作得很好,因为移动()只是改变了棋子,验证()是正确的,因为它显示了玩家可以进行的所有移动,计算分数()是正确的,因为它只是计算棋子的实例并根据它们的颜色计算分数。(如果AI是前方的骑士,分数将是3;如果玩家是前方的棋子,分数将是-1)。

然而,该项目似乎仍然没有遵循我希望它遵循的逻辑,并且在受到威胁时不会将其分割开来。例如,我移动了一个兵,这样它就可以带走机器人的骑士,但它没能把骑士移开。

这是它的一个错误的例子,让我相信我的逻辑在计算最佳移动/它的递归是错误的,但是它可能是计算分数(),所以我也会添加它。

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个答案

蓝宜
2023-03-14

事实证明,这个错误不是逻辑上的问题,而是我的方法上的问题,即使在我声明“我确信其他方法工作完美”之后。事实证明,问题是由于验证了碎片的移动。

在国际象棋中,有一条模糊的“顺势”规则,即刚刚向前移动了两个棋子的棋子的行为与不只是向前移动了两个方格的棋子不同。出于这个原因,我为这些棋子开设了一门课,并在常规移动结束时用常规棋子替换了它们的实例,然而,由于这些测试移动不是常规移动,它没有移除移动的棋子,并且认为它不能移动,因为在常规游戏中,移动的棋子永远不能移动。

为了解决这个问题,我添加了移动的TwoPawns替换为普通的Pawns,它工作得很好。

 类似资料:
  • 我想我终于对minimax和Alpha-beta修剪有所了解了,但实现它完全是另一回事! 根据我的理解,基础是:您为某些动作分配一个启发式函数分数(Gomoku为例)。 如果一行有5个,我们应该分配一个高值,比如9999,因为这是一个胜利的举动 当我们必须在Java中实现这一点时,我的问题来了! 我有一块彩色[][]板(8x8),其中黑色是播放器1,白色是播放器2,null表示空白,我不知道我们应

  • 极小极大算法的一个缺点是每个板状态必须被访问两次:一次查找其子级,第二次评估启发式值。 极小极大算法还有其他缺点或优点吗?对于像象棋这样的游戏,还有更好的选择吗?(当然是带有α-β修剪的极小极大算法,但还有其他吗?)

  • 计算机科学中最有趣的事情之一就是编写一个人机博弈的程序。有大量的例子,最出名的是编写一个国际象棋的博弈机器。但不管是什么游戏,程序趋向于遵循一个被称为Minimax算法,伴随着各种各样的子算法在一块。本篇将简要介绍 minimax 算法,并通过实例分析帮助大家更好的理解。 一、概念 Minimax算法又名极小化极大算法,是一种找出失败的最大可能性中的最小值的算法。Minimax算法常用于棋类等由两

  • 我最近实现了极小极大和阿尔法贝塔修剪算法,我100%确定(自动分级器)我正确地实现了它们。但是当我执行我的程序时,它们的行为不同。我99%确定极小极大和阿尔法贝塔的结束状态应该是相同的。我说得对吗?它们在实现结果的路径上会有所不同吗?因为我们忽略了min将选择的一些值,而max不会选择这些值,反之亦然。

  • 我正在为Gomoku(16x16)构建一个具有极大极小值和α-β修剪的AI,但速度非常慢。到目前为止,我已经尝试过对动作顺序进行预排序,而不是深度复制棋盘,添加和删除动作。此外,我还使用了相关移动的arraylist(距离已放置的块的半径在2以内)来减少搜索栏。然而,即使在3的深度搜索中,人工智能仍在苦苦挣扎<编辑:我发现了一个叫做换位表的东西,但我不知道从哪里开始。任何帮助都会很好!

  • 我到处寻找修复代码的答案,但在花了很长时间调试代码后,我发现自己陷入了绝望。问题是,我的minimax函数不会为可能的最佳移动返回正确的值,我甚至试图通过存储最佳的第一个移动(当深度=0时)来修复它,但如果解决方案不明显,那么该算法将严重失败。我还尝试修改基本案例的返回值,以便优先考虑早期的胜利,但这并没有解决问题。 目前我正在TictoE板上测试这个函数,助手类(如getMoves()或getW