大家好,又见面了,我是你们的朋友全栈君。
我想建议您完全重新考虑代码.查看代码的问题(以及为什么这里没有很多响应)是很难遵循并且很难调试.例如,什么是gs.getRemainingLines,它究竟做了什么? (为什么剩下的线而不是所有合法的线?)
但是,通过一些简化,可以更容易地弄清楚发生了什么并修复它.
在抽象层面,minimax只是这个过程:
float minimax_max(GameState g)
{
if (g is terminal or max depth reached)
return eval(g);
float bestVal = -inf;
bestMove = null;
moves = g->getLegalMoves();
for (m : moves)
{
ApplyMove(m);
if (g->nextPlayer == maxPlayer)
nextVal = minimax_max(g);
else
nextVal = minimax_min(g);
if (nextVal > bestVal)
{
bestVal = nextVal;
bestMove = m;
}
UndoMove(m);
}
return bestVal;
}
我没有详细说明如何在最后获得/使用最后一步,但并不是那么难.您还需要minimax_min的另一个过程,或者您可以在代码中放入if语句.
如果你看一下你的代码,你已经把它写得很接近了,但你在代码中留下了很多游戏特定的细节.但是,您不必考虑那些让minimax正常工作的事情.
特别是,如果为GetMoves(),ApplyMove(),UndoMove()和eval()提供函数来评估状态,大多数游戏都可以抽象地进行推理. (进一步的搜索增强功能需要更多功能,但这会让你有很长的路要走.)
您可能希望以这种方式重新考虑因素的一些原因:
>您现在可以单独测试minimax和其他代码.
>您可以通过验证所有合法移动是否已生成来测试您的点和框代码,并且在应用移动后您将拥有合法状态,并且接下来会移动正确的玩家. (您可以播放和撤消长时间的随机移动序列,以帮助验证您之后总是回到开始状态.)
>您可以在各个州轻松测试评估功能,以确保其正常工作. (实际上,你通常不能搜索游戏结束来确定获胜者.)
>您可以使用简单的评估函数测试minimax并测试以查看是否进行了正确的移动. (例如,如果您喜欢在边缘上移动,则单层搜索应返回边缘上的移动)
>其他人可以更轻松地阅读您的代码.我们可以查看每段代码并查看它是否正确,而不必将特定于游戏的实现细节混合到minimax特定的细节中.
>如果您可以正确应用和撤消移动,则无需复制游戏状态.这将使代码更有效.
虽然您可以尝试修复代码而不进行重构(例如,只需找到它返回null的第一个位置,并指出错误的位置),但从长远来看,如果没有这些更改,您的代码将难以调试和改进.
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/156385.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...