2
\$\begingroup\$

First time writing a "game" in a sense. Used a functions approach, it's simple, looking for a review of the way it's written and of course looking for how should it be written. Also using random for first time (I know I'm a nube).

#Number Guess Game

import random

def gameNumber():
     while True:
        difficulty = input("Type: E, M, H for easy, medium, or hard number range:\n").lower()    

        if difficulty == 'e':
            return random.randint(0,20)

        elif difficulty == 'm':
            return random.randint(0,50)

        elif difficulty == 'h':
            return random.randint(0,100)

        else:
            print("Incorrect input")


def numberGuessGame():
    number = gameNumber()
    while True:        
        try:  
           guess = int(input("Your guess: "))
           if number == guess:
               print("Correct guess!\n")
               return numberGuessGame() if input("play again?(y/any key to exit) ").lower() == 'y' else 0
           print("Too High" if number < guess else "Too Low")            
        except ValueError:
            print("must be an integer value\n")


def main():
    numberGuessGame()

if __name__ == '__main__':
    main()
\$\endgroup\$
3
\$\begingroup\$

What you have is very good and it certainly functions as expected. I have just a few ideas to consider implementing (more in relation to the game than the code):

  • Print the number ranges for each difficulty at the start, so that the user knows what range to guess in.
  • Check if the guess is outside the range.
  • Count the number of guesses and report back to the user at the end.
  • Edit the prompts slightly so user knows when input is expected.

I have shown my code below, implementing these features. I reduced it to a single function (to avoid having to use global variables). I have used a dictionary to store the top end of the range of each difficulty (difficulty_ranges) so this can be checked easily later, using fewer if else checks.

I also corrected a few PEP8 style warnings (spacing, use snake case instead of camel case for function name etc).

import random


def number_guess_game():
    # Set up main variables
    guesses = 0
    difficulty_ranges = {'e': 20, 'm': 50, 'h': 100}

    while True:
        difficulty = input(
            "Type E, M or H for easy (0-20), medium (0-50), or hard (0-100) number range:\n").lower()
        try:
            number = random.randint(0, difficulty_ranges[difficulty])
            break  # Need to break the while loop here
        except KeyError:
            print("Incorrect input! Choose again...")  # Encourage user input

    while True:
        try:
            guess = int(input("Your guess: "))
            guesses += 1
            if number == guess:
                print("Correct guess! You used {} guesses.".format(guesses))
                return number_guess_game() if input(
                    "Play again? Press Y to play again or any key to exit.").lower() == 'y' else 0
            elif guess < 0 or guess > difficulty_ranges[difficulty]:
                print("Your guess was out of range!")
            else:
                print("Too High. Guess again..." if number < guess else "Too Low. Guess again...")
        except ValueError:
            print("Must be an integer value.\n")


def main():
    number_guess_game()


if __name__ == '__main__':
    main()

I should add that I am not a Python expert, so other users will likely provide more useful information on the code. I think your layout is good and the logic is easy to follow. I wanted to suggest a few of these extra features as it is a game and these may improve the experience.

\$\endgroup\$
2
\$\begingroup\$

Chris has made some good UX improvements, and mentioned some nice code review points. I won’t duplicate those.

He also fell into the same trap: recursion is not meant as a looping substitute!

def numberGuessGame():
    ...
               return numberGuessGame() if input("play again?(y/any key to exit) ").lower() == 'y' else 0
    ...

If Python had tail-recursion-optimization, you could almost argue this as valid, reasonable code. But it doesn’t, so you can’t.

Consider: to test your code, I might write a program which runs your program, and plays for say 1,000,000 games. Perhaps it is some kind of neural network and it is learning how to best play; maybe 1,000,000 games is a reasonable training set. But your program will quickly crash with a stack-overflow, because each game doesn’t return until the last game has been played.

Instead of using recursion, how about using a loop?

def numberGuessGame():
    play_again = 'y'            # play the first time
    while play_again == 'y':

        ...
        while True:
            ...
                if number == guess:
                    print("Correct guess\n")
                    break
            ...

        play_again = input("play again?(y/any key to exit) ").lower()
\$\endgroup\$
  • 1
    \$\begingroup\$ I agree my answer is largely UX considerations. Changing recursion to a loop is a great improvement that I have learned from as well. I hadn’t considered the effect of an ever-increasing call stack! Thanks :) \$\endgroup\$ – Chris Oct 13 '18 at 12:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.