# Python guessing game

I'd like some feedback.

from random import randint

turns = 1
computer_guess = randint(1, 10)
while True:
user_guess = raw_input("Guess Number: ")
print 4-turns, "Turns left"
if turns == 4:
print "You lost!, LOOSER!"
exit()
else:
if int(user_guess) == int(computer_guess):
print "Congratulations, You won!\n"
play_again = raw_input("Do You Want To Play Again? (Y / N): ")
if play_again.upper() == 'Y':
continue
else:
exit()
else:
turns += 1
print "Try again - N was ", computer_guess


## 2 Answers

I’ll build on @zondo advices which are missing an important point:

# Use functions

Not only they allow you to give a meaningfull name to a logical section, they also improve overall readability and let you test individual behavior easily.

Out of your main loop, you can easily extract two functions: one that prompt the user for a (valid) number, and one that as the user if he wants to play again.

This lets write the main loop more easily:

from random import randint

TOTAL_TURNS = 4

turns = 1
computer_guess = randint(1, 10)
while True:
user_guess = prompt_for_number()
if user_guess == computer_guess:
print "Congratulations, You won!\n"
if prompt_for_play_again():
turns = 1
computer_guess = randint(1, 10)
continue
else:
break
else:
turns += 1
print "Try again"
print TOTAL_TURNS - turns + 1, "Turns left"


I will get to the definition of prompt_for_number and prompt_for_play_again later but for now, it's a little bit easier to read and understand.

But we can still make use of function to improve that code and remove redundant parts (for instance turns = 1 or computer_guess = randint(1, 10)). We can also make use of parameters to make the program more generic (why limit to numbers between 1 and 10, after all).

from random import randint

def guess_game(turns=3, lower_bound=1, upper_bound=10):
computer_value = randint(lower_bound, upper_bound)
for remaining_turns in range(turns, 0, -1):
print remaining_turns, "turns left"
guess = prompt_for_number(lower_bound, upper_bound)
if guess == computer_value:
print "Congratulations, You won!\n"
return
print "Try again!"
print "You lost!"

while True:
guess_game()
if not prompt_for_play_again():
break


The main change here being the use of for remaining_turns in range(turns, 0, -1) instead of hardcoding a value for the maximum number of turns + 1 (which will most likely be misnamed, then) and managing the amount of turns ourselves.

This solution will also print 'Try again!' right before 'You lost!' in case the player can't find the number after the given amount of tries. You can put an if remaining_turns > 1: before print "Try again!" if you want to get rid of it.

Now that we have an efficient and readable main loop, we can focus on implementing the two missing functions.

# Proposed improvements

Reusing most of @zondo constructs:

from random import randint

def prompt_for_number(min_value, max_value):
prompt = "Guess number between {} and {}: ".format(min_value, max_value)
while True:
try:
value = int(raw_input(prompt))
except ValueError:
print "Please type an integer"
continue
if min_value <= value <= max_value:
return value
print "Your number is not in the acceptable range"

def prompt_for_play_again():
while True:
play_again = raw_input("Do you want to play again? (Y/N): ").upper()
if play_again == 'Y':
return True
if play_again == 'N':
return False
print "Please type Y or N"

def guess_game(turns=3, lower_bound=1, upper_bound=10):
computer_value = randint(lower_bound, upper_bound)
for remaining_turns in range(turns, 0, -1):
print remaining_turns, "turns left"
guess = prompt_for_number(lower_bound, upper_bound)
if guess == computer_value:
print "Congratulations, You won!\n"
return
print "Try again!"
print "You lost!"

if __name__ == '__main__':
while True:
guess_game()
if not prompt_for_play_again():
break


I just added if __name__ == '__main__': to wrap the top-level code. And used format to account for varying bounds.

• Why did you not use type() to check if inpur is INT or not Apr 11 '16 at 14:23
• dont you think that 1.1m.yt/KQxn6MB.png is better than 1.1m.yt/CIhNStN.png Apr 11 '16 at 14:41
• @IdontReallywolf How would you want to use type? Something like v = raw_input(…); if type(v) == int: …? Then it will always fail since raw_input always return str. And for the input validation, I would have written if play_again in ('Y', 'YES'): … and if play_again in ('N', 'NO'): …; but you need to slightly change the messages to let the user know he can also input 'yes' or 'no'. Apr 11 '16 at 15:06
• :D I understand now why type didnt work for me the first time i used it & This works better 1.1m.yt/odL7EWT.png Apr 11 '16 at 15:30

