为什么我的极小极大不起作用

时间:2016-03-20 18:06:37

标签: c++ algorithm artificial-intelligence minimax

我已经尝试修改我的算法以更好地工作,但我还没有取得任何结果。我的问题是,在第一次移动后,如果我有,例如:

  XX.
  OO.
  ...

计算机,而不是选择0 2,选择例如1 2,有时候会尝试去寻找能够做到的位置。

我的代码:

#include "game.hpp"

pair<int,int> winner;
int m = INT_MAX;

pair<int,int> game::minimax(State ini) {
    int v = maxValue(ini);

    cout << v << endl;
    return winner;
}


int game::maxValue(State u){
    int check = u.getUtility();

    if( check % 700 == 0 ) {

        if( u.moves < m ) {
            winner = u.move;
            m = u.moves;
        }
        return check;
    }

    int v = INT_MIN;
    u.makeDescendents();

    while( !u.ls.empty() ) {
        v = max(v,minValue(u.ls.front()));
        u.ls.pop_front();
    }
    return v;
}

int game::minValue(State u) {
    int check = u.getUtility();

    if( check % 700 == 0 )
        return check;

    int v = INT_MAX;
    u.makeDescendents();

    while( !u.ls.empty() ) {
        v = min(v,maxValue(u.ls.front()));
        u.ls.pop_front();
    }
    return v;
}

因为你可以帮助我更好地表达一些变量的含义:

  • 获胜者:是计算机将移动的位置

  • u.moves:是搜索树上的深度,对于root是0

  • m:应该保存较少深度的状态解决方案,因此过滤器解决方案和计算机必须更加接近解决方案。

  • 检查:此时保存实用程序值,知道是否为终端状态

  • 胜利的效用为700,领带为0,失败为-700

  • u.ls:儿童状态列表

其他一些事情,我认为使用m和胜利者全球并在极小极大情况下返回全局是一个糟糕的解决方案,你能看到一些方法来改善这个吗?

非常感谢。

1 个答案:

答案 0 :(得分:1)

首先,如果状态不是终端,u.getUtility()会返回什么?如果它返回0,那么0 % 700 == 0为真,那么它只是找到它展开的第一步并选择它。由于我无法看到u.makeDescendents()算法,因此我无法排除这一点。

如果情况并非如此,那么几乎可以肯定你的u.getUtility()函数假设它只是被称为同一个最大玩家。即如果X获胜则返回700,如果X输了则返回-700。如果您通过相同的极小极大值运行双方,那么当您将O评估为最大值时,它仍在尝试为X找到胜利,因为这是唯一一次将评估视为一场胜利。

如果是这种情况,那么修复很简单,确定哪个玩家从状态转向并返回赢/输评估,就好像是那个玩家一样(这通常是TicTacToe的损失,因为你不能做出一个让你失去游戏的举动,你只能通过采取行动而获胜并且前一位玩家做出最后的动作。)

如果这些建议都没有解决问题,那么调试minimax问题的典型方法是一次一步地深入游戏树,探索返回已知无效评估的路径,直到找到关键点为止生成不正确的值。然后你必须检查它以找出原因。这对于像tic tac toe这样的小游戏来说是微不足道的,因为它只有9级深度并且你可以获得完美的极小极大值,但对于任何非平凡的游戏,你通常必须查看你的评估函数来确定差异发生的位置