实现极小化极大算法

我已经在网上搜索了伪代码、工作示例、堆栈溢出的问题/解决方案等,但到目前为止还没有找到任何有帮助的内容,所以我在这里寻求帮助。

我试图以一种非常基本的方式(没有alpha/beta剪枝)在我的井字游戏中实现极小化极大算法。让我先解释一下我有的每个辅助方法,然后如果需要,我可以分享我实际代码的部分。注意(我在检查终止状态时不使用深度,只检查胜利或平局)。

首先,我有一个名为MakeBestMove的实用程序,它会在电脑移动时被调用,然后在MakeBestMove中会调用MiniMax,MiniMax会一直调用自己直到boardState达到终止状态或没有剩余移动为止。

我希望MakeBestMove返回最佳移动,我的MiniMax函数返回boardState的分数。

如果你熟悉MiniMax,当状态是终止状态时,状态会被评分。我使用-100表示玩家O获胜,100表示玩家X获胜,0表示平局来评分我的游戏。这是在我的EvaluateScore辅助函数中完成的。我还有一个函数会根据游戏板的当前状态确定可用的移动,以帮助我遍历开放的移动。另外,值得注意的是,玩家“X”总是人类,而玩家“O”总是电脑。

我试图使用我在Python中实现MiniMax的方法来实现F#中的MiniMax,理论上它应该能工作,尽管它不忠于F#的函数式范式。

不知为何,它的行为与我预期的不一样。我花了几个小时检查每一行代码,确保没有奇怪的副作用,但没有成功。如果有人能指导我正确的方向,我将不胜感激。我知道我写的代码非常命令式,但我认为这样也可以工作,但我无法弄清楚为什么它不工作,以及我可能遗漏了什么。任何帮助都将不胜感激!

代码行为问题:1. MakeBestMove不能正确返回bestMove 2. 虽然Minimax函数看起来通过递归迭代不同的终止boardStates表现正确,但MakeBestMove不会阻止“O”的移动,但会在一步之遥时采取获胜的移动。

我希望我的代码表现如下:1. 能够正确评分boardState(我认为我已经在做了)2. 如果boardState是终止状态,或者没有更多的移动可以采取时,返回该分数(我正在做)3. 使用该分数来做出最佳移动选择(这是问题所在)

编辑 我想添加一个对我的程序中调用的“走查”,以防你想在Visual Studio中运行我的代码并测试它。

我的代码从Program.fs开始,当它调用ComputerPlayerTurn()时,它会使用Game.fs,其中ComputerPlayerTurn()被调用后会初始化变量let mutable computerMoveMakeBestMove(board)。在MakeBestMove(board)被调用后,在函数内部会调用MiniMax(board) marker

以下代码是我遇到行为问题的地方:

let rec MiniMax(board) marker =     let mutable bestValue = 0    let mutable board = board    let mutable moves = GetListOfMoves(board)     if GameWon(board) marker = true || GetListOfMoves(board).Count = 0 then        bestValue <- EvaluateScore(board)    else        if marker = "X" then            bestValue <- -100            for move in moves do                  board <- ModifyBoard(board) move marker                bestValue <- max(MiniMax(board) "O")(bestValue)                 board <- ModifyBoard(board) move " "            bestValue <- bestValue        else             bestValue <- 100            for move in moves do                  board <- ModifyBoard(board) move marker                bestValue <- min(MiniMax(board) "X")(bestValue)                 board <- ModifyBoard(board) move " "            bestValue <- bestValue    bestValuelet MakeBestMove (board) marker =     let mutable board = board    let mutable bestMove = 0    let mutable bestValue = 0    let mutable bestMoves = ResizeArray<int>()    let moves = GetListOfMoves(board)    for move in moves do        board <- ModifyBoard(board) move marker        bestValue <- MiniMax(board) "X"         board <- ModifyBoard(board) move " "        if marker = "X" then            if bestValue = 100 then                bestMove <- move            if bestValue > 0 then                bestMoves.Add(move)            else if bestValue = 0 then                bestMoves.Add(move)        elif marker = "O" then            if bestValue = -100 then                bestMove <- move            if bestValue < 0 then                bestMoves.Add(move)            else if bestValue = 0 then                bestMoves.Add(move)    if bestMove = 0 && bestMoves.Count > 0 then        bestMove <- bestMoves.[0]    elif bestMove <> 0 then        bestMove <- bestMove    else        bestMove <- GetListOfMoves(board).[0]    bestMove 

我的代码在Github上的我的MASTER分支的仓库中:https://github.com/sinnmk/fsharp-tictactoe


回答:

问题出在这里:

if ((GameWon(board) marker) = true || (moves.Count = 0)) then

它只考虑了平局和marker获胜的游戏。它还应该考虑marker输掉的游戏:

if GameWon board "O" || GameWon board "X" || moves.Count = 0 then

我删除了不必要的括号和条件,如= true

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注