【问题标题】:connect 4 minimax algorithm: one for loop连接 4 极小极大算法:一个 for 循环
【发布时间】:2013-12-03 00:14:44
【问题描述】:

我正在尝试用一个 for 循环在 python 中编写 minimax 算法(是的,我知道维基百科说 min 和 max 播放器通常是分开处理的),我正在使用变量 turn 来跟踪minmax 播放器当前是否正在探索选项。然而,我认为,当轮到O 玩家时,代码错误地评估X,而当轮到X 玩家时,代码错误地评估O

这是源代码 (p12):http://web.cs.wpi.edu/~rich/courses/imgd4000-d10/lectures/E-MiniMax.pdf

您可能想知道的事情:

  1. b 是列表列表; 0 表示可用空间
  2. evaluate 既用于检查胜利(默认情况下),也用于为特定玩家在棋盘上打分(我们在棋盘上寻找单元格值的位置)。
  3. makeMove 返回该块所在列的行(用于后续删除)

任何帮助将不胜感激。如果有什么不清楚的地方请告诉我。

def minMax(b, turn, depth=0):

    player, piece  = None, None
    best,   move   = None, -1

    if turn % 2 == 0 : # even player is max player
        player, piece = 'max', 'X'
        best, move    = -1000, -1
    else :             
        player, piece = 'min', 'O'
        best, move    = 1000, -1

    if boardFull(b) or depth == MAX_DEPTH:
        return evaluate(b, False, piece)

    for col in range(N_COLS):
        if possibleMove(b, col) :

            row   = makeMove(b, col, piece)
            turn += 1  # now the other player's turn
            score = minMax(b, turn, depth+1)

            if player == 'max':
                if score > best:
                    best, move = score, col
            else:
                if score < best:
                    best, move = score, col

            reset(b, row, col)

    return move

@seaotternerd。是的,我想知道这一点。但我不确定这是问题所在。这是一份打印输出。如您所见,X 已被 AI 删除到第四列,但正在从最小玩家的角度进行评估(它在最右边的列中计算 2 个O 单位)。

这是评估函数确定的内容,具体取决于片段:

if piece == 'O':
    return best * -25
return best * 25

【问题讨论】:

  • 你能澄清一下这些列是什么吗?另外,这是在更改回合更新后吗?最后,您能否发布其余的评估功能? (例如,“最佳”从何而来?)
  • @seaotternerd:可以查看完整代码here(约200行)。我认为这将回答您所有的问题,但如果您还有更多问题,请告诉我。

标签: python algorithm artificial-intelligence


【解决方案1】:

每次你发现一个可能的移动而不是撤消它时,你都会增加turn。因此,当控制返回给定的 minMax 调用时,turn 比以前大 1。然后,下次您的程序找到可能的移动时,它会再次增加turn。这将导致对 minMax 的下一次调用选择错误的玩家作为当前玩家。总的来说,我相信这将导致董事会在大约一半的时间里被错误的玩家评估。您可以通过在对 minMax() 的递归调用中将 1 添加到 turn 来解决此问题,而不是通过更改存储在变量中的值:

        row   = makeMove(b, col, piece)
        score = minMax(b, turn+1, depth+1) 

编辑:深入研究您的代码,我发现了许多其他问题:

  1. MAX_DEPTH 设置为 1。这不会让 AI 看到自己的下一步行动,而是迫使它仅根据妨碍其他玩家的方式做出决定。
  2. minMax() 在达到MAX_DEPTH 或获胜条件时返回分数,否则返回移动。这会破坏分数在递归树上的传播。
  3. 这并不重要,但需要牢记:您的棋盘评估功能只考虑给定玩家的最长字符串有多长,而忽略其他玩家的表现以及可能使某个位置更好的任何其他因素比另一个。这主要意味着你的 AI 不会很“聪明”。
  4. 编辑 2:您跟踪最小值和最大值的方式的很大一部分问题在于您的评估函数。您检查是否每件都赢了。然后,您将根据当前玩家是谁来确定该棋盘的分数,但是拥有最小玩家和最大玩家的意义在于您不需要知道当前玩家是谁来评估棋盘。如果 max 赢了,则得分为无穷大。如果 min 获胜,则得分为 -infinity。 def 评估(b,片):

    if evaluate_aux(b, True, 'X'):
       return 100000
    
    if evaluate_aux(b, True, 'O'):
       return -100000
    
    return evaluate_aux(b, False, piece)
    
  5. 总的来说,我认为您可以做很多事情来使代码更简洁、更易于阅读,从而更容易检测错误。例如,如果您说“X”始终为最大值,“Y”始终为最小值,那么您无需费心跟踪玩家和棋子。此外,evaluate_aux 有时返回一个布尔值,有时返回一个 int 值是令人困惑的。例如,您可以让它计算一行中每件的数量,例如,连续的“X”计数为正数,连续的“O”计数为负数,然后将分数相加;评估函数不应该是从一个玩家的角度来看的。显然,您仍然需要检查那里的获胜条件。这也将解决第 3 点。

可能还有更多的问题,但是就像我说的,这段代码不是特别容易涉水的。如果你修复我已经找到的东西并清理它,我可以再看看。

【讨论】:

  • @hovaflow - 好的,我编辑了我的答案。我认为这包括很多问题,但可能还有更多问题被这些掩盖了。
  • 我不同意“你不必知道当前玩家是谁来评估董事会”的说法。如果当前玩家是O 并且X 刚刚赢了,我们不需要向O 报告吗?我现在正在为井字游戏编写代码,希望这将更容易调试/提供建议。我也将尝试解决您关于冗长的一些观点。评估函数会更清晰。
  • 你完全正确,O 需要知道 X 是否刚刚赢了。但是,传统上,你与 O 沟通的方式是给棋盘分配一个无穷大的分数(或 10000,在这个实现中)。这也是你与 X 沟通 X 刚刚获胜的方式。相反,-infinity(或-10000)的棋盘分数向两个玩家表明 O 刚刚赢了。这个想法是提出一个棋盘分数,表明当前棋盘设置有利于哪个玩家,以及有多少。分数越高意味着 max(在这种情况下为 X)表现良好,分数越低意味着 min (O) 表现良好。
  • 是的,我同意。我将在今晚 6 点之前将代码链接到井字游戏。我遇到了一种新算法,negamax,我认为它更符合我正在尝试做的事情的精神。代码不到 100 行,如果您有时间,我将不胜感激。谢谢;你已经解决了很多困惑。
  • 如果逻辑是正确的,适应更复杂的 Connect 4 游戏应该不会太难(所有需要改变的是评估,检查胜利......)。再一次,我真的很感激你看看:dropbox.com/s/jzel60jn76a80xl/TTT.py
猜你喜欢
  • 1970-01-01
  • 2016-01-24
  • 2019-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多