With some short code like that, I decided I'd run it to get a better feel for the program. Here's my first session:

Guess Number: 45
3 Turns left
Try again - N was  9
Guess Number: 9
2 Turns left
Congratulations, You won!

Do You Want To Play Again? (Y / N): yes


(end)

You didn't give any rules at the beginning of the file, so how was I to know the number had to be between one and ten? I know only because I looked at your code. I typed 45 and there was no indication that it was invalid. It told me it wasn't the right answer and said I had three turns left, but it also told me what the right answer was. That made my second guess easy. I was right, but it still printed 2 Turns left. I said yes when it asked if I wanted to play again, but it exited the program anyway. Another minor thing: you want to look professional and that includes more than just how the program works. It includes how your text is formatted. Your caPitaliZatioN maKes a diFfErence iN How yOur ProGram LooKs. You have a lot of unnecessarily capitalized letters. I would recommend looking up a good style guide on capitalization.

print 4-turns, ...


Why 4? Well, of course, it's because that's how many turns there are. It's an arbitrary number (called a magic number) that should instead be defined as a constant at the beginning of the file to be used in all cases instead of typing in magic numbers. You also shouldn't be printing how many turns are left unless the user did not win or lose. That means that it should come after the if and else blocks.

exit()


It is unnecessary to exit; you can just use break.

if int(user_guess) == int(computer_guess):


What if the user typed wheeeee!? It's a common thing to say, right? Well, anyway, the user might type something invalid and you wouldn't want to have an error if he did. You'd have a disgruntled user on your hands. You also don't need to convert computer_guess. It's already an integer.

if play_again.upper() == 'Y':
continue
else:
exit()


You shouldn't just continue. You also need to reset turns.

You shouldn't use a bare else. What if the user typed yes as I did? It still exits. You should use a loop there that validates the user's input. If you want to be really fancy, define a function that excepts a bunch of different inputs as positive and a bunch as negative. I once wrote a function that even counted uh huh as a valid way of saying yes.

print "Try again - N was ", computer_guess


You shouldn't tell the user what the answer is until the game is over.

The new code:

from random import randint

TOTAL_TURNS = 4

turns = 1
computer_guess = randint(1, 10)
while True:
try:
user_guess = int(raw_input("Guess number between 1 and 10: "))
except ValueError:
print "Please type an integer."
continue
if not 1 <= user_guess <= 10:
print "Please type a number between 1 and 10."
continue
if turns == TOTAL_TURNS:
print "You lost! Loser!"
break
else:
if user_guess == computer_guess:
print "Congratulations, You won!\n"
while True:
play_again = raw_input("Do you Want To Play Again? (Y / N): ").upper()
if play_again in "YN": break
print "Please type Y / N"
if play_again == 'Y':
turns = 1
computer_guess = randint(1, 10)
continue
else:
break
else:
turns += 1
print "Try again"
print TOTAL_TURNS - turns + 1, "Turns left"

• what is this line gonna do? if play_again in "YN": break Apr 11 '16 at 6:17
• @IdontReallywolf: If play_again is either Y or N, then it is a substring of YN. The if statement sees if it is a substring and if it is, breaks out of the loop. That way, if it isn't either one of them, it will ask again, but if it is one of them, it will leave the loop and continue with the game or exit depending on which letter the user typed. Apr 11 '16 at 10:37
• @mathias-ettinger Do you have a facebook account? :P I've made another game, 'Dice'. I got some problems in the code. plx help Apr 11 '16 at 20:06
• @IdontReallywolf: You posted your comment on the wrong post. If you have problems, ask them on stackoverflow.com. I wouldn't try to limit my help to one person, if I were you. Apr 11 '16 at 22:20
• People on stackoverflow seems to be rude. instead of helping they are trolling me :P lawl Apr 12 '16 at 16:42