Python Tkinter Tic Tac Toe:添加平局条件,绑定到键,停止游戏而不关闭画布

Python Tkinter Tic Tac Toe:添加平局条件,绑定到键,停止游戏而不关闭画布,python,tkinter,Python,Tkinter,随着一个Tic Tac Toe项目即将完成,我有一些关于绑定和添加领带条件的问题。我可以将函数绑定到和,它们工作正常,但我希望它们绑定到R和escape键(将游戏重置为R并关闭escape)。我也尝试过为tie条件添加一个变量k,但它表示尚未定义它。代码如下: from tkinter import * import tkinter.messagebox ttt = Tk() ttt.title("Tic Tac Toe") w = Canvas(ttt, width = 902, height

随着一个Tic Tac Toe项目即将完成,我有一些关于绑定和添加领带条件的问题。我可以将函数绑定到和,它们工作正常,但我希望它们绑定到R和escape键(将游戏重置为R并关闭escape)。我也尝试过为tie条件添加一个变量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()
从tkinter导入*
导入tkinter.messagebox
ttt=Tk()
ttt.标题(“Tic Tac Toe”)
w=画布(ttt,宽度=902,高度=902)
w、 配置(bg=“白色”)
w、 包()
m=[[0,0,0],[0,0,0],[0,0,0]]
尺寸=300
玩家=1
w、 创建线(0,300,902,300,fill=“黑色”)
w、 创建线(0601902601,fill=“黑色”)
w、 创建_线(300,0,300,902,fill=“黑色”)
w、 创建线(6010601902,fill=“黑色”)
单击时的def(事件):
全球m
全球玩家
全局k
行=事件。y//大小
col=event.x//size
如果m[行][列]==0:
cx=列*大小+大小//2
cy=行*大小+大小//2
如果player==1:
绘制X(cx,cy)
打印(“播放器1,X”)
其他:
抽签(cx,cy)
打印(“玩家2,O”)
m[行][列]=玩家
赢()
如果player==1,则player=2,否则为1
k=k+1
def图纸O(x,y):
半径=大小//3
w、 创建椭圆(x-半径,y-半径,x+半径,y+半径,宽度=5,标记='cell')
def draw_X(X,y):
半径=大小//3
w、 创建_线(x半径,y半径,x+半径,y+半径,宽度=5,标记='cell')
w、 创建_线(x+半径,y-半径,x-半径,y+半径,宽度=5,标记='cell')
def重置_游戏(事件):
全球m
全球玩家
w、 删除('单元格')
m=[[0,0,0],[0,0,0],[0,0,0]]
玩家=1
k=0
def tie():
如果(k==8):
tkinter.messagebox.showinfo(“Tic-Tac-Toe”、“Tie”)
def Win():
如果(m[0][0]==m[0][1]和m[0][0]==m[0][2]和m[0][0]!=0):
tkinter.messagebox.showinfo(“Tic Tac Toe”,“胜者是玩家”+str(m[0][0]))
ttt.destroy()
打印(“玩家”,str(m[0][0]),“获胜”)
elif(m[0][0]==m[1][0]和m[0][0]==m[2][0]和m[0][0]!=0):
tkinter.messagebox.showinfo(“Tic Tac Toe”,“胜者是玩家”+str(m[0][0]))
ttt.destroy()
打印(“玩家”,str(m[0][0]),“获胜”)
elif(m[1][0]==m[1][1]和m[1][0]==m[1][2]和m[1][0]!=0):
tkinter.messagebox.showinfo(“Tic Tac Toe”,“胜者是玩家”+str(m[1][0]))
ttt.destroy()
打印(“玩家”,str(m[1][0]),“获胜”)
elif(m[0][1]==m[1][1]和m[0][1]==m[2][1]和m[0][1]!=0):
tkinter.messagebox.showinfo(“Tic Tac Toe”,“胜者是玩家”+str(m[0][1]))
ttt.destroy()
打印(“玩家”,str(m[0][1]),“获胜”)
elif(m[0][2]==m[1][2]和m[0][2]==m[2][2]和m[0][2]!=0):
tkinter.messagebox.showinfo(“Tic Tac Toe”,“胜者是玩家”+str(m[0][2]))
ttt.destroy()
打印(“玩家”,str(m[0][2]),“获胜”)
elif(m[2][0]==m[2][1]和m[2][0]==m[2][2]和m[2][0]!=0):
tkinter.messagebox.showinfo(“Tic Tac Toe”,“胜者是玩家”+str(m[2][0]))
ttt.destroy()
打印(“玩家”,str(m[2][0]),“获胜”)
elif(m[0][0]==m[1][1]和m[0][0]==m[2][2]和m[0][0]!=0):
tkinter.messagebox.showinfo(“Tic Tac Toe”,“胜者是玩家”+str(m[0][0]))
ttt.destroy()
打印(“玩家”,str(m[0][0]),“获胜”)
elif(m[0][2]==m[1][1]和m[0][2]==m[2][0]和m[0][2]):
tkinter.messagebox.showinfo(“Tic Tac Toe”,“胜者是玩家”+str(m[0][2]))
ttt.destroy()
打印(“玩家”,str(m[0][2]),“获胜”)
w、 绑定(“”,单击时)
def关闭(事件):
ttt.destroy()
w、 绑定(“”,关闭)
w、 绑定(“”,重置游戏)
ttt.mainloop()

我还想在有人赢了或者平局后停止比赛,而不关闭画布,这样我就可以重置。有什么办法吗?

既然你已经添加了全局变量
k
作为游戏的回合数,
player
可以通过
k
的值来确定,所以它可以从全局变量中删除

您需要声明全局变量
k

m = [[0,0,0], [0,0,0], [0,0,0]]
size = 300
k = 0
您还可以简化/修改函数
Win
,以接受
作为参数,并返回是否有赢家:

 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
然后单击功能上的修改

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
w.bind(“”,lambda e:ttt.destroy())
w、 绑定('R',重置\U游戏)
w、 绑定('r',重置\U游戏)
w、 focus_set()#画布需要获得焦点才能获得键盘事件

“停止游戏”它是交互式的,那么您想停止什么?我可能没有很好地解释(或者根本没有解释)。如果满足赢的条件,将弹出一个赢家的窗口。如果关闭该窗口,仍然可以单击其他空框。这就是为什么我在每次获胜后都添加了“ttt.destroy()”,但我想更改它。基本上,我想在每次胜利或平局后禁用游戏,这样我就可以使用键重置游戏,而不必再次运行代码。“想要禁用游戏”:您可以使用使
funcid=w.bind(“”,
处于非活动状态。好的,谢谢!成功了。现在只有另外两个问题我还没有解决。