0

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. The war button should command=self.game_war when it is clicked, and the same for garbage. instruct should show how to play, and quit_exe should simply quit the application. Let's take war for this problem I have.

The Goal

I need to have, when clicked, war execute the def game_war(self) function when it is clicked. When this is clicked, it should grid_forget() all the widgets so that it can generate widgets for the game of war. It should also, when a button called return is clicked, it clears the widgets, and then regenerates the main menu.

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. 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.

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()
1
  • You don't need all of that code to reproduce your problem. Your question would be better if you removed all code that wasn't relevant. Commented Apr 10, 2015 at 16:28

1 Answer 1

2

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. I recommend "import tkinter as tk", and then use "tk." as a prefix to every widget, because global imports can lead to unclear code.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.