当前位置: 首页 > 知识库问答 >
问题:

蒂克塔克托·特金特圭不断崩溃

左丘峰
2023-03-14

我试图用Tkinter做一个简单的TicTacToe游戏,但我不能真正测试它,因为应用程序一直崩溃。我不能超过第二轮。谁能告诉我为什么它总是崩溃?在实现后()方法后,它似乎变得更好了一点,但是它仍然不能正常运行。

这是我的代码:

import tkinter as tk
from tkinter import messagebox
from random import randrange


# click function
def choose(event):
    global game_over
    if not game_over:
        if event.widget["state"] == "normal":
            event.widget.configure(text="O", disabledforeground="#0000ff", state="disabled")
            # check for winner
            window.after(1000, check)
            # let computer make its move
            if not game_over:
                window.after(1000, machine_move)
                # check again
                window.after(1000, check)
        elif event.widget["state"] == "disabled":
            messagebox.showerror("Field taken", "Please choose a different field")


# define machine move
def machine_move():
    global taken
    pick = randrange(1, 9)
    taken = True
    while taken:
        if button_dict[pick-1].cget("state") == "normal":
            button_dict[pick-1].configure(text="X", disabledforeground="#ff0000", state="disabled")
            taken = False


# check for winner function
def check():
    global game_over
    global inputs
    inputs = []
    for key in button_dict.keys():
        inputs.append(button_dict[key].cget("text"))
    # line win
    if inputs[0] == "X" and inputs[1] == "X" and inputs[2] == "X" \
    or inputs[3] == "X" and inputs[4] == "X" and inputs[5] == "X" \
    or inputs[6] == "X" and inputs[7] == "X" and inputs[8] == "X":
        messagebox.showinfo("Game over", "Line win by machine")
        game_over = True
    elif inputs[0] == "O" and inputs[1] == "O" and inputs[2] == "O" \
    or inputs[3] == "O" and inputs[4] == "O" and inputs[5] == "O" \
    or inputs[6] == "O" and inputs[7] == "O" and inputs[8] == "O":
        messagebox.showinfo("Game over", "Line win by you")
        game_over = True
    # row win
    elif inputs[0] == "X" and inputs[3] == "X" and inputs[6] == "X" \
    or inputs[1] == "X" and inputs[4] == "X" and inputs[7] == "X" \
    or inputs[2] == "X" and inputs[5] == "X" and inputs[8] == "X":
        messagebox.showinfo("Game over", "Row win by machine")
        game_over = True
    elif inputs[0] == "O" and inputs[3] == "O" and inputs[6] == "O" \
    or inputs[1] == "O" and inputs[4] == "O" and inputs[7] == "O" \
    or inputs[2] == "O" and inputs[5] == "O" and inputs[8] == "O":
        messagebox.showinfo("Game over", "Row win by you")
        game_over = True
    # check for diagonal win
    elif inputs[0] == "X" and inputs[4] == "X" and inputs[8] == "X" \
    or inputs[2] == "X" and inputs[4] == "X" and inputs[6] == "X":
        messagebox.showinfo("Game over", "Diagonal win by machine")
        game_over = True
    elif inputs[0] == "O" and inputs[4] == "O" and inputs[8] == "O" \
    or inputs[2] == "O" and inputs[4] == "O" and inputs[6] == "O":
        messagebox.showinfo("Game over", "Diagonal win by machine")
        game_over = True


# create window
window = tk.Tk()
window.title("TicTacToe")
window.geometry("450x480")


# create buttons

