【问题标题】:Tic Tac Toe Python Tkinter Display "X" and "Y"井字游戏 Python Tkinter 显示“X”和“Y”
【发布时间】:2021-03-09 22:12:19
【问题描述】:

我已经开始用 Python 为 Tkinter 制作一个井字游戏。基本上在这一点上,它并不需要获胜,而只是具有基本功能。左键单击放置一个“X”,右键单击放置一个“O”。按“C”应该清除电路板,并且应该使用标签和绑定来完成。我在显示“X”和“O”时遇到了问题,我确实画了板。我尝试单击第一行,但没有任何反应。

它应该像这样工作:https://youtu.be/0x6HKuyXAuU

from tkinter import *
from tkinter import ttk


root = Tk()
root.title("Tic Tac Toe")

message = StringVar()

# This is the portion that draws out the grid used in Tic Tac Toe

label1 = ttk.Label(root, text="")
label1.grid(row=1, column=0)
label2 = ttk.Label(root, text="|")
label2.grid(row=1, column=1)
label3 = ttk.Label(root, text="")
label3.grid(row=1, column=2)
label4 = ttk.Label(root, text="|")
label4.grid(row=1, column=3)
label5 = ttk.Label(root, text="-")
label5.grid(row=4, column=1)
label6 = ttk.Label(root, text="-")
label6.grid(row=4, column=2)
label7 = ttk.Label(root, text="-")
label7.grid(row=4, column=3)
label8 = ttk.Label(root, text="-")
label8.grid(row=4, column=4)
label9 = ttk.Label(root, text="       ")
label9.grid(row=5, column=0)
label10 = ttk.Label(root, text="|")
label10.grid(row=5, column=1)
label11 = ttk.Label(root, text="       ")
label11.grid(row=5, column=2)
label12 = ttk.Label(root, text="|")
label12.grid(row=5, column=3)
label13 = ttk.Label(root, text="-")
label13.grid(row=6, column=1)
label14 = ttk.Label(root, text="-")
label14.grid(row=6, column=2)
label15 = ttk.Label(root, text="-")
label15.grid(row=6, column=3)
label16 = ttk.Label(root, text="-")
label16.grid(row=6, column=4)
label17 = ttk.Label(root, text="       ")
label17.grid(row=7, column=0)
label18 = ttk.Label(root, text="|")
label18.grid(row=7, column=1)
label19 = ttk.Label(root, text="       ")
label19.grid(row=7, column=2)
label20 = ttk.Label(root, text="|")
label20.grid(row=7, column=3)

#This is the code that draws out the O and X in this the first row
label21 = ttk.Label(root, text="")
label21.grid(row=1, column=0)
label21.bind("<Button-1>", lambda e: message.set("X"))
label21.bind("<Button-3>", lambda e: message.set("O"))
label22 = ttk.Label(root, text="")
label22.grid(row=1, column=1)
label22.bind("<Button-1>", lambda e: message.set("X"))
label22.bind("<Button-3>", lambda e: message.set("O"))
label22.grid(row=1, column=3)
label22.bind("<Button-1>", lambda e: message.set("X"))
label22.bind("<Button-3>", lambda e: message.set("O"))

root.mainloop()

【问题讨论】:

  • 你为什么使用标签而不是按钮?有具体原因吗?您还知道您实际上没有在任何标签中使用message
  • 我们的老师告诉我们不要使用按钮,只使用标签和装订。
  • 我编辑了我的答案以使用按钮。顺便说一句,如果您使用标签,则必须添加边框,以便标签看起来不像 1。按钮没有这个问题。

标签: python user-interface tkinter computer-science bind


【解决方案1】:

使用循环而不是像这样创建大量变量和标签:

这是一个你可以改进的例子:

from tkinter import *

def updateX(event):
    event.widget['text'] = 'X'

def updateO(event):
    event.widget['text'] = 'O'
    
