pythonmathtkinter

Why does the op integer not change when the buttons are pressed?


I have found a bug I can't fix. The program is meant to give you maths sums to solve and I was using buttons that sent an int as a value from 1 to 4 then that is tested in the guess function to generate the next question. The problem is that the int is not changing when the buttons are pressed and every sum is an addition one because it is set as 1 in the root.

from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from random import randint

def plus(*args):
    op = 1

def minus(*args):
    op = 2

def times(*args):
    op = 3

def divide(*args):
    op = 4

def  guess(*args):
    try:
        numberguess = int(ans.get())
    except ValueError:
        ask.set('That is not a number!')
    
    global number
    gdif = number - numberguess

    if gdif == 0:
        ask.set('You got it right!')
        global score
        sco = score.get() + 1
        score.set(sco)
        result = messagebox.askquestion('', 'Next question')
        if result == 'yes':
            if top.get() == 0:
                noone = randint(1,10)
                notwo = randint (1,10)
            else:
                noone = randint(1,top.get())
                notwo = randint(1,top.get())
            ans_entry.focus()
            if op == 1:
                number = noone + notwo
                numb.set('What is ' + str(noone) + ' + '+ str(notwo) + '?')
            elif op == 2:
                number = noone - notwo
                numb.set('What is ' + str(noone) + ' - '+ str(notwo) + '?')
            elif op == 3:
                number = noone * notwo
                numb.set('What is ' + str(noone) + ' x '+ str(notwo) + '?')
            elif op == 4:
                number = noone / notwo
                numb.set('What is ' + str(noone) + ' / '+ str(notwo) + '?')
        elif result == 'no':
            root.destroy()
    elif gdif>0:
        ask.set(ans.get() + ' is too low')
    elif gdif<0:
        ask.set(ans.get() + ' is too high')
    ans.set('')
        
root = Tk()
root.title('Maths Game') #window title
mainframe = ttk.Frame(root, padding = '3 3 12 12')
mainframe.grid(column = 0, row = 0, sticky = (N, W, E, S))
mainframe.columnconfigure(0,weight = 1)
mainframe.rowconfigure(0, weight = 1)
#organises grid well

ans = StringVar()
numb = StringVar()
ask = StringVar()
pts = StringVar()
score = IntVar()
top = IntVar()
#sets as variables

ans_entry = ttk.Entry(mainframe, width = 7, textvariable = ans) #defines          guess entry
ans_entry.grid(column = 2, row = 1, sticky = (W, E)) #places guess entry on grid
ttk.Label(mainframe, textvariable = numb).grid(column = 2, row = 2, sticky = (W, E)) #label
ttk.Label(mainframe, textvariable = ask).grid(column = 3, row = 1, sticky = (W, E)) #label
ttk.Label(mainframe, textvariable = score).grid(column = 3, row = 2, sticky = (E)) #label
ttk.Label(mainframe, textvariable = pts).grid(column = 4, row = 2, sticky = (W, E))
ttk.Button(mainframe, text = 'Answer', command = guess).grid(column = 3, row = 3, sticky = (W, E)) #guess button
top_entry = ttk.Entry(mainframe, width = 3, textvariable = top)
top_entry.grid(column = 3, row = 4, sticky = (E))
ttk.Button(mainframe, text = '+', command = plus).grid(column = 1, row = 5, sticky = (W, E))
ttk.Button(mainframe, text = '-', command = minus).grid(column = 2, row = 5, sticky = (W, E))
ttk.Button(mainframe, text = 'x', command = times).grid(column = 3, row = 5, sticky = (W, E))
ttk.Button(mainframe, text = '/', command = divide).grid(column = 4, row = 5, sticky = (W, E))

for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5)                       #pads grid nicely
ans_entry.focus() #cursor starts in box
root.bind('<Return>', guess) #binds entry key to guess button

noone = randint(1,10)
notwo = randint (1,10)
number = noone + notwo
numb.set('What is ' + str(noone) + ' + '+ str(notwo) + '?')
right = False
sco = 0
score.set(sco)
pts.set(' points')
one = 10
op = 1

root.mainloop() #launches main code

Solution

  • Because op is a local variable in every function.

    You should add global op:

    def plus(*args):
        global op
        op = 1
    
    .
    .
    .
    

    But be aware that this is a very sub-optimal way of doing it. It makes much more sense to have a class, then have these functions as its methods. That way they will all have access to the op variable without it having to be a global.