我试图创建我的第一个游戏使用极大极小算法,但我不知道如何实现这一点使用树。
游戏规则如下:
>
赢家是从桌子上拿走最后一个立方体的玩家。
第一个玩的玩家是MAX(电脑),第二个玩MIN(人类)。
首先我们必须运行minimax算法,然后玩家MAX使用最佳移动。
这是游戏,但我无法想象如何实现这一点与树。谁能帮帮我,给我一个主意吗?
并不是你创建了一棵树,而是你的搜索可以被描述为一棵树。
举一个更熟悉的例子,说它是Tic-Tac-Toe。你是X。你有9个选择,9个可能的动作。
在那之后,碰巧,O将有8个可能的动作。等等。
您可以执行深度优先搜索(确保有深度限制),每次从子级返回结果时,都会获取最小(或最大)结果。
本页详细讨论了Tic Tac Toe示例:http://neverstopbuilding.com/minimax.注意,他们的算法是递归的,这使得累积孩子们的分数相对简单。
根据我的理解,通常(也许是最直观的方式)不是使用游戏树的显式表示,而是将算法的内部工作视为实际执行所需的移动,递归地评估移动并最终取消移动。这意味着游戏树中的导航由调用堆栈表示,可以被视为隐式表示树上的深度优先搜索。成功的电话将分别从任何一个对手的角度出发。
尽管如此,这样的实现在第一次尝试时可能并不容易。此外,请注意,您描述的游戏似乎与Nim密切相关,对于Nim,可能存在更有效的算法。
minimax计算应通过深度优先搜索执行。最好的方法是稍微抽象一下状态空间。实现一个名为GetMoves
的函数,该函数返回所有有效的移动,以及一个GameOver
函数,该函数在游戏结束时返回。如果无法搜索整个树,还应限制搜索深度(这将启用迭代深化)。然后您的代码是这样的(这只是伪代码):
double maxPlayer(state, depth)
{
if (state.GameOver() || depth == 0)
return state.eval;
auto moves = state.GetMoves();
int best = NINF;
for (m : moves)
{
state.ApplyMove(m);
int tmp = minPlayer(state, depth-1);
if (tmp > best)
best = tmp;
state.UndoMove(m);
}
return best;
}
在这里,您需要编写相应的minPlayer
函数。注意,这不包括alpha-beta修剪。它也不会返回最佳移动。您还可以使用negamax格式为max/min播放器编写一个函数,而不是两个函数。
在您的情况下,您的移动可能只是整数,1或L。应用移动减去1或L个立方体,撤消移动添加1或L个立方体。
请注意,在这个公式中,我们没有检查树中的重复项,因此它将是立方体数量的指数。但是,由于在确定胜利者时不关心动作的历史记录,因此实际上整个树中只需要2M个节点。使用一个表来存储搜索结果(记忆/换位表)将使树的节点数最多减少到2M,而不是2^M。