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

Tobias Edwards
Tobias Edwards
14,458 Points

Improvements to my solution of the Python Basics challenge?

So I've recently got back into learning Python again and I thought I would try the challenge in Python Basics where I have to create a "Guess my number game".

My attempt was very different to Kenneth's solution. But, is there any improvements I could make? Whether it be unnecessary code or little changes to make things cleaner and clearer?

THE CHALLENGE: to create a guess a number game:

  • Picks a random number between 1 and 10 and asks the user to guess a number

  • If the guess is wrong, tell the user if the guess is too high or too low, and let the user guess again

  • If the user guesses the right number, congratulate the user

  • Limit the number of guesses

  • Tell the user how many guesses that the user has made

Thank you :)

import random

def main():
    lives_left = 4
    number = random.randint(1,10)
    while lives_left >= 1:
        print("Guesses raminging: {}\n".format(lives_left))
        guess = user_input(lives_left)
        print(guess_check(guess, number))
        lives_left -= 1
    print("You ran out of lives.")
    print("\nMy number was {}.".format(number))
    again()
    quit()


def instructions():
    print("""
HOW TO PLAY:
-\tI am thinking of a number.
-\tGuess a number from 1 to 10.
-\tI will tell you if your guess is higher or lower than my number.
-\tTry and find my number in under 5 moves and you win.
-\tGood luck!

Type 'HELP' at any point for instructions.
Type 'LIVES' to recap on how many lives you have left.
Type 'QUIT' to quit at any point during the game.\n""")


def user_input(lives):
    while True:
        print("Guess a number between 1 and 10.")
        guess = input("> ")
        if guess.upper() == "HELP":
            instructions()
            continue
        elif guess.upper() == "LIVES":
            print("Guesses remaining: {}".format(lives))
            continue
        elif guess.upper() == "QUIT":
            quit()
        else:
            try:
                guess = int(guess)
                if guess in range(1, 11):
                    return guess
            except ValueError:
                print("\nPlease enter numbers between 1 and 10.\n"
                      "Or type 'LIVES', 'HELP' or 'QUIT'.")
                continue


def guess_check(guess, answer):
    if guess == answer:
        print("\nYour guess was CORRECT.")
        again()
    elif guess < answer:
        return "\nYour guess was too LOW."
    elif guess > answer:
        return "\nYour guess was too HIGH."
    else:
        user_input()


def again():
    playing_again = input("\nDid you want to play again?\n> ").lower()
    user_yes = ["yes", "y", "ya", "ye", "yeah"]
    user_no = ["no", "n", "na", "nope", "nah"]
    if any(response in playing_again for response in user_yes):
        main()
    elif any(response in playing_again for response in user_no):
        quit()
    else:
        print("I do not understand '{}'. Please respond 'YES' or 'NO'.".format(playing_again))
        again()


print("Welcome to GUESS MY NUMBER!")
instructions()
main()

Hey Tobias,

This looks good!

The only things that jump out at me right away are that print("Guesses raminging: {}\n".format(lives_left)) means to say "Guesses remaining", I assume, and that it would be easier and more Pythonic to check if playing_again were any word that started with either an 'n' or a 'y', rather than having that limited, but still somewhat lengthy, hardcoded list.

I hope this helps!

Be Well, Graham

1 Answer

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,426 Points

Nice work Tobias! I have two feedback points:

quit() shouldn't be used in production code

As mentioned in this stackoverflow response, use sys.exit() or os._exit() instead.

Using quit() will also kick you out of an interactive python session which might not be what you want. If I were to import this code into an ipython session, the quit() commands would exit the session. The code can usually by restructured to remove quit() either by making it an implied last option or simply using a return statement.

In the again() function, you could negate the second if condition, then allow the function to "fall through" if a negative response:

    if any(response in playing_again for response in user_yes):
        main()
    elif not any(response in playing_again for response in user_no):
        print("I do not understand '{}'. Please respond 'YES' or 'NO'.".format(playing_again))
        again()

In user_input(), you could use a simple return in place of quit():

        elif guess.upper() == "QUIT":
            return  #<-- returns 'None'

This would return a None to main(), so the guess line would need to be replaced with code similar to:

    guess = user_input(lives_left)
    if not guess:
        continue

The last quit() in main() is unnecessary as the script would fall through to end.

Add code for interactive use

To make your code reusable, you can add a wrapper around the instructions and main that only executes if run interactively:

if __name_ == '__main__':
    print("Welcome to GUESS MY NUMBER!")
    instructions()
    main()

With this, you can run it from the command line with python guess.py, and reuse the code in an interactive session such as: import guess:

In [1]: import guess

In [2]: guess.main()
Guesses raminging: 4

...