button_dict = {}
for i in range(9):
    new_button = tk.Button(window, text=" ", width=3, font=30)
    new_button.grid(column=i // 3, row=i % 3, ipadx=50, ipady=50)
    new_button.bind("<Button-1>", choose)
    button_dict[i] = new_button


# start game
game_over = False
button_dict[4].configure(text="X", disabledforeground="#ff0000", state="disabled")
window.mainloop()

共有1个答案

邵鸿福
2023-03-14

正如@Paul M在评论中所述,如果machine\u move函数中的pick变量恰好是已禁用的按钮的变量,其值将保持不变,while循环将无限期运行,导致程序挂起。要克服这一点,您可以尝试以下方法(这是解决此问题的众多解决方案之一)

def machine_move():
    available_buttons=[button_dict[i] for i in range(len(button_dict)) if button_dict[i].cget("state") == "normal"]
    pick = choice(available_buttons)
    pick.configure(text="X", disabledforeground="#ff0000", state="disabled")

所以,基本上列表available_buttons包含尚未禁用的按钮,变量选择是从列表中随机选择(使用random.choice()),然后相应地进行配置。

更新

我还注意到,您正在使用方法调用check(),这可能会导致在决定获胜者时出现重大延迟,有时如果在调用检查之前进行另一次移动,会导致多个获胜者克服这个问题,你可以试试这个(同样,这是解决这个问题的众多解决方案之一)

def choose(event):
    global game_over
    if not game_over:
        if event.widget["state"] == "normal":
            event.widget.configure(text="O", disabledforeground="#0000ff", state="disabled")
            # check for winner
            check()
            # let computer make its move
            if not game_over:
                window.after(1000, machine_move)
        elif event.widget["state"] == "disabled":
            messagebox.showerror("Field taken", "Please choose a different field")


# define machine move
def machine_move():
    available_buttons=[button_dict[i] for i in range(len(button_dict)) if button_dict[i].cget("state") == "normal"]
    pick = choice(available_buttons)
    pick.configure(text="X", disabledforeground="#ff0000", state="disabled")
    check()

调用check()在玩家或机器移动之后。

 类似资料:
  • 我正试图使用Kryo库来执行对象的深度复制,但我遇到了一个小问题。我想深度复制一个没有瞬态变量的对象。我知道可以将用于,如下所示: 但是我必须为每个类设置一个新的。我可以从Kryo获得一个默认的,并在那里设置吗?我尝试了类似的解决方案,但它什么也做不到:

  • 问题内容: 我被Wicket和Vaadin所折服。我正在开始一个微型ISV,需要选择Web框架。我将选择范围缩小到Wicket和Vaadin。我已经使用了两个框架,并且我都喜欢它们。但是我需要做出选择。 如果我选择Vaadin: 我不必担心外观。它带有不错的主题。 我将使用Java进行所有擅长的编程,而不必花费时间来攻克不太擅长的CSS。 我需要的大多数业务应用程序组件都是开箱即用的,包括桌面之类

  • 我一直试图使用Kontakt.io的示例Android应用程序(可在这个地址)来实现一个简单的应用程序,将连接到Kontakt信标,并更改诸如主要,次要,txPower等细节。我能够检测信标并读取上述所有内容的正确细节,但我无法更改它们。查看示例应用程序,步骤应该很简单,这就是我所做的 OnBeaconsDiscovery有一个BeaconDevice对象列表作为参数,因此我选择其中一个Beaco

  • 从技术上讲,< code>cron、< code>crontab和< code>cronjob之间有什么区别? 从我能收集到的信息来看,是服务器上的实用程序,是一个包含时间间隔和命令的文件,是实际的命令(或包含命令的文件/脚本)。 这是正确的吗?

  • 当我做crontab-l时,我可以看到我所有的工作。 总之我可以只提取“表情”吗? 我需要这样的外出…

  • 外企面试跟国内的厂还是差别挺大,包括微软也是基本不问八股。 一面结对编程:     面试之前会有邮件发你git仓库代码,有各种语言的,要求你在面试之前熟悉代码,配置好环境,了解单元测试。 面试开始后,双方自我介绍(很多厂面试官都不会自我介绍),然后会询问你是否之前熟悉了代码,并让你把代码正常跑起来。 如果没配置好环境跑不起来,可能结果会让你下次约面。 代码正常跑起来之后,面试官会问你是否了解TDD

  • 我试图在本页上编译并运行一个斯坦福NLP java示例:https://stanfordnlp.github.io/CoreNLP/api.html#quickstart-使用便利包装(第一个示例BasicPipeLine示例) 据说这个例子是为3.9.0开发的,但我哪里都找不到,所以我用的是3.9.2。 我在简单的scala构建工具下运行代码,因为进一步的工作将用scala编写。 我的身材。sb

  • 我正在使用cmake Gui构建开罗。当我点击“配置”时,Cmake显示以下错误: 找不到PIXMAN,尝试在系统变量PIXMAN中设置PIXMAN根文件夹的路径(缺少:PIXMAN_LIBRARIESPIXMAN_INCLUDE_DIRS) 找不到ZLIB(缺少:ZLIB_LIBRARYZLIB_INCLUDE_DIR) C:/cmake-3.7.0-rc1-win32-x86/share/cm