努力想知道为什么我的井字游戏没有选择最佳动作 - python

时间:2021-03-30 15:24:33

标签: python tic-tac-toe 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()

抱歉乱码,先谢谢了

1 个答案:

答案 0 :(得分:0)

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

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 返回语句中添加和减去深度。

4..您可以通过列表推导获得所有可能的移动:

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


调试

还有一些其他的清理工作要做,但要弄清楚为什么它给出了错误的答案,您需要进行一些调试。您的赢/平/输功能是否像您认为的那样工作,即它是否为已知输入板返回正确结果?它是否遍历所有可能的移动?在您的极小极大循环中打印内容,看看它的行为是否符合您的预期。