# number-guessing game - 1 through 30

I created this python number-guessing game and I have two concerns with it. The code works as intended with no flaws; however, I'm not too fond of the way I wrote it. It is messy, unorganized, and all over the place. There is repeated code such as the while loop that checks for a negative number or a number greater than 30, and the repeating "if number == n".

I wrote it like that because the program would bug if I did not repeat those expressions.

I also want to make it ask the user if they would like to play again; I do not know how.

import random
n = random.randint(1, 31)

choice = input("\nDo you want to play a game? (y/n): ")
if (choice == "y") or (choice == "Y") or (choice == "Yes") or (choice == "yes"):

counter = 0
number = int(input("\nGuess a number between 1 and 30: "))
if (number == n):
print("\nYou guessed correctly!!! Go you!")
counter += 1

while (number < 1) or (number > 30):
number = int(
input("\nThat is an invalid number. Please re-enter a number between 1 and 30: "))
if (number == n):
print("\nYou guessed correctly!!! Go you!")

while number != n:
if (number <= 5) and (n > 5):
number = int(input("\nToo low! Try again: "))
counter += 1
elif (number >= 25) and (n < 25):
number = int(input("\nWay too high! Try again: "))
counter += 1
elif ((n + 5 >= number) and (n - 5 <= number)):
number = int(input("\nYou are so close! Try again: "))
counter += 1
else:
number = int(input("\nWrong! Try again: "))
counter += 1
if (number == n):
print("\nYou guessed correctly!!! Go you!")
while (number < 1) or (number > 30):
number = int(
input("\nThat is an invalid number. Please re-enter a number between 1 and 30: "))

print(f"You took {counter} attempts to guess the number!")

else:

• Do you know about functions? Have you tried using one to solve the duplication? Feb 28 at 22:46

## Bug

First off there's a minor bug in your code in that random.randint(1, 31) can be 31, which you are not allowed to enter in your game. You probably want random.randint(1, 30)

## Naming

Your names are a little unhelpful. n should probably be something like target, counter num_guesses or similar. This makes it easier for someone coming along to easily identify what the variables actually mean.

## Structure

You take an initial guess, then have a second guess if the number is outside [1,30], then you have 2 whiles one for the initial guess and one for subsequent ones. This is probably a little unnecessary.

For checking numbers we probably only need 2 loops. One to check while it's not the correct number, and another to get a valid input from the user.

We could just get the guess as a function!

def get_guess():
""" Get valid input from player """
while True:
inp = input("Guess a number between 1 and 30: ")
try:
inp = int(inp)
except ValueError:
print(f"Invalid value input {inp}, must be an integer between 1 and 30")
continue
if inp in range(1, 31):
return inp

print(f"Invalid value input {inp}, must be an integer between 1 and 30")

guesses = 0
while guesses < MAX_GUESSES:
number = get_guess()
if number <= 5 and n > 5:
...


## Use of ifs

Comparisons in Python can be chained to clean up a lot of checks.

if 0 < i < 31:


checks whether i is in the range [1, 30], you can also do i in range(1,31) which also makes your intent obvious.

In order to check how far you are from the correct answer, rather than checking the value of n and number separately, why not check if number is far from n by calculating the difference?

if abs(number - target) <= 5:  # Could just precompute the difference and compare it against each
print("You're so close try again!")
elif number - target > 10:
print("Way too high!")
elif number - target > 5:
print("Too high!")
elif target - number > 10: # N.B. these are target - number i.e. number - target < -10
print("Way too low!")
elif target - number > 5:
print("Too low!")


In order to check whether choice is y,Y,yes or Yes, we could do:

if choice.lower() in ('y', 'yes'):


which will case insensitively check.

## Replay

To answer your question on replaying the game, we need to wrap the whole thing in a while loop checking each time whether the player wants to play again, and generating a new number.

## Putting it all together

Putting it all together with main guards and functions we might end up with something like:

"""
Number guessing game
"""

import random

def get_guess():
""" Get valid input from player """
while True:
inp = input("Guess a number between 1 and 30: ")
try:
inp = int(inp)
except ValueError:
print(f"Invalid value input {inp}, must be an integer between 1 and 30")
continue
if inp in range(1, 31):
return inp

print(f"Invalid value input {inp}, must be an integer between 1 and 30")

def play_guess_game():
""" Play a round of the guessing game """
target = random.randint(1, 30)

number = -1
guesses = 0
while number != target:
guesses += 1
number = get_guess()

diff = number - target

if diff == 0:
print("You guessed correctly!!! Go you!")
elif abs(diff) <= 5:
print("You're so close try again!")
elif diff > 10:
print("Way too high!")
elif diff > 5:
print("Too high!")
elif diff < -10:
print("Way too low!")
elif diff < -5:
print("Too low!")

print(f"You took {guesses} attempts to guess the number!")

if __name__ == "__main__":
while input("Do you want to play a game? (y/[n]): ").lower() in ('y', 'yes'):
play_guess_game()