python 最小最大井字游戏没有选择真正的最佳移动

fivyi3re  于 2023-01-16  发布在  Python
关注(0)|答案(1)|浏览(115)

我为Minimax AI井字游戏编写了python代码。然而,Minimax实际上并没有选择最好的移动。它似乎总是选择右上角的第一步,所有其他的移动几乎都是随机的。它非常容易被击败,这似乎是我代码中的一个错误。谢谢你的帮助。
GUI代码:

from tkinter import *
import customtkinter
import minimax

customtkinter.set_appearance_mode("Dark")
#creating CTk window for app
root = customtkinter.CTk()

#setting window width and height
root.geometry('500x300')

#Creating label
label = customtkinter.CTkLabel(master=root,
                               text="Tic Tac Toe",
                               width=120,
                               height=50,
                               font=("normal", 20),
                               corner_radius=8)
label.place(relx=0.25, rely=0.8, anchor=CENTER)

#Handling clicks
depth=9
def clickbutton(r, c):
    buttons[r][c]["text"]="X"
    board[r][c]="X"
    buttons[r][c]['state']=DISABLED

    label = customtkinter.CTkLabel(master=root,
                               text=checkwin(board),
                               width=120,
                               height=25,
                               corner_radius=8)
    label.place(relx=0.25, rely=0.9, anchor=CENTER)

    global depth
    depth-=1
    computerplay()
    depth-=1
    
    

#Button matrix
buttons = [
     [0,0,0],
     [0,0,0],
     [0,0,0]]
 
#Matrix identifying whether buttons are active or inactive
board=[[0,0,0],[0,0,0],[0,0,0]]
 
for i in range(3):
    for j in range(3):                                 
        buttons[i][j] = Button(height = 3, width = 6, font = ("Normal", 20),
                        command = lambda r = i, c = j : clickbutton(r,c))
        buttons[i][j].grid(row = i, column = j)


def computerplay():
    global depth
    bestmove=minimax.minimax(board, depth, 1)
    buttons[bestmove[0]][bestmove[1]]['text']="O"
    buttons[bestmove[0]][bestmove[1]]['state']=DISABLED
    board[bestmove[0]][bestmove[1]]="O"

def checkwin(b):
    score=minimax.evaluate(b)
    if score==10:
        return 'Computer won!'
    elif score==-10:
        return 'You won!'
    else:
        return 'Player vs. Computer'
    

root.mainloop()

最小最大代码:

def change_board(board):
    return [
        [(cell == "O") - (cell == "X") for cell in row]
        for row in board
    ]

def empty_cells(board):
    return [(i, j) for i in range(3) for j in range(3) if board[i][j] == 0]

def game_over(board):
    return (evaluate(board) == 10 or evaluate(board) ==-10 or not empty_cells(board))
    
lines = (
    (0, 0, 1, 1, 2, 2),
    (0, 2, 1, 1, 2, 0),
    (0, 0, 0, 1, 0, 2),
    (1, 0, 1, 1, 1, 2),
    (2, 0, 2, 1, 2, 2),
    (0, 0, 1, 0, 2, 0),
    (0, 1, 1, 1, 2, 1),
    (0, 2, 1, 2, 2, 2)
)

def evaluate(board):
    def iswin(line):
        arow, acol, brow, bcol, crow, ccol = line
        if board[arow][acol] == board[brow][bcol] == board[crow][ccol]:
            return board[arow][acol]*10

    return next((win for win in map(iswin, lines) if win), 0)
    

def minimax(board, depth, player):
    best = (-1, -1, -11*player)

    if depth <= 0 or game_over(board):
        return (-1, -1, evaluate(board))  # must return same structure

    for x, y in empty_cells(board):
        board[x][y] = player
        score = minimax(board, depth - 1, -player)[2]  # only get the score
        board[x][y] = 0
        if (player == 1) == (score > best[2]):
            best = (x, y, score)  # only inject x, y when move is best

    return best
5ktev3wc

5ktev3wc1#

您的代码混淆了存储在board中的值。一方面,有一个minimax模块,它在board中存储并期望值-1、0和1(当player为1或-1时),但另一方面,GUI端的代码将"O""X"存储在电路板数据结构中。这种混淆破坏了evaluate函数中使用的逻辑。
在主题的previous question中,您有一个函数change_board,它执行了从"X""O"值到-1和1的转换。但在本题中没有执行此转换。
因此,要解决此问题,请更改GUI管理代码中的以下行:

board[r][c]="X"
...
board[bestmove[0]][bestmove[1]]="O"

...至:

board[r][c]=-1
...
board[bestmove[0]][bestmove[1]]=1

相关问题