Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

Thomas Rose
seal-mask
.a{fill-rule:evenodd;}techdegree
Thomas Rose
Python Web Development Techdegree Student 393 Points

High score programming in python across programs: why do one of these work but the other doesn't?

I'm making a high score feature for the dungeon game in unit two of the python techdegree, and I'm not quite sure what is going wrong. Here's my code for it:

import random
import os


CELLS = [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0),
         (0, 1), (1, 1), (2, 1), (3, 1), (4, 1),
         (0, 2), (1, 2), (2, 2), (3, 2), (4, 2),
         (0, 3), (1, 3), (2, 3), (3, 3), (4, 3),
         (0, 4), (1, 4), (2, 4), (3, 4), (4, 4),]

def clear_screen():
    os.system("cls" if os.name == "nt" else "clear")

def get_locations():
    return random.sample(CELLS, 3)


def move_player(player, move):
    x, y = player
    if move == "LEFT":
        x -= 1
    if move == "RIGHT":
        x += 1
    if move == "UP":
        y -= 1
    if move == "DOWN":
        y += 1
    return x, y

def get_moves(player):
    moves = ["LEFT", "RIGHT", "UP", "DOWN"]
    x, y = player
    if y == 0:
        moves.remove("UP")
    if y == 4:
        moves.remove("DOWN")
    if x == 0:
        moves.remove("LEFT")
    if x == 4:
        moves.remove("RIGHT")
    return moves

def draw_map(player, door, monster):
    print(" _" * 5)
    tile = "|{}"

    for cell in CELLS:
        x, y = cell
        if x < 4:
            line_end = ""
            if cell == player:
                output = tile.format("X")
            elif cell == door:
                output = tile.format("O")
            elif cell == monster:
                output = tile.format("M")
            else:
                output = tile.format("_")
        else:
            line_end = "\n"
            if cell == player:
                output = tile.format("X|")
            elif cell == door:
                output = tile.format("O|")
            elif cell == monster:
                output = tile.format("M|")
            else:
                output = tile.format("_|")
        print(output, end = line_end)

def game_loop():
    player, door, monster = get_locations()
    playing = True
    move_count = 0
    print("The high score is currently held by {} with a score of {}!".format(first_place[0], high_score[0]))

    clear_screen()
    while playing:
        clear_screen()
        high_score.sort()

        draw_map(player, door, monster)
        valid_moves = get_moves(player)

        print("You're currently in room {}".format(player))
        print("You can move {}".format(", ".join(valid_moves)))
        print("Enter 'QUIT' to quit")

        move = input("> ")
        move = move.upper()
        clear_screen()

        if move == 'QUIT':
            print("\n** See you next time! **\n")
            break
        if move in valid_moves:
            move_count += 1
            player = move_player(player, move)
            clear_screen()
            draw_map(player, door, monster)


            if player == monster:
                print("\n ** Oh no! The monster fot you! Better luck next time **\n")
                playing = False
            if player == door:
                new_high = move_count
                high_score.sort()
                print("\n** You escaped in {} moves! Congratulations! **\n".format(new_high))
                if new_high < high_score[0]:
                    high_score.insert(0, new_high)
                    print("\n** You have the new high score!!! **\n")
                    first_place = input("What is your name? \n > ")
                else:
                    print("The high score is still held by {} with a score of {}!".format(first_place[0], high_score[0]))
                playing = False
        else:
            input("\n ** Walls are hard! Don't run into them! **\n")
    else:
        if input("Play again? [Y/n]").lower != "n":
            game_loop()

if __name__ == '__main__':
    clear_screen()
    print("Welcome to the dungeon!")
    input("Press return to start!")
    clear_screen
    high_score = [15]
    first_place = ["Niel Armstrong"]
    game_loop()

I am getting an error for not having the first_place variable assigned before it's being read, but I used, as far as I can tell, this exact method to finally get the number guessing game highscore to work, code below:

import random

import os

def clear_screen():
    os.system("cls" if os.name == "nt" else "clear")

def start_game():
    low = 1
    high = 10
    secret_number = random.randint(low, high)

    #This is a Test Line 
    #print("The number is {}".format(secret_number))

    print("""
    ================================================
    Welcome to the Number Guessing Extravaganza!!!!
    ================================================
    """)

    print("""
    The rules are simple; choose a number between 1 
    and 10, and we will tell you if the secret 
    number is higher or lower than that. Try and 
    guess the secret number in as few guesses as
    possible!
    """)
    print("The current high score is {}, held by {}. Try and beat it!".format(high_score[0], first_place[0])) 

    attempts = 0
    while True:
        try:
            guess = int(input("What is your guess?  "))
        except ValueError:
            print("Please enter a whole number!")
            continue
        if guess == secret_number:
            attempts += 1
            print("You got it!")
            print("You guessed the secret number in {} try(s)!".format(attempts))
            high_score.sort()
            if high_score[0] > attempts:
                first_place[0] = input("What is your name? ")
                high_score.insert(0, attempts)

                print("You have the new high score!")
            else:
                print("The high score is currently {}, held by {}".format(high_score[0], first_place[0]))

            print("Thanks for playing!")
            replay = input("""Would you like to play again? [y]es or [n]o? """)
            if replay == "n":
                print("Thanks for playing!")
                break
            if replay == "y":
                clear_screen()
                start_game()

        if 1 <= guess < secret_number:
            attempts += 1
            print("Too low!")
            continue
        if 11 >= guess > secret_number:
            attempts += 1
            print("Too high!")
            continue
        if guess > 10:
            print("The number must be between 1 and 10.")
            continue
        if guess < 1:
            print ("The number must be between 1 and 10.")
            continue

if __name__ == '__main__':
    high_score = [7]
    first_place = ["Jim-Bob"]    
    start_game()

I'm lost! Any help would be appreciated

Steven Parker
Steven Parker
231,275 Points

It looks like apostrophes (''') in the code instead of accents (```). And they have to be on lines by themselves, except the starting one can have the word "python" after it to give you syntax coloring.

4 Answers

Jeff Muday
MOD
Jeff Muday
Treehouse Moderator 28,722 Points

You can assign your globals "high_score" and "first_place" right after your import statements.

import random

import os

# declaring/assigning variables in the global scope.
high_score = [7]
first_place = ["Jim-Bob"] 

Then... in start_game() or any other function you choose can access these variables successfully as globals.

def start_game():
    # this will give access to the global variables
    global high_score
    global first_place

    low = 1
    high = 10
    secret_number = random.randint(low, high)

Here is some decent documentation on "global"

https://www.programiz.com/python-programming/global-keyword

Another cool trick from the magic of Treehouse is the workspace snapshot (that you can share). With the snapshot URL we can look at your code and supporting files rather than having to cut-and-paste it all in. The snapshot button is in the upper-right-hand corner of the workspace.

Later on, when you are doing some really complex stuff, you will have lots of files in a directory structure and you can share all these in the forum with a few clicks.

best, Jeff

The difference between the two is in the dungeon game you have this:

first_place = input("What is your name? \n > ")

whereas in the number guessing game you have:

first_place[0] = input("What is your name? ")

If you change the variable to first_place[0] in the dungeon game it also runs without the error and without declaring the variables as global in the function. My question for Jeff or Steven is why?

I have a snapshot with the above code

a.py = number guessing game

b.py = dungeon game (I added some code to delay the clear_screen around where the error occurs )

c.py = shorter code that demonstrates the same error and seems to contradict a and b

Jeff Muday
MOD
Jeff Muday
Treehouse Moderator 28,722 Points

Kris, your "c.py" is a great reductionist view of the issue!

The Python scoper does a "scope check" on any variable that is accessed or assigned within a new scope.

In f(), 'x' is accessed only... so Python looks into its parent's scope and finds 'x' (no errors)

In g(), 'x' is assigned, so it assumes it must be a LOCAL x, and doesn't find it. (throws an error) The telling thing here is that it won't even print(x) because the Python scoper already scanned ahead to find an assignment!

If you include the 'global x' command, it overrides the local scope and tells the Python scoper to use the 'x' in the parent scope.

x = 1
def f():
    print(x)
def g():
    print(x)
    x = 2
f() #prints 1
g() #throws an error