# Python - Random Number Guessing Game

I'm new to programming in general (Python is the first language I've tried learning) and I'm working my way through a collection of beginner's challenges. I'm having a little trouble wrapping my head around functions, positional arguments, and the way they interact with user input. I wrote this program to test my understanding. Is there any way it could be made more efficient?

This program does the following things:

• It generates a random 3 digit number.
• It tells the user how to play the game.
• It asks the user to guess the number.
• If the number is too low, it returns 'Higher' and if the number is too high it returns 'Lower'. Finally, if the user guesses the number correctly, it congratulates the user.
• Once the correct number has been guessed, it asks the user if he/she wants to play again.
• If the user says yes, the program generates a new random 3 digit number and the game starts again. If the user chooses no, it says goodbye and quits.

Here's the code:

import random

def instructions():
"""Tells user how to operate program."""
i = """
I have selected a random 3 digit number.  Your goal is to guess my
number in the smallest amount of of moves.  I will tell you if your
guess is too high or too low, but that's all the help you'll get
from me.
"""
print(i)

def guess():
g = int(input("Guess the number: "))
return g

def hint(x):
if x > ans:
print("Lower")
elif x < ans:
print("Higher")
else:
print(victory(x))

def victory(x):
if x == ans:
print("Congratulations!  You got it!")

instructions()

ans = random.randint(100,999)

while True:
x = guess()
if x != ans:
hint(x)
elif x == ans:
victory(x)
replay = input("Would you like to play again? y/n: ").strip().lower()
if replay == "y":
ans = random.randint(100,999)
continue
else:
print("Okay then.  Bye-bye.")
break


Again, just to clarify, I've tested the program and it does work, I'm just looking to see if there's a more efficient way of writing it which doesn't sacrifice any of its current functions. Thanks.

I'd say the code itself is not bad but there are a few things to keep in mind.

• i is a bad name for a string. Also, you don't need it in the instructions function, you can just print the string.

• The same goes for g. It's not a good name and you can return directly the input.

• guess is not a good name because the function is not guessing, it's getting the user input, so you could call it get_user_input. Also, since the number is between 100 and 999, you could add some checks that the user input is in that range, and you could use some constants to define the range.

• This works correctly on python 3, but on python 2 you would use raw_input instead of input. Just something to keep in mind.

• In the hint function you're printing the output of the victory function, which actually is returning nothing. That's why it works, but the proper way would be to either use the victory function only to return the winning message, or to use the victory function separately to check that the user has won. It looks like this is the main point you want to understand, so have a close look at that.

• victory is also not a really good name. If you want to check that the user has won, name it has_won, or maybe is_guess_correct.

• If the user enters something invalid (like a letter or an empty line) you're going to get an error. You should use exceptions there, but maybe this is a bit of an advanced topic for now?

• You don't need the continue in this case, because nothing is executed after that instruction.

Modified code:

import random

LOWER_LIMIT = 100
UPPER_LIMIT = 999

def instructions():
"""Tells user how to operate program."""
print("""
I have selected a random 3 digit number.  Your goal is to guess my
number in the smallest amount of of moves.  I will tell you if your
guess is too high or too low, but that's all the help you'll get
from me.
""")

def get_user_input():
current_guess = int(input("Guess the number: "))
while (current_guess < LOWER_LIMIT) or (current_guess > UPPER_LIMIT):
current_guess = int(input("Please enter a number between " + str(LOWER_LIMIT) + " and " + str(UPPER_LIMIT) + ": "))

return current_guess

def hint(x):
if x > ans:
print("Lower")
elif x < ans:
print("Higher")

def is_guess_correct(x):
if x == ans:
print("Congratulations!  You got it!")
return True
return False

instructions()

ans = random.randint(LOWER_LIMIT, UPPER_LIMIT)

while True:
x = get_user_input()
if is_guess_correct(x):
replay = input("Would you like to play again? y/n: ").strip().lower()
if replay == "y":
ans = random.randint(100,999)
else:
print("Okay then.  Bye-bye.")
break
else:
hint(x)


I think that inside your function hint(x) you should remove the following:

else:
print(victory(x))


It is pointless to have those lines, as your code will never reach them, because you are validating that your input is not the answer with these lines:

if x != ans:
hint(x)
elif x == ans:
victory(x)


For the purpose of using functions, I think that your program is enough efficient, however, for a regular Guess the Number game, I wouldn't use functions, but write the instructions directly in the loop.

• As far as I can tel print(victory(x)) will do the same as victory(x), right? – unicorn2 May 12 '17 at 7:29
• You are right, however, the victory(x) statement inside hint will never be reached. – JPYamamoto May 12 '17 at 11:13
• Also, you shouldn't write print(victory(x)), but only victory(x), because you are telling it to print something inside the function – JPYamamoto May 12 '17 at 11:13