Tkinter Tic Tac Toe:添加平局条件,绑定键,在不关闭画布的情况下停止游戏

问题描述 投票:0回答:1

井字游戏项目快要完成了,我在绑定和添加平局条件方面遇到了一些问题。我能够将函数绑定到,并且它们可以正常工作,但是我希望将它们绑定到R和转义键(将reset_game绑定到R并接近转义)。我也尝试过为平局条件添加变量k,但该变量k尚未定义。这是代码:

from tkinter import *
import tkinter.messagebox
ttt = Tk()
ttt.title("Tic Tac Toe")
w = Canvas(ttt, width = 902, height = 902)
w.configure (bg =  "white")
w.pack()

m = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
size = 300
player = 1


w.create_line(0, 300, 902, 300, fill = "black") 
w.create_line(0, 601, 902, 601, fill = "black")
w.create_line(300, 0, 300, 902, fill = "black")
w.create_line(601, 0, 601, 902, fill = "black")

def on_click(event):
    global m
    global player
    global k
    row = event.y // size
    col = event.x // size
    if m[row][col] == 0:
        cx = col * size + size // 2
        cy = row * size + size // 2
        if player == 1:
            draw_X(cx, cy)
            print ("Player 1, X")
        else:
            draw_O(cx, cy)
            print ("Player 2, O")
        m[row][col] = player
        Win()
        player = 2 if player == 1 else 1
    k = k + 1

def draw_O(x, y):
    radius = size // 3
    w.create_oval(x-radius, y-radius, x+radius, y+radius, width=5, tag='cell')

def draw_X(x, y):
    radius = size // 3
    w.create_line(x-radius, y-radius, x+radius, y+radius, width=5, tag='cell')
    w.create_line(x+radius, y-radius, x-radius, y+radius, width=5, tag='cell')

def reset_game(event):
    global m
    global player
    w.delete('cell')
    m = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
    player = 1
    k = 0

def tie():
    if (k==8):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Tie")

def Win():
    if (m[0][0] == m[0][1] and m[0][0] == m[0][2] and m[0][0]!=0):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[0][0]))
        ttt.destroy()
        print ("Player", str(m[0][0]), "wins")
    elif (m[0][0] == m[1][0] and m[0][0] == m[2][0] and m[0][0]!=0):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[0][0]))
        ttt.destroy()
        print ("Player", str(m[0][0]), "wins")
    elif (m[1][0] == m[1][1] and m[1][0] == m[1][2] and m[1][0]!=0):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[1][0]))
        ttt.destroy()
        print ("Player", str(m[1][0]), "wins")
    elif (m[0][1] == m[1][1] and m[0][1] == m[2][1] and m[0][1]!=0):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[0][1]))
        ttt.destroy()
        print ("Player", str(m[0][1]), "wins")
    elif (m[0][2] == m[1][2] and m[0][2] == m[2][2] and m[0][2]!=0):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[0][2]))
        ttt.destroy()
        print ("Player", str(m[0][2]), "wins")
    elif (m[2][0] == m[2][1] and m[2][0] == m[2][2] and m[2][0]!=0):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[2][0]))
        ttt.destroy()
        print ("Player", str(m[2][0]), "wins")
    elif (m[0][0] == m[1][1] and m[0][0] == m[2][2] and m[0][0]!=0):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[0][0]))
        ttt.destroy()
        print ("Player", str(m[0][0]), "wins")
    elif (m[0][2] == m[1][1] and m[0][2] == m[2][0] and m[0][2]):
        tkinter.messagebox.showinfo("Tic Tac Toe", "Winner is player " + str(m[0][2]))
        ttt.destroy()
        print ("Player", str(m[0][2]), "wins")


w.bind('<Button-1>', on_click)

def close(event):
    ttt.destroy()

w.bind('<Button-2>',close)

w.bind('<Button-3>', reset_game)

ttt.mainloop()

我也想在某人获胜或没有平局的情况下平局以停止比赛,以便我重新设置。关于如何做到这一点的任何想法?

python tkinter
1个回答
0
投票

由于您已经添加了全局变量k作为玩转数,因此player可以由k的值确定,因此可以将其从全局变量中删除。

您需要声明全局变量k

m = [[0,0,0], [0,0,0], [0,0,0]]
size = 300
k = 0

此外,您可以简化/修改函数Win以接受rowcol作为参数并返回是否有赢家:

 def Win(row, col):
    # check horizontal
    if m[row][0] == m[row][1] == m[row][2]:
        return m[row][col]
    # check vertical
    if m[0][col] == m[1][col] == m[2][col]:
        return m[row][col]
    # check diagonals
    cell = (row, col)
    if cell in ((0,0), (1,1), (2,2)) and m[0][0] == m[1][1] == m[2][2]:
        return m[row][col]
    if cell in ((2,0), (1,1), (0,2)) and m[2][0] == m[1][1] == m[0][2]:
        return m[row][col]
    # no winner, returns None
    return None

然后修改on_click功能:

def on_click(event):
    global m
    global k
    row = event.y // size
    col = event.x // size
    if m[row][col] == 0:
        cx = col * size + size // 2
        cy = row * size + size // 2
        # determine current player
        player = 1 + k % 2
        if player == 1:
            draw_X(cx, cy)
            print("Player 1, X")
        else:
            draw_O(cx, cy)
            print("Player 2, O")
        m[row][col] = player
        k += 1
        # only need to check winner after 5 turns
        if k >= 5:
            winner = Win(row, col)
            msg = None
            if winner:
                msg = "Winner is player {}: {}".format(player, 'X' if player == 1 else 'O')
            elif k == 9:
                msg = "Tie game"
            if msg:
                tkinter.messagebox.showinfo("Tic Tac Toe", msg)
                reset_game()

对于键绑定:

w.bind('<Escape>', lambda e: ttt.destroy())
w.bind('R', reset_game)
w.bind('r', reset_game)
w.focus_set()   # Canvas need to get the focus in order to get the keyboard events
© www.soinside.com 2019 - 2024. All rights reserved.