[Tutor] Times Tables Program that constantly tells you that you are wrong!

Alan Gauld alan.gauld at yahoo.co.uk
Thu Aug 16 05:11:23 EDT 2018


On 16/08/18 08:18, Matthew Polack wrote:

> The last remaining issue is the program does not calculate the percentage
> right when you make mistakes...it just keeps giving a result of 100%.

> def percentCheck():
>     global percentScore
>     global score
>     global mistakes
>     global total

While you do need some globals in your program you only
need to declare the ones you are changing. In this case
you only need to declare percentScore as global.

>     percentScore = float(score/total) * 100

To debug this I would add a print line such as

print(score, total)

Since if you always get 100 it suggests that score
and total are the same.

One problem here is that you are converting to float
after doing the division. That's usually the wrong
thing to do. In fact I notice you do that a lot of
conversions on expressions. Its much safer to do the
conversions on the individual values then perform
the computation after the conversion.

In fact in this case (and most of the other similar
cases) you should not need the float conversion since
you already converted the values when you read them
from the GUI. You should aim to convert the data
into the correct type as soon as possible then you
will not need to use conversions anywhere else.

Some more observations below...

>     viewPercent()
> 
> 
> def makeproblem():
>     # deletes anything in text box from location 00 to the end
>     global answer # access global answer
> 
>     txt.delete(0.0, 'end')
> 
>     sentence = "Here is your problem "
> 
>     number1 = random.randint(2,12)
>     number2 = random.randint(2,12)
> 
>     answer = number1 * number2
> 
>     txt.insert(0.0, sentence)
>     txt.insert(2.2, number1)
>     txt.insert(3.3, " x ")
>     txt.insert(4.4, number2)
> 
> def checkanswer():
>     # deletes anything in text box from location 00 to the end
>     txt.delete(0.0, 'end')
> 
>     global answer
>     global score
>     global wrong
>     global mistakes
>     global percentScore
>     global total
> 
>     # checks for what is written in answerbox
>     response = int(answerbox.get())
>     wordScore = "Your score is now "
> 
>     if response == answer:
>         score = int(score + 1)
>         total = int(total + 1)
....
>     else :
>         score= int(score + 1)
>         total = int(total + 1)

Notice that regardless of what the answer is
you update both score and total. And again you
don't need the int() conversions, the variables
are already integers.

> root = Tk()
> root.geometry("640x700+0+0")
> root.title("Times Tables")
> 
> 
> #HOW CAN I CENTRE THE TEXT???
> txt = Text(root, width=35, height=8, wrap=WORD, font=("arial", 24, "bold"))
> txt.grid(row=12, columnspan=2, sticky=EW )

AS per Peter's link you need to create a tag and configure
it with the font and justification you want. Then when you
insert the text you add the tag name.

eg:

center = txt.tag_config("center", justify="center")
txt.insert(1.0, "Hello world", "center")


> blankline3 = Label(root, text = "", bg = "white")
> blankline3.grid(row=17, sticky='ew')

I'm not sure what this is for. If you want some space
just add some padding to the label below.

> scorelab = Label(root, text="Score", bg="green", fg="white", font=("arial",
> 20, "bold"))
> scorelab.grid(row=18, column=0, sticky=E)

Note that you create a Label here, but in ViewSC below you create
another label which causes this one to be deleted. This is not
necessary, instead just change the text of this label in viewSC.

scorelab['text'] = "New text here"

> totalLab = Label(root, text="Out of", bg="purple", fg="white",
> font=("arial", 20, "bold"))
> totalLab.grid(row=19, column=0, sticky=E)

Same applies to the other viewXXX functions, just update these
labels, don't build and destroy new label widgets each time.
That's a lot of wasted work and time for your PC.

> def viewSC():
>     global score

You don't change score so no need for global here.
You only need global when changing the data.

>     scoreViewLab = Label(root, text=score, fg="black", bg="grey",
> font=("arial", 20, "bold"))
>     scoreViewLab.grid(row=18, column=1, sticky=W)

I just noticed this is in a different grid location,
but the principle still applies create it once at the
start of the GUI then update it in the view functions.

> def viewTotal():
>     global total
>     #scoreViewLab=Label(root, scoreView, textvariable=scoreView)
>     totalViewLab = Label(root, text=total, fg="black", bg="grey",
> font=("arial", 20, "bold"))
>     totalViewLab.grid(row=19, column=1, sticky=W)
> 
> def viewWrong():
>     global wrong
>     global mistakes
> 
>     #scoreViewLab=Label(root, scoreView, textvariable=scoreView)
>     wrongViewLab = Label(root, text=mistakes, fg="black", bg="grey",
> font=("arial", 20, "bold"))
>     wrongViewLab.grid(row=20, column=1, sticky=W)

You declare wrong as global but never use it.
Should this function not be called viewMistakes?

> def viewPercent():
>     global percentScore
>     global total
>     global score
>     #scoreViewLab=Label(root, scoreView, textvariable=scoreView)
>     percentViewLab = Label(root, text=percentScore, fg="black", bg="grey",
> font=("arial", 20, "bold"))
>     percentViewLab.grid(row=21, column=1, sticky=W)

> viewSC()
> viewWrong()
> viewPercent()
> viewTotal()
> 
> root.mainloop(
While your code sort of works its doing an awful
lot of work that it doesn't need to do. You need
to stop and think through why you use each global
and type conversions and only keep the ones you
really need.

Similarly you should only need to create the
widgets once when you build the GUI. After that
its just a matter of updating the content.


-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos




More information about the Tutor mailing list