0

This is my code:

enter code here
def Game():
try:

    tkMessageBox.showinfo("Hello!", "Welcome To my Game, %name")
    root.destroy()

    colors = ['Red', 'Blue', 'Green', 'Pink', 'Orange', 'Black', 'Yellow', 
    'White', 'Purple', 'Brown']
    score = 0
    timeLeft = 30

    def startGame(event):
        global timeLeft
        if timeLeft == 30:
            countdown()

        nextColor()

    def nextColor():
        global score
        global timeLeft

        if timeLeft > 0:
            e.focus_set()
            if e.get().lower() == colors[1].lower():
                score += 1

        e.delete(0, Tkinter.END)
        random.shuffle(colors)
        label.config(fg=str(colors[1]), text=str(colors[0]))
        scoreLabel.config(text="Score: " + str(score))

    def countdown():
        global timeLeft

        if timeLeft > 0:
            timeLeft -= 1
            time.config(text="Time Left: " + str(timeLeft))
            time.after(1000, countdown)

this is the error i got

C:\Python27\python.exe D:/pythonaldecoa/TypingGameColor.py
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1542, in __call__
    return self.func(*args)
  File "D:/pythonaldecoa/TypingGameColor.py", line 17, in startGame
    if timeLeft == 30:
NameError: global name 'timeLeft' is not defined

After seeing the program with indentation, things are more clear: 'timeleft' and 'score' are NOT global, they are local to the function 'Game()'. To use them in the nested functions nextColor() and countdown() requires declaration as nonlocal, not global.

1 Answers1

2

You didn't make your question very clear, but I it appears that you are using the wrong keyword. Yes, those variables are nonlocal, but you used the global keyword to define them, instead use the nonlocal keyword, python litterally doesn't see those variables in global scope, so using global is useless. nonlocal rules documented here

For example, change this:

def Game():
    ...
    score ...
    timeleft ...
    ...
    def nextColor():
        global score
        global timeLeft

        if timeLeft > 0:
            e.focus_set()
            if e.get().lower() == colors[1].lower():
                score += 1

to this:

def Game():
    ...
    score ...
    timeleft ...
    ...
    def nextColor():
        nonlocal score
        nonlocal timeLeft

        if timeLeft > 0:
            e.focus_set()
            if e.get().lower() == colors[1].lower():
                score += 1

This solution doesn't work in 2.7. You shouldn't use 2.7 if you don't have to, but if this is for an assignment or for a legacy codebase, then you can get around the restrictions of 2.7 via the solution discussed here:

def outer():
    d = {'y' : 0}
    def inner():
        d['y'] += 1
        return d['y']
    return inner

f = outer()
print(f(), f(), f()) #prints 1 2 3

This works because you can read nonlocal variables, but you can't change them, so you need some sort of mutable container, hence the dictionary.

In your situation, this might look like this:

def Game():
    ...
    game_stats['score'] ...
    game_stats['timeLeft'] ...
    ...
    def nextColor():

        if game_stats['timeLeft'] > 0:
            e.focus_set()
            if e.get().lower() == colors[1].lower():
                game_stats['score'] += 1
Community
  • 1
  • 1
Krupip
  • 4,404
  • 2
  • 32
  • 54
  • I agree that nonlocal is a good solution, but only if OP is using 3.X, as it doesn't exist in 2.7. Unfortunately, since OP's call stack contains "C:\Python27", I'm guessing he can't use 3.X-only features. – Kevin May 01 '17 at 13:45
  • @Kevin There is no 2.7 tag... – Krupip May 01 '17 at 14:00
  • Yeah, but from the "can't use nonlocal" in the question title, I could only come up with two interpretations: he can't use it because he's using 2.7, or he can't use it because his instructor forbade him to use it for this exercise. In either case, we may as well look for solutions that don't use nonlocal. – Kevin May 01 '17 at 14:10
  • @Kevin I interpreted it him understanding the concept of nonlocal, but thinking that global was the keyword you had to use for it. – Krupip May 01 '17 at 14:18
  • yeah i cant use nonlocal . so im finding a new solution for this. im still a newbie in python – Mimok Aldecoa May 01 '17 at 14:19
  • @Kevin is there anyway that i can make this work without using nonlocal. or should i just use 3.x and how should i upgrade from 2.7 to 3.x im using jetbeans pycharm btw – Mimok Aldecoa May 01 '17 at 14:25
  • 1
    @MimokAldecoa look at my answer it explains how to do that, it includes both solutions, but you shouldn't use 2.7 regardless if you don't need to. – Krupip May 01 '17 at 14:26