努力了解为什么我的井字游戏 minimax 游戏没有选择最佳着法 - python

Struggling to see why my tic tac toe minimax game is not picking the best move - python

我正在努力查看我的 minimax 算法是如何不起作用的。它循环遍历所有最佳动作,但没有选择最佳动作,我不明白为什么。例如,我可以输入 1 5 9 并获胜。如果解决方案很简单,请提前抱歉 这是代码。

board = {1: ' ', 2: ' ', 3: ' ',
         4: ' ', 5: ' ', 6: ' ',
         7: ' ', 8: ' ', 9: ' '}
win = False
turn = 1
depth = 1
nodeindex = 0
possibles= []
moves = []
depth = 0
targetdepth = 3
movesdone = []
#def minimax(moves, targetdepth, depth, turn, scores):


def checkForWin(mark):
    if board[1] == board[2] and board[1] == board[3] and board[1] == mark:
        return True
    elif (board[4] == board[5] and board[4] == board[6] and board[4] == mark):
        return True
    elif (board[7] == board[8] and board[7] == board[9] and board[7] == mark):
        return True
    elif (board[1] == board[4] and board[1] == board[7] and board[1] == mark):
        return True
    elif (board[2] == board[5] and board[2] == board[8] and board[2] == mark):
        return True
    elif (board[3] == board[6] and board[3] == board[9] and board[3] == mark):
        return True
    elif (board[1] == board[5] and board[1] == board[9] and board[1] == mark):
        return True
    elif (board[7] == board[5] and board[7] == board[3] and board[7] == mark):
        return True
    else:
        return False

def checkForWin2():
    if (board[1] == board[2] and board[1] == board[3] and board[1] != ' '):
        return True
    elif (board[4] == board[5] and board[4] == board[6] and board[4] != ' '):
        return True
    elif (board[7] == board[8] and board[7] == board[9] and board[7] != ' '):
        return True
    elif (board[1] == board[4] and board[1] == board[7] and board[1] != ' '):
        return True
    elif (board[2] == board[5] and board[2] == board[8] and board[2] != ' '):
        return True
    elif (board[3] == board[6] and board[3] == board[9] and board[3] != ' '):
        return True
    elif (board[1] == board[5] and board[1] == board[9] and board[1] != ' '):
        return True
    elif (board[7] == board[5] and board[7] == board[3] and board[7] != ' '):
        return True
    else:
        return False

def possiblemoves(board):
    y=0
    possibles.clear()
    for i in board:
        if board[i] == " ":
            possibles.append(i)
    return possibles


def botgo(possibles, mark):
    bestscore = -800
    bestmove = 0
    for key in board.keys():
        if (board[key] == ' '):
            board[key] = mark
            score = minimax(board,0,False)
            board[key] = ' '
            if(score > bestscore):
                bestscore = score
                bestmove = key
    insert(bestmove,mark='O')
    return
def printboard():
    print(board[1] + '|' + board[2] + '|' + board[3])
    print('-----')
    print(board[4] + '|' + board[5] + '|' + board[6])
    print('-----')
    print(board[7] + '|' + board[8] + '|' + board[9])

def start():
    turn = 1
    count = 0
    while count != 9:
        humango()
        printboard()
        possiblemoves(board)
        botgo(possibles, mark='O')
        printboard()
        count = count + 1
        
        #minimax(depth, possibles)

def spacefree(space):
    if board[space] == ' ':
        return True
    else:
        return False
def insert(space, mark):
    if spacefree(space):
        board[space]=mark
        if checkForWin(mark):
            if mark == 'X':
                printboard()
                print("human win")
                exit()
            else:
                printboard()
                print("BOT WIN")
                exit()
    else:
        print("cannot insert there!!!")
        space = int(input("Enter position"))
        insert(space, mark)
def checkdraw(board):
    if checkForWin2():
        return True
def humango():
    global turn
    space = int(input("Enter position"))
    insert(space, mark='X')
    turn = turn + 1
    printboard()

def minimax(board, depth, ismax):
    if checkForWin(mark='O'):
        return 1
    elif checkForWin(mark='X'):
        return -1
    elif checkdraw(board):
        return 0
    if ismax == True:
        bestscore = -800
        for key in board.keys():
            if (board[key] == ' '):
                board[key] = 'O'
                score = minimax(board, depth + 1, False)
                board[key] = ' '
                if (score > bestscore):
                    bestscore = score
                printboard()
        return bestscore
    else:
        bestscore = 800
        for key in board.keys():
            if (board[key] == ' '):
                board[key] = 'X'
                score = minimax(board, depth + 1, True)
                board[key] = ' '
                if (score < bestscore):
                    bestscore = score
        return bestscore


    
start()

抱歉代码乱七八糟,先谢谢了

看来你把事情复杂化了,你调试起来会更容易,代码更少,看得更清楚。我首先建议您使用列表而不是字典来简化您在这个游戏中的代码:board = [' ']*9。我下面的所有suggestions/simplifications都是基于这个表示。

1.. 在 1D 棋盘上检查是否获胜非常容易。首先,您创建一个包含所有可能获胜线的变量:

winning_lines = ([0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6])

然后你可以用一个循环遍历它们:

def is_win(board, player):    
    for pos in winning_lines:
            if board[pos[0]] == board[pos[1]] == board[pos[2]] == player:
                return 1

2.. 检查平局更简单,因为你只需要检查是否有空格:

def is_draw(board):
    return 0 if ' ' in board else 1

3.. 在此游戏中您不需要深度变量,因为您总是达到最大深度,以赢、平或输告终。如果有超过 1 条路径,深度可用于始终选择最短的获胜路径,或最长的失败路径。然后你需要在 minimax 循环中从你的 check_win return 语句中添加和减去深度。

4.. 你可以通过列表理解得到所有可能的走法:

possible_moves = [i for i in range(len(board)) if board[i] == ' ']


调试

还有一些其他的清理工作要做,但要弄清楚为什么它会给出错误的答案,您需要进行一些调试。您的 win/draw/loss 功能是否如您所想的那样工作,即它是否 return 是已知输入板的正确结果?它会遍历所有可能的动作吗?在你的 minimax 循环中打印一些东西,看看它的行为是否如你所期望的那样。