实现极小化极大算法

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

我试图以一种非常基本的方式(没有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

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

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