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

在Minimax中实现Alpha-Beta

罗奇文
2023-03-14

我试图在我的极小值中添加阿尔法贝塔修剪,但我不明白我哪里出错了。

目前,我正在经历5000次迭代,根据一个朋友的说法,我应该经历大约16000次迭代。当选择第一个位置时,它返回-1(一个损失),而它应该能够在这一点上肯定返回0(一个平局),因为它应该能够从一个空的棋盘中抽签,但是我看不到我哪里出错了,因为我跟着我的代码走似乎没问题

奇怪的是,如果我在我的检查中切换返回α和β(以实现返回0),计算机将尝试绘制,但永远不会启动任何获胜的动作,只有块

我的逻辑流程

如果我们在寻找阿尔法:如果分数

如果我们在找β:如果分数

这是我的递归调用

int MinimaxAB(TGameBoard* GameBoard, int iPlayer, bool _bFindAlpha, int _iAlpha, int _iBeta) 
{

    //How is the position like for player (their turn) on iGameBoard?
    int iWinner = CheckForWin(GameBoard);
    bool bFull = CheckForFullBoard(GameBoard);

    //If the board is full or there is a winner on this board, return the winner
    if(iWinner != NONE || bFull == true) 
    {
        //Will return 1 or -1 depending on winner
        return iWinner*iPlayer;
    }

    //Initial invalid move (just follows i in for loop)
    int iMove = -1;
    //Set the score to be instantly beaten
    int iScore = INVALID_SCORE;

    for(int i = 0; i < 9; ++i)
    {
        //Check if the move is possible
        if(GameBoard->iBoard[i] == 0) 
        {
            //Put the move in
            GameBoard->iBoard[i] = iPlayer;

            //Recall function
            int iBestPositionSoFar = -MinimaxAB(GameBoard, Switch(iPlayer), !_bFindAlpha, _iAlpha, _iBeta);

            //Replace Alpha and Beta variables if they fit the conditions - stops checking for situations that will never happen
            if (_bFindAlpha == false)
            {
                if (iBestPositionSoFar < _iBeta)
                {
                    //If the beta is larger, make the beta smaller
                    _iBeta = iBestPositionSoFar;
                    iMove = i;

                    if (_iAlpha >= _iBeta)
                    {
                        GameBoard->iBoard[i] = EMPTY;

                        //If alpha and beta are overlapping, exit the loop
                        ++g_iIterations;
                        return _iBeta;

                    }
                }
            }
            else
            {
                if (iBestPositionSoFar > _iAlpha)
                {
                    //If the alpha is smaller, make the alpha bigger
                    _iAlpha = iBestPositionSoFar;
                    iMove = i;

                    if (_iAlpha >= _iBeta)
                    {
                        GameBoard->iBoard[i] = EMPTY;

                        //If alpha and beta are overlapping, exit the loop
                        ++g_iIterations;
                        return _iAlpha;
                    }
                }
            }

            //Remove the move you just placed
            GameBoard->iBoard[i] = EMPTY;
        }
    }


    ++g_iIterations;

    if (_bFindAlpha == true)
    {
        return _iAlpha;
    }
    else
    {
        return _iBeta;
    }
}

初始呼叫(计算机应选择位置时)

int iMove = -1; //Invalid
int iScore = INVALID_SCORE;

for(int i = 0; i < 9; ++i) 
{
    if(GameBoard->iBoard[i] == EMPTY) 
    {
        GameBoard->iBoard[i] = CROSS;
        int tempScore = -MinimaxAB(GameBoard, NAUGHT, true, -1000000, 1000000);
        GameBoard->iBoard[i] = EMPTY;

        //Choosing best value here
        if (tempScore > iScore)
        {
            iScore = tempScore;
            iMove = i;
        }
    }
}
//returns a score based on Minimax tree at a given node.
GameBoard->iBoard[iMove] = CROSS;

任何关于我的逻辑流程的帮助都会使计算机返回正确的结果并做出明智的动作,我们将不胜感激

共有1个答案

牟恺
2023-03-14

您的算法在没有alpha-beta修剪的情况下是否能完美工作?对于\u bFindAlpha,您的初始调用应该使用false进行,因为根节点的行为类似于alpha节点,但看起来这不会有什么不同:

int tempScore = -MinimaxAB(GameBoard, NAUGHT, false, -1000000, 1000000);

因此,我建议您放弃这个\u bFindAlpha废话,将您的算法转换为negamax。它的行为与minimax相同,但使代码更短、更清晰。不必检查是最大化alpha还是最小化beta,您可以在递归调用时交换和求反(这与您现在可以返回函数的求反值的原因相同)。以下是维基百科伪代码的略加编辑的版本:

function negamax(node, α, β, player)
    if node is a terminal node
        return color * the heuristic value of node
    else
        foreach child of node
            val := -negamax(child, -β, -α, -player)
            if val ≥ β
                return val
            if val > α
                α := val
        return α

除非您喜欢单步搜索树,否则我认为您会发现编写干净、正确的negamax版本比调试当前实现更容易。

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

  • 我正在尝试为一个游戏创建一个AI播放器,使用带有alpha-beta修剪的minimax算法。我在正确地执行它时遇到了一些困难。我有两个功能要使用,一个用于评估给定玩家(返回一些分数)getBoardScore的当前棋盘状态,另一个用于返回每个可能移动(从给定玩家的给定棋盘状态)GetPossibleBoard创建的所有可能棋盘状态。 我的AI通过最初调用alphaBeta,将其传递到当前的板状态

  • 我很难让Alpha-beta修剪正常工作。我有一个函数Minimax算法,我试着去适应,但没有用。我在维基百科上用了这个例子 目前,该算法似乎在大多数情况下都按预期运行,但不管怎样,它都会选择第一个测试节点。 这可能是因为缺乏理解,但我已经花了数小时阅读了这篇文章。让我困惑的是,在零和博弈中,算法如何知道当达到深度极限时哪个节点是最佳选择;在哪一点上,我们还不能确定哪位球员会从这样的举动中受益最大

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

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

  • 好的,我的问题对于任何玩过棋盘游戏编程的人来说都应该很熟悉,所以这里是: 我实现了MiniMax算法的一种变体(返回移动而不是最小/最大值) 我还尝试将其设置为alpha beta版,尽管最终完全失败 这是我的极大极小码: 有什么想法吗?如何调整上述内容,使其成为Alpha Beta搜索? 下面是我尝试的Alpha-Beta转换(失败得很惨): 提示(以避免任何误解): > 此- 和分别被定义为一