如何修复井字游戏的极小极大算法

How to fix my minimax algorithm for tic tac toe game

对于一个学校项目,我一直在尝试制作一款无与伦比的井字游戏。为此,我尝试实现一个 minimax 算法,它给出了意想不到的输出,我一直无法弄清楚原因,也没有解决任何问题。

我已经尝试打印出变量以查看何时出现问题,但是对于比最简单的情况(它在其中工作)更复杂的任何事情,它输出的东西太多以至于任何人都无法筛选,并且当我完成它,跟踪调用自身的函数,以及它调用自身的次数是很困难的。我试过将严格的不等式改为非严格的不等式。我试过几次重写整个事情,看看我是否只是有错字。我已经逐步了解了逻辑,但一无所获。

这是我的算法

def minimax(newboard, player, huplayer, aiplayer):
    move=-1
    empty=emptyindices(newboard)
    if winning(newboard, huplayer):
        score=-1
    elif winning(newboard, aiplayer):
        score = 1
    elif empty==[]:
        score=0
    else:
        if player == aiplayer:
            score=0
            for i in empty:
                newboard[i]=player
                output=minimax(newboard, huplayer, huplayer, aiplayer)
                tempscore=output[1]
                if tempscore > score:
                    score=tempscore
                    move = i
                    newboard[i]=""
                newboard[i]=""
        if player == huplayer:
            score=0
            for i in empty:
                newboard[i]=player
                output=minimax(newboard, aiplayer, huplayer, aiplayer)
                tempscore=output[1]
                if tempscore < score:
                    score=tempscore
                    move = i
                    newboard[i]=""
                newboard[i]=""
    return [move,score]

我已经将电路板从 0 索引到 8,就像

0 | 1 | 2

3 | 4 | 5

6 | 7 | 8

我不认为使用的其他函数有错误,但我还是会把它们包括在这里,以防它们确实是问题所在。

def winning(board,player):
    if (board[0]==player and board[1]==player and board[2]==player) or (board[3]==player and board[4]==player and board[5]==player) or(board[6]==player and board[7]==player and board[8]==player) or(board[0]==player and board[3]==player and board[6]==player) or (board[1]==player and board[4]==player and board[7]==player) or(board[2]==player and board[5]==player and board[8]==player) or (board[0]==player and board[4]==player and board[8]==player) or (board[2]==player and board[4]==player and board[6]==player):
        win=True
    else:
        win=False
    return win

def emptyindices(board):
    empty=[]
    for i in range(9):
        if board[i]=="":
            empty.append(i)
    return empty

对于计算机可以立即采取行动获胜的简单情况,它会这样做。 但是对于

这样的东西
print(minimax(['X', '', '', 'O', '', 'X', 'X', 'O', 'O'],"X","O","X"))

输出是

[-1, 0]

即使计算机可以通过移动 2 来保证获胜,这意味着由于某种原因移动没有从默认值改变

我认为这应该可行(我刚刚测试了我在评论中提出的建议)。可怜的输家球员太瘫痪了,无法采取行动,认识到这是不可避免的命运:-)

def minimax(newboard, player, huplayer, aiplayer):
    move=-1
    empty=emptyindices(newboard)
    if winning(newboard, huplayer):
        score=-1
    elif winning(newboard, aiplayer):
        score = 1
    elif empty==[]:
        score=0
    else:
        if player == aiplayer:
            score=-2
            for i in empty:
                newboard[i]=player
                output=minimax(newboard, huplayer, huplayer, aiplayer)
                tempscore=output[1]
                if tempscore > score:
                    score=tempscore
                    move = i
                    newboard[i]=""
                newboard[i]=""
        if player == huplayer:
            score=2
            for i in empty:
                newboard[i]=player
                output=minimax(newboard, aiplayer, huplayer, aiplayer)
                tempscore=output[1]
                if tempscore < score:
                    score=tempscore
                    move = i
                    newboard[i]=""
                newboard[i]=""
    return [move,score]

不错的功能!

顺便说一句。您可以通过为分数使用一个因子来使代码更短一些。因此,对于最小化玩家,您将因子设置为 -1,将最大化设置为 1。这样您就可以重复使用空字段上的循环和两个玩家的循环体,而无需通过将条件更改为类似的东西来实现两次:

if tempscore*factor > score: