TaraF13
TaraF13

Reputation: 13

Unable to break a python while loop inside a function

This program is a snakes and ladders program for my GCSE computer science (don't worry, this is just practice), and I'm having trouble breaking a while loop with a function that exists inside the loop. Here's the code:

win = False

while win == False:
    print("Player 1 goes first.")

    def dice():
        roll = random.randint(1,6)
        return roll

    roll = dice()
    print("They roll a...",roll)
    player1+=roll

    def check():
        if player1 in ladders or player2 in ladders:
            print("A ladder has moved the player to a new position.")
        elif player1 in snakes or player2 in snakes:
            print("A snake has moved the player to a new position.")
        elif player1 >= 36:
            print("Congratulations. Player 1 has won the game.")
            win = True
        elif player2 >= 36:
            print("Congratulations. Player 2 has won the game.")
            win = True

    check()

    print("Player 1 is on square",player1)

It's obviously not finished yet, and that's not all the code. After that bit, it does the same but with player2. There's a tuple above it that the check function checks to see if the player landed on a snake or a ladder, but I haven't added the code which actually moves the player up/down the ladder/snake.

The error is that the while loop is an infinite loop.

I've tried changing the whole win = False or True thing to just while True and then using break where I say win = True, but then it returns an error of 'break outside loop' even though the break is obviously inside the loop. I wonder if it's because I need to return something from the function, but I'm not quite sure how to do that. Simply putting 'return win' below both win = True doesn't change anything, and the while loop still continues indefinitely.

I've looked here and here for answers but neither worked for me; I think my situation is slightly different.

Upvotes: 1

Views: 2886

Answers (2)

Mentos
Mentos

Reputation: 170

It happened because when you are assign variable in function it used local variable. So, for a fast fix you can add global win in check function:

def check():
    global win
    if player1 in ladders or player2 in ladders:
        print("A ladder has moved the player to a new position.")
    elif player1 in snakes or player2 in snakes:
        print("A snake has moved the player to a new position.")
    elif player1 >= 36:
        print("Congratulations. Player 1 has won the game.")
        win = True
    elif player2 >= 36:
        print("Congratulations. Player 2 has won the game.")
        win = True

You can read more about type of variables here - http://www.python-course.eu/python3_global_vs_local_variables.php

Also it's not a good idea to store function inside while because it will create function on each iteration which is not good. So better is define them outside of loop.

Upvotes: 1

Luke
Luke

Reputation: 774

Perhaps this is what you are looking for? Note how I took the functions out of the loop. Then I ditched using a boolean variable altogether, as there is cleaner ways around it. You can use while True and then simply break if a certain condition is met. If you want the loop go back to starting point when a certain condition is met, you can use continue.

def dice():
        return random.randint(1,6)


def check():
        if player1 in ladders or player2 in ladders:
            print("A ladder has moved the player to a new position.")
        elif player1 in snakes or player2 in snakes:
            print("A snake has moved the player to a new position.")
        elif player1 >= 36:
            print("Congratulations. Player 1 has won the game.")
            return True
        elif player2 >= 36:
            print("Congratulations. Player 2 has won the game.")
            return True

while True:
    print("Player 1 goes first.")

    roll = dice()
    print("They roll a...",roll)
    player1 += roll

    if check():
        break

    print("Player 1 is on square",player1)

I didn't really touch the logic but it would make sense to pass the player score into check.

Upvotes: 1

Related Questions