我已经尝试修改我的算法以更好地工作,但我没有取得任何结果 . 我的问题是,在第一次移动后,如果我有,例如:
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;
}
因为你可以帮助我更好,我会明确一些变量的含义:
-
winner:是计算机移动的位置
-
u.moves:是搜索树上的深度,因为root是0
-
m:应该保存较少深度的状态解决方案,因此过滤器解决方案和计算机必须更加接近解决方案 .
-
检查:此时保存实用程序值,知道是否为终端状态
胜利的
-
实用程序是700,因为领带是0而失败是-700
-
u.ls:儿童状态列表
还有其他的东西,我认为使用m和胜利者全球并且在极小极大情况下返回全局是一个糟糕的解决方案,你能看到一些方法来改善这个吗?
非常感谢 .
1 回答
首先,如果状态不是终端,
u.getUtility()
会返回什么?如果它返回0,那么0 % 700 == 0
为真,所以's just finding the first move it expanded and selecting it. Since I can' t看到u.makeDescendents()
算法,我不能排除这个 .如果情况并非如此,那么几乎可以肯定你的
u.getUtility()
函数假设它只是被称为同一个最大玩家 . 即它_2522500_通过相同的极小极大值运行双方,然后当你评估O为最大值时,它将是唯一一次将评估视为胜利的时间 .如果是这种情况,修复很简单,确定哪个玩家从状态转向并返回赢/输评估,就好像它是那个玩家一样(这通常总是在TicTacToe中丢失,因为你不能做出失败的动作)你是游戏,你只能通过采取行动获胜,前一位玩家做出最后的动作) .
如果这些建议都没有解决问题,那么调试minimax问题的典型方法是一次一步深入游戏树,探索返回已知无效评估的路径,直到找到生成错误的点为止值 . 然后你必须检查它以找出原因 . 这对于像tic tac toe这样的小游戏来说是微不足道的,因为它只有9级深度并且你可以获得完美的极小极大值,但对于任何非平凡的游戏,你通常必须查看你的评估函数来确定差异发生的位置 .