root = Tk()
root.title("Tic Tac Toe")

for x in range(5):
    for y in range(5):
        label = Label(root)

        if x%2==0:
            if y%2!= 0:
                label['text'] = '|'

            else:
    
                label.bind('<1>', updateX)
                label.bind('<Button-3>', updateO)
                root.grid_columnconfigure(y, weight=1)
                root.grid_rowconfigure(x, weight=1)

        else:
            label['text']='-'

        label.grid(column=y, row=x, sticky="nsew")

root.mainloop()

你的 clear 函数可以是这样的:

def clear(event):
    for item in root.winfo_children():
        if isinstance(item, Label) and item['text'] in ['O', 'X']:
            item['text'] = ''

别忘了将&lt;c&gt;绑定到root。

【讨论】:

  • 你为什么不把bd=3, relief="groove"加到标签上。这将添加一个边框。此外,如果您将所有标签存储在一个列表中,这样您就不必使用root.winfo_children()
  • @TheLizzard 你可以这样做。但是OP发布的视频链接没有边框。当窗口中有其他小部件时,可以将标签存储在列表中。但是,我猜不会有,因为这看起来像一个任务。所以使用 root.winfo_children() 会很好,如果 OP 愿意,OP 也可以删除 isinstance(item, Label)
【解决方案2】:

试试这个:

from functools import partial
import tkinter as tk


def change_text(button, text, event=None):
    # Only if the button is empty
    if button.cget("text") == "":
        # Change the button's text to whatever is in the variable `text`
        button.config(text=text)

def clear(event=None):
    for button in buttons:
        button.config(text="")


# Create the tkinter window
root = tk.Tk()
# A list to store all of the buttons
buttons = []

for i in range(9):
    # Create the button:
    button = tk.Label(root, text="", width=3, font=("", 15), bd=3,
                      relief="groove")

    # 1st parameter of `partial` is the function. The rest are just arguments
    command = partial(change_text, button, "X")
    button.bind("<Button-1>", command) # Left click

    command = partial(change_text, button, "O")
    button.bind("<Button-3>", command) # Right click

    # Display the button:
    button.grid(row=i//3, column=i%3)
    # Add the button to the list of buttons:
    buttons.append(button)

clear_button = tk.Label(root, text="Clear screen", width=3, font=("", 15), bd=3,
                        relief="groove")
clear_button.grid(row=4, column=0, columnspan=3, sticky="news")
clear_button.bind("<Button-1>", clear) # Left click

# Run tkinter's mainloop
root.mainloop()

有关partial 工作原理的更多信息,请阅读this

【讨论】:

    【解决方案3】:

    您的绑定lambda 只是更新了那些标签从未使用过的message 变量。

    您可以使用带有边框的Label 小部件来模拟游戏板。最好使用listdict 来存储这些标签以供以后参考,例如通过按c 字符来清除游戏板。

    下面是一个修改过的例子:

    import tkinter as tk
    from tkinter import ttk
    
    root = tk.Tk()
    root.title("Tic Tac Toe")
    
    def set_cell(lbl, mark):
        if lbl["text"] == "":
            lbl["text"] = mark
    
    def clear(event):
        for lbl in cells.values():
            lbl["text"] = ""
    
    cells = {} # for storing the labels
    # create the 3 x 3 board using labels
    for row in range(3):
        for col in range(3):
            lbl = ttk.Label(root, width=3, borderwidth=1, relief="solid", font="Arial 32 bold", anchor="c")
            lbl.grid(row=row, column=col, sticky="nsew")
            lbl.bind("<Button-1>", lambda e: set_cell(e.widget, "X"))
            lbl.bind("<Button-3>", lambda e: set_cell(e.widget, "O"))
            cells[row,col] = lbl # store the label
    
    root.bind("c", clear)
    root.mainloop()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-04
      • 1970-01-01
      • 1970-01-01
      • 2014-04-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多