# Number-guessing game using functions

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

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():
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()


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.

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()

• 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 :) – Chris Oct 13 '18 at 12:52