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.