简体   繁体   English

Python函数/按钮参考/范围错误

[英]Python Function/Button Reference/Scope Error

I'm trying to create a simple card game. 我正在尝试创建一个简单的纸牌游戏。 It features a main menu with 4 buttons and 2 images.The 4 buttons are war , garbage , instruct , and quit_exe . 它具有一个主菜单,带有4个按钮和2个图像。这4个按钮是wargarbageinstructquit_exe The war button should command=self.game_war when it is clicked, and the same for garbage. 当单击war按钮时,应该为command=self.game_war ,对于垃圾也应如此。 instruct should show how to play, and quit_exe should simply quit the application. instruct应该显示如何播放,而quit_exe应该只是退出应用程序。 Let's take war for this problem I have. 让我们为我war的这个问题而war

The Goal 目标

I need to have, when clicked, war execute the def game_war(self) function when it is clicked. 单击时,我需要war执行def game_war(self)函数。 When this is clicked, it should grid_forget() all the widgets so that it can generate widgets for the game of war . 单击此按钮后,它应该grid_forget()所有小部件,以便它可以为war游戏生成小部件。 It should also, when a button called return is clicked, it clears the widgets, and then regenerates the main menu. 当单击一个名为return的按钮时,它也应该清除小部件,然后重新生成主菜单。

Requirements 要求

It needs to be able to start a game based on a button being clicked, and the game functions should be able to use the variables already referenced to use, overwrite, and save those variables, so that it can forget the widgets and place new ones. 它需要能够基于被单击的按钮启动游戏,并且游戏功能应该能够使用已经引用的变量使用,覆盖和保存这些变量,以便它可以忘记小部件并放置新的小部件。 。 When the game ends , it should forget the current widgets, use the pre-referenced variables , then regenerate the main menu. 游戏结束时 ,应该忘记当前的小部件, 使用预先引用的变量 ,然后重新生成主菜单。

The Problems 问题所在

I get a local variable referenced before assignment error. 我在分配错误之前得到了引用的局部变量。 I tried using nonlocal and global , but it doesn't seem to work. 我尝试使用nonlocalglobal ,但似乎不起作用。 I need this as this is a requirement. 我需要这个,因为这是必需的。

Summary 摘要

I need to be able to execute a function that can grab and use variables. 我需要能够执行一个可以捕获和使用变量的函数。 In this case, I need war to call game_war , which can access the war , instruct , quit_exe , garbage , usrCrd , and cpuCrd variables to clear them out, then to generate new variables for the game, and then when the game ends, regenerate the main menu widgets. 在这种情况下,我需要war来调用game_war ,它可以访问warinstructquit_exegarbageusrCrdcpuCrd变量以清除它们,然后为游戏生成新变量,然后在游戏结束时重新生成主菜单小部件。

import tkinter
import winsound
from tkinter import *
from PIL import Image, ImageTk
from random import randint, randrange

class CardGame(tkinter.Frame):

  def __init__(self, root):

    tkinter.Frame.__init__(self, root)

    #define variables for cards
    crdImg = []
    usrStk = None
    cpuStk = None

    #define card images
    i = 1
    while i < 57:
      i = i + 1
      crdImg.append('img/cards/%s.png' % (i - 1))

    usrStk = crdImg[54]
    cpuStk = crdImg[55]

    #define card stacks
    usrCrdImg = Image.open(usrStk)
    usrCrdBg = ImageTk.PhotoImage(usrCrdImg)
    usrCrd = tkinter.Label(root, image=usrCrdBg)
    usrCrd.image = usrCrdBg

    cpuCrdImg = Image.open(cpuStk)
    cpuCrdBg = ImageTk.PhotoImage(cpuCrdImg)
    cpuCrd = tkinter.Label(root, image=cpuCrdBg)
    cpuCrd.image = cpuCrdBg

    #define empty cell generation
    def empCell(px, py, r, c):
      grid(padx=px, pady=py, row=r, column=c)

    #define buttons
    war = tkinter.Button(self, text="Play War!", command=self.game_war)
    garbage = tkinter.Button(self, text="Play Caravan!", command=self.game_garbage)
    instruct = tkinter.Button(self, text="How to Play", command=self.instruct)
    quit_exe = tkinter.Button(self, text="Quit", command=quit)

    #define layout
    usrCrd.grid(row=1, column=1)
    cpuCrd.grid(row=1, column=4)
    war.grid(row=2, column=2)
    garbage.grid(row=3, column=2)
    instruct.grid(row=4, column=2)
    quit_exe.grid(row=5, column=2)

  #define game functions
  def game_war(self):

    war.grid_forget()
    garbage.grid_forget()
    instruct.grid_forget()
    quit_exe.grid_forget()
    usrCrd.grid_forget()
    cpuCrd.grid_forget()
    print("Debug")

  def game_garbage(self):

    print("Debug")

  def instruct(self):

    print("Debug")

if __name__=='__main__':
  root = Tk()
  root.columnconfigure(1, weight=1)
  root.rowconfigure(1, weight=1)
  CardGame(root).grid(row=5, column=3)
  root.wm_title('Card Game')
  root.mainloop()

You are not saving any variables as instance variables -- they are all local. 您没有将任何变量另存为实例变量-它们都是局部变量。 If you want to save a variable so that you can use it in other methods, save it as an instance: 如果要保存变量以便可以在其他方法中使用它,请将其另存为实例:

self.war = Button(self, text="Play War!", command=self.game_war)
self.garbage = Button(self, text="Play Caravan!", command=self.game_garbage)
self.instruct = Button(self, text="How to Play", command=self.instruct)
self.quit_exe = Button(self, text="Quit", command=quit)
...
self.war.grid_forget()
self.garbage.grid_forget()
self.instruct.grid_forget()
self.quit_exe.grid_forget()

... and so on. ... 等等。

On a side note, you should pick a single method of importing tkinter instead of importing it twice. 附带说明,您应该选择一种导入tkinter的方法,而不是两次导入。 I recommend "import tkinter as tk", and then use "tk." 我建议“将tkinter导入为tk”,然后使用“ tk”。 as a prefix to every widget, because global imports can lead to unclear code. 作为每个小部件的前缀,因为全局导入会导致代码不清晰。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM