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

MiniMax与阿尔法Beta修剪奥赛罗不工作

尹承泽
2023-03-14

我有以下奥赛罗(reversi)游戏的阿尔法-贝塔极小值的实现。不知怎的,这永远不会返回正确的行动。它似乎返回了我在函数(0,0)中设置的默认操作和第二个值-32768,这意味着它在MAX子例程中被删减了。关于我可以改进什么以及如何解决这个问题,有什么建议吗?

注意:我已经确定了大部分正确返回的继任者。目前的最大深度是8。电脑玩家的pn(玩家数量)是1,人类玩家的是0。第一阶段,0,是MINIMAX_MAX。阿尔法和贝塔最初分别设置为INT_MIN和INT_MAX。

mm_out minimax(Grid& G, int alpha, int beta, Action& A, uint pn, uint depth, bool stage) {
    if (G.check_terminal_state() || depth == MAX_DEPTH) {
#ifdef DEBUG
        cout << "best action: (" << A.get_x() << ", " << A.get_y() << ")\n";
#endif
        return mm_out(A, G.get_utility(pn));
    }

    // add end game score total here

#ifdef DEBUG
    if (stage == MINIMAX_MAX) {
        cout << "max " << alpha << " " << beta << "\n";
    }
    else {
        cout << "min " << alpha << " " << beta << "\n";
    }
#endif

    set<Action> succ_temp = G.get_successors(pn);
    for (Action a : succ_temp) {

#ifdef DEBUG
        cout << a.get_x() << " " << a.get_y() << '\n';
#endif

        Grid gt(G);
        a.evaluate(gt);
    }
    set<Action, action_greater> successors(succ_temp.begin(), succ_temp.end());

#ifdef DEBUG
    Player p(0, "minimaxtest");
    G.display(p);
    int test;
    cin >> test;
#endif

    // if no successor, that player passes
    if (successors.size()) {
        for (auto a = successors.begin(); a != successors.end(); ++a) {
            Grid gt(G);
            gt.do_move(pn, a->get_x(), a->get_y(), !PRINT_ERR);
            Action at = *a;
            mm_out mt = minimax(gt, alpha, beta, at, pn ^ 1, depth + 1, !stage);
            int temp = mt.val;
//          A = mt.best_move;

            if (stage == MINIMAX_MAX) {
                if (alpha < temp) {
                    alpha = temp;
                    A = *a;
#ifdef DEBUG
                    cout << "Current action: (" << A.get_x() << ", " << A.get_y() << ") alpha = " << alpha << "\n";
#endif
                }
                if (alpha >= beta) {
#ifdef DEBUG
                    cout << "pruned at max\n";
#endif
                    return mm_out(A, beta);
                }
            }
            else {
                if (beta > temp) {
                    beta = temp;
                    A = *a;
#ifdef DEBUG
                    cout << "Current action: (" << A.get_x() << ", " << A.get_y() << ") beta = " << beta << "\n";
#endif
                }
                if (alpha >= beta) {
#ifdef DEBUG
                    cout << "pruned at min\n";
#endif
                    return mm_out(A, alpha);
                }


}
    }
    return mm_out(A, (stage == MINIMAX_MAX) ? alpha : beta);
}
else {
    cout << "no successor\n";
    return mm_out(A, (stage == MINIMAX_MAX) ? (std::numeric_limits<int>::max() - 1) : (std::numeric_limits<int>::min() + 1));
}

}

实用功能:

int Grid::get_utility(uint pnum) const {
    if (pnum)
        return wcount - bcount;
    return bcount - wcount;
}

共有1个答案

单于承
2023-03-14

您应该按值传递alpha/beta参数(而不是通过引用):

mm_out minimax(Grid& G, int alpha, int beta, Action& A, uint pn, uint depth, bool stage)

每个节点都将alpha和beta值传递给其子节点。然后,子节点根据轮到谁更新自己的alpha或beta值副本,并返回该节点的最终评估。然后用于更新父级的alpha或beta值。

 类似资料:
  • 我正在实现一个Alpha Beta修剪算法,该算法将用于在奥赛罗游戏中获得最佳移动。当算法到达叶节点(即没有有效移动或达到最大深度)时,我基于此计算该节点的启发式值: 最大化玩家(正在运行算法并将使用算法返回的移动的玩家)在这个节点的棋盘上有多少块砖块?(每个砖块1块) 最大化玩家在这个节点上有多少有效动作?(每招10) 最大化玩家有多少角砖?(每块角砖100) 问题是:当不是玩家在叶节点中交出的

  • 我试图让Alpha-beta修剪工作,但与我的Minimax函数相比,它给了我完全错误的动作。这是我的极大极小函数,它现在工作得很好。 这是我的Alphabeta修剪函数 两者都使用相同的评估,不确定这里出了什么问题。谢谢你的帮助。

  • 在我的方法newminimax49中,我有一个minimax算法,它利用了本文中建议给我的记忆和其他一般性改进。该方法使用一个简单的启发式电路板评估函数。我的问题基本上是关于alpha-beta修剪,即我的minimax方法是否使用alpha-beta修剪。据我所知,我相信这是真的,然而,我用来实现它的东西似乎太简单了,不可能是真的。此外,其他人建议我使用alpha-beta剪枝,正如我所说的,我

  • 我目前正在从事我的第一个C项目,并选择使用基于Minimax的AI编写一个Connect Four(又名Score 4),更具体地说是基于Alpha-Beta修剪方法。 到目前为止,我了解到AB修剪包含在一个递归算法中,该算法考虑了一个alpha和一个beta参数,这是您在游戏树中找不到的“极限”。此外,我们定义了最大化和最小化玩家,前者是第一个开始玩游戏的玩家。最后,还有一个“深度”,我把它理解

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

  • 这是我的极小极大方法,它实现了alpha beta修剪和记忆: 作为一个测试游戏,在我的主要方法中,我在某处放置一个X(X是玩家),然后调用newminimax499查看我应该在哪里放置O(计算机): } 该方法返回计算机应该在何处播放它的O(在本场景中为6),因此我按照指示放置O,自己播放X,调用newminimax499并再次运行代码以查看O要在何处播放,依此类推。 在这次特殊的运行之后,我得