Please give me some pointers on my first Python program!
Points of interest:
- Within the
calculate()
function, I wanted to returncorrectAnswer
in order to avoid using it as a global variable. When passingcalculate
toisCorrect()
, I would get a TypeError: missing 1 required positional argument. After a ton of searching I wasn't able to avoid using the global variable. - This leads me to the point on global variables: I tried my darnest to avoid using them across the board but I must be missing something obvious that's preventing me from understanding how to do so.
- I will be honest, I didn't place much time on the
playAgain()
function but not because I didn't want to--I just didn't have many ideas of what I wanted. Any pointers on a better "restart" button are welcomed.
from tkinter import Entry
import tkinter as tk
import random as rand
import sys
import os
root = tk.Tk()
root.geometry("450x250+500+300")
root.title("Let's play Math!")
welcomeLabel = tk.Label(text="LET'S PLAY MATH!").pack()
startLabel = tk.Label(text='Select a math operation to start').pack()
def genRandom():
a = rand.randrange(1,10,1)
b = rand.randrange(1,10,1)
return a, b
def calculate(method):
global correctAnswer
ranNumber = genRandom()
if method == "Add":
correctAnswer = int(ranNumber[0] + ranNumber[1])
calcString = "+"
elif method == "Sub":
correctAnswer = int(ranNumber[0] - ranNumber[1])
calcString = "-"
QuestionLbl = tk.Label(text="What does {0} {1} {2} equal?".format(ranNumber[0], calcString, ranNumber[1]))
QuestionLbl.place(x=0, y=125)
global answerEntry
answerEntry = Entry()
answerEntry.place(x=300, y=125)
isCorrectBtn = tk.Button(text="Check Answer", command=isCorrect)
isCorrectBtn.place(x=300, y = 150)
def isCorrect():
answerEntered = int(answerEntry.get())
if answerEntered != correctAnswer:
checkAnswerLbl = tk.Label(text="Let's try again.")
checkAnswerLbl.place(x=150, y=125)
elif answerEntered == correctAnswer:
checkAnswerLbl = tk.Label(text="Hooray!")
checkAnswerLbl.place(x=150, y=125)
restartBtn = tk.Button(text="Play Again?", command=playAgain)
restartBtn.place(x=300, y = 200)
def playAgain():
python = sys.executable
os.execl(python, python, * sys.argv)
addBtn = tk.Button(text="Addition", command=lambda: calculate("Add"))
addBtn.place(x=160, y = 60)
subBtn = tk.Button(text="Subtraction", command=lambda: calculate("Sub"))
subBtn.place(x=220, y=60)
tk.mainloop()
Through some research I've updated the following:
- Per Simple addition, multiplication, division, and subtraction program, the generation of 2 random numbers occurs on it's own function.
- Combined the addition and subtraction code into one function, implemented a "restart" button from the examples provided on a question I asked on SO; you can see the first stages of my code here.
Thanks to @Shule, I've settled on using the code below. I added some comments of my own, moved some stuff around to try to make a bit more sense of what's going on, and also created the rightWrongTxt
string. However, @Shule deserves most of the credit for making this code better.
import tkinter as tk
import random as rand
class Game:
def __init__(self):
# Initializing the widgets and the variables you want to access from multiple methods
self.root = tk.Tk()
#defining actual dimensions of the window
self.root.geometry("450x250+500+300")
#window title; does not require .pack()
self.root.title("Let's play Math!")
#LABELS
#.pack() will display labels in the middle of the screen
self.welcomeLbl = tk.Label(text="LET'S PLAY MATH!")
self.welcomeLbl.pack()
self.startLbl = tk.Label(text='Select a math operation to start')
self.startLbl.pack()
self.QuestionLbl = tk.Label()
self.rightWrongLbl = tk.Label()
self.rightWrongTxt = tk.StringVar()
#BUTTONS
self.addBtn = tk.Button(text="Addition", command=lambda: self.calculate("Add"))
self.addBtn.place(x=150, y=60)
self.subBtn = tk.Button(text="Subtraction", command=lambda: self.calculate("Sub"))
self.subBtn.place(x=225, y=60)
self.isCorrectBtn = tk.Button(text="Check Answer", command=self.isCorrect)
self.restartBtn = tk.Button(text="Play Again?", command=self.playAgain)
#INPUT BOX
self.answerEntry = tk.Entry()
self.answerEntry.focus_set()
#ADDITIONAL VARIABLES
self.correctAnswer = None
def genRandom(self):
a = rand.randrange(1,10,1)
b = rand.randrange(1,10,1)
return a, b
def calculate(self, method):
self.addBtn.config(state='disabled')
self.subBtn.config(state='disabled')
randNum = self.genRandom()
if method == "Add":
self.correctAnswer = int(randNum[0] + randNum[1])
calcString = "+"
elif method == "Sub":
self.correctAnswer = int(randNum[0] - randNum[1])
calcString = "-"
#Question generation
self.QuestionLbl.config(text="What does {0} {1} {2} equal?".format(randNum[0], calcString, randNum[1]))
self.QuestionLbl.place(x=0, y=125)
self.answerEntry.place(x=300, y=125)
self.isCorrectBtn.place(x=300, y=150)
def isCorrect(self):
try:
answerEntered = int(self.answerEntry.get())
except ValueError:
self.rightWrongTxt.set("Non-numeric input. \nEnter numbers only.")
self.rightWrongLbl.config(textvariable = self.rightWrongTxt)
self.rightWrongLbl.place(x=150, y=125)
if answerEntered != self.correctAnswer:
self.rightWrongTxt.set("Let's try again.")
self.rightWrongLbl.config(textvariable = self.rightWrongTxt)
self.rightWrongLbl.place(x=150, y=125)
elif answerEntered == self.correctAnswer:
self.rightWrongTxt.set("Hooray!")
self.rightWrongLbl.config(textvariable = self.rightWrongTxt)
self.rightWrongLbl.place(x=150, y=125)
self.restartBtn.place(x=300, y=200)
def playAgain(self):
self.rightWrongLbl.config(text="Let's try again.")
self.addBtn.config(state='active')
self.subBtn.config(state='active')
self.answerEntry.place_forget()
self.answerEntry.delete(0, "end")
self.QuestionLbl.place_forget()
self.isCorrectBtn.place_forget()
self.rightWrongLbl.place_forget()
self.restartBtn.place_forget()
if __name__ == '__main__':
game = Game()
game.root.mainloop()