I am trying to create a small hangman game in tkinter and unfortunately my 'chances' variable is not playing nice and is somewhat preventing me from continuing. I was wondering if anyone could take a look at the code and see what's going on and how to fix it! (getting an error saying it's undefined however I've tried several attempts to fix it without success)
from tkinter import *
from tkinter import messagebox
import random
#Defines the main application size, title, and resizeability with name 'window'
window = Tk()
window.geometry('450x250')
window.resizable(False, False)
window.title("Hangman")
window.canvas = Canvas(window, width=450, height=250)
window.canvas.pack()
def gameEasy(*args):
hangman = Tk()
hangman.geometry('450x200')
hangman.resizable(False, False)
hangman.title("Hangman")
hangman.canvas = Canvas(hangman, width=450, height=200)
hangman.canvas.pack()
hangman.canvas.create_line(50, 120, 70, 120)
hangman.canvas.create_line(59, 120, 59, 80)
hangman.canvas.create_line(59, 80, 39, 80)
hangman.canvas.create_line(39, 80, 39, 85)
wordlistEasy = '''cat dog apple stars movie hammer sprint farmer'''
wordlistEasy = wordlistEasy.split(' ')
word = random.choice(wordlistEasy)
letterguessed = []
chances = len(word) + 2
correct = 0
flag = 0
X1 = 75
Y1 = 120
X2 = 85
Y2 = 120
for i in word:
X1 += 12
X2 += 12
hangman.canvas.create_line(X1, Y1, X2, Y2, dash=(8,1))
def main_loop(*args):
Guess = str(GuessInput.get())
global chances
incorrectLabel.config(text="")
while chances != 0 and flag == 0:
chances -= 1
if not Guess.isalpha() and Guess != "":
incorrectLabel.config(text="Please input a LETTER!")
chances += 1
break
elif len(Guess) > 1 and (Guess != word):
incorrectLabel.config(text="Please input only one letter!")
chances += 1
break
elif (Guess in letterguessed) and Guess != "":
incorrectLabel.config(text="Letter already guessed!")
chances += 1
break
else:
letterguessed.append(Guess)
letterList.config(text=(letterguessed))
chancesLabel.config(text=f"Chances left: {chances}")
chances -= 1
break
GuessInput.delete(0,"end") #Resets the entry box after each input
GuessInput = StringVar()
GuessInput = Entry(hangman, width=8, bd="1")
GuessInput.place(x=15, y=31)
GuessInput.focus_force()
Guessbtn = Button(hangman, text="Guess", width=7, bd="1", command=main_loop).place(x=75, y=28)
hangman.bind('<Return>', main_loop)
lettersLabel = Label(hangman, text="Guessed letters:").place(x=220, y=5)
letterList = Label(hangman, text="")
letterList.place(x=220, y=20)
chancesLabel = Label(hangman, text=f"Chances left: {chances}")
chancesLabel.place(x=12, y=5)
incorrectLabel = Label(hangman, text="", fg="red")
incorrectLabel.place(x=12, y=52)
hangman.mainloop()
def exit(*args):
messagebox.showinfo("Thank You", "Thanks for playing!")
window.destroy()
mainlabel = Label(window, text="Welcome to Hangman", font=("Arial Bold",14)).place(x=120, y=5)
introMessage = Message(window, text="This is a simple hangman program using Tkinter. To play, simply select a difficulty, to leave, select quit!", width=280)
introMessage.place(x=80, y=30)
difficultyLabel = Label(window, text="Select a difficulty", font=("Arial Bold",9)).place(x=170, y=70)
easybtn = Button(window, text = "Easy", width=10, bd="1", command=gameEasy).place(x=182, y=95) #Defining a button with properties
hardbtn = Button(window, text = "Hard", width=10, bd="1").place(x=182, y=120) #Defining a button with properties
window.canvas.create_line(175,150,265,150)
rulesbtn = Button(window, text = "Rules", width=10, bd="1").place(x=182, y=155) #Defining a button with properties
quitbtn = Button(window, text = "Quit", width=10, bd="1", command=exit).place(x=182, y=180) #Defining a button with properties
window.mainloop()
Tried making chances global, tried swapping the ordering of the function call several different ways etc.
chances
is a local variable inside function gameEasy()
, so you should not declare it as global variable inside the nested function main_loop()
. You should declare it as nonlocal
variable instead.
Also avoid creating multiple instances of Tk()
. Use Toplevel()
for child windows.
def gameEasy(*args):
hangman = Toplevel() # use Toplevel() instead of Tk() for child window
...
def main_loop(*args):
...
nonlocal chances # declare chances as nonlocal variable
...
...