Waldxn
Waldxn

Reputation: 91

Program not exiting after multiple games?

from random import random


# This function handles the number guessing and number formatting
def run_game():

    # rand is declared by grabbing a number between 0 and 1, multiplying it by 100, and rounds to nearest integer
    rand = round(random() * 100, 0)
    print("Guess the number [0 - 100]")
    guesses = 0

    while True:

        # Assigns the 'answer' variable by grabbing user input from console
        answer = input()

        # Checks if the input from the console is a number, and if not, asks the user to enter a valid number
        if answer.isdigit():
            n = int(answer)
            if n > int(rand):
                print("Number is less than " + str(n))
                guesses = guesses + 1
            elif n < int(rand):
                print("Number is greater than " + str(n))
                guesses = guesses + 1
            else:
                guesses = guesses + 1
                print("It took you " + str(guesses) + " guesses to guess the right number!")
                reply = play_again()
                if reply is False:
                    break
                else:
                    run_game()
        else:
            print("Please enter a number")


def play_again():
    while True:
        reply = input("Play again? (y/n)\n")
        if reply.lower() == "y":
            return True
        elif reply.lower() == "n":
            return False
        else:
            print("Enter 'y' or 'n'")


if __name__ == "__main__":
    run_game()

So when I run this program, it runs fine. Once guessing the number, I can type y or n to play again. If I have only played once, it works fine. But if I select y, and play again, entering n after playing the second game does nothing

Upvotes: 2

Views: 51

Answers (4)

jmgd
jmgd

Reputation: 25

There's no point in returning True or False according to the user input, you can work from there directly.

import sys
from random import random


# This function handles the number guessing and number formatting
def run_game():

    # rand is declared by grabbing a number between 0 and 1, multiplying it by 100, and rounds to nearest integer
    rand = round(random() * 100, 0)
    print("Guess the number [0 - 100]")
    guesses = 0

    while True:

        # Assigns the 'answer' variable by grabbing user input from console
        answer = input()

        # Checks if the input from the console is a number, and if not, asks the user to enter a valid number
        if answer.isdigit():
            n = int(answer)
            if n > int(rand):
                print("Number is less than " + str(n))
                guesses = guesses + 1
            elif n < int(rand):
                print("Number is greater than " + str(n))
                guesses = guesses + 1
            else:
                guesses = guesses + 1
                print("It took you " + str(guesses) + " guesses to guess the right number!")
                play_again()
        else:
            print("Please enter a number")


def play_again():
    while True:
        reply = input("Play again? (y/n)\n")
        if reply.lower() == "y":
            run_game()
        elif reply.lower() == "n":
            sys.exit(0)
        else:
            print("Enter 'y' or 'n'")


if __name__ == "__main__":
    run_game()

This way the code is somewhat cleaner and fixes your problem. There's no point in passing "flags" around when you can do things directly. Since your game is from 0 to 100 you should also verify if the user doesn't put a number that's bigger than 100, since lower than 0 doesn't pass the isdigit check.

Upvotes: 0

Blckknght
Blckknght

Reputation: 104702

Your main issue is that you're using recursion to start a new game, but after the recursive call returns (assuming it does), you just keep on going in the original game.

There are a few ways you could fix that. The simplest would be to change the code that handles checking the user's choice to play again so that it always breaks:

if reply:
    run_game()
break

A better approach would be to get rid of the recursion. There are a few ways you could do that. One simple idea is to simply reset the appropriate variables and keep right on going with your game loop when the user wants to play again:

reply = play_again()
if reply:
    rand = round(random() * 100, 0)
    print("Guess the number [0 - 100]")
    guesses = 0
else:
    break

Another way to avoid recursion would be to add another loop. Here's one way you could do it with a separate function:

def run_game():
    rand = round(random() * 100, 0)
    print("Guess the number [0 - 100]")
    guesses = 0

    while True:
        answer = input()
        if answer.isdigit():
            n = int(answer)
            if n > int(rand):
                print("Number is less than " + str(n))
                guesses = guesses + 1
            elif n < int(rand):
                print("Number is greater than " + str(n))
                guesses = guesses + 1
            else:
                guesses = guesses + 1
                print("It took you " + str(guesses) + " guesses to guess the right number!")
                break # unconditionally break here!

def run_many_games():
    again = True
    while again:
        run_game()
        again = play_again()

One thing you may note that I've changed in all of the code above is how I test if the return value from play_again is True or False. There's no need for an extra comparison step when you have a bool value already. Just do if reply (or if not reply if you're testing for False). You can also do this in a while loop condition, as I do with again in my last code block.

Upvotes: 2

Arkia
Arkia

Reputation: 126

The reason this is happening is because run_game ends up calling itself recursively. Instead of restarting the game when the user chooses to play again it effectively creates a new instance of the game. Then when the user chooses to stop playing it returns back to the old session instead of exiting the program.

You can even prove this to yourself by remembering the solution before choosing to play again, and then choosing not to play again after the second session. You'll then be playing the previous session again and entering the solution you remembered or wrote down.

Now you can solve this problem by using sys.exit() instead of break to force the program to close, but that doesn't seem like good practice. If somebody chooses to play again too many times they can cause the program to run out of stack space and crash. Instead it's probably better to move that check out of run_game like this

if __name__ == "__main__":
  while True:
  run_game()
  if not play_again():
    break

And modify the else block in run_game to this

else:
  guesses = guesses + 1
  print("It took you " + str(guesses) + " guesses to guess the right number!")
  break

Upvotes: 0

Ryan JB
Ryan JB

Reputation: 1

Heres a good way to solve this problem. In your code you never actually exit the while loop because run game never exits, and there is no system variable returned to break it. Using sys.exit(0) also works, but its a bad habit to get into for these kinds of programs.

from random import random


# This function handles the number guessing and number formatting
def run_game():

    # rand is declared by grabbing a number between 0 and 1, multiplying it by 100, and rounds to nearest integer
    rand = round(random() * 100, 0)
    print("Guess the number [0 - 100]")
    guesses = 0

    while True:
        answer = input()
        if type(answer) == int:
            n = int(answer)
            if n > int(rand):
                print("Number is less than " + str(n))
                guesses = guesses + 1
            elif n < int(rand):
                print("Number is greater than " + str(n))
                guesses = guesses + 1
            else:
                guesses = guesses + 1
                print("It took you " + str(guesses) + " guesses to guess the right number!")
                break
    reply = play_again()
    if reply:
        run_game()
    else:
        print 'Thank you for playing'

def play_again():
    while True:
        reply = raw_input("Play again? (y/n)\n")
        if reply.lower() == "y":
            return True
        elif reply.lower() == "n":
            return False
        else:
            print("Enter 'y' or 'n'")

if __name__ == "__main__":
    run_game()

Upvotes: 0

Related Questions