Guess the Number Game in Python: Code, Logic, and Variants
Build a number-guessing game in Python using random, input(), and while loops. Includes a basic version, a max-attempts variant, and higher-or-lower hint logic.
A number-guessing game is one of the shortest Python programs that still exercises loops, conditionals, random number generation, and user input in a single file.
How the Game Works
The game is a loop built on one comparison operator. The program knows the answer; the player doesn’t. Every iteration narrows the search space by half if the player follows the hints, which is why 5 attempts are enough to cover a 1-to-20 range (binary search reasoning: log2(20) rounds up to 5).
The logic is four steps:
- The program picks a random integer within a defined range (say 1 to 20).
- The player enters a guess via the terminal.
- The program compares the guess to the secret number and prints a hint: too high, too low, or correct.
- Steps 2 and 3 repeat until the player guesses correctly or runs out of attempts.
Two Python standard-library tools do the heavy lifting: random.randint() generates the secret number, and input() reads the player’s guess as a string (which you cast to int).
Basic Version: Loop Until Correct
This version has no attempt limit. The loop runs until the player hits the right number.
import random
secret = random.randint(1, 20)
print("Guess a number between 1 and 20.")
while True:
guess = int(input("Your guess: "))
if guess < secret:
print("Too low.")
elif guess > secret:
print("Too high.")
else:
print(f"Correct! The number was {secret}.")
break
Line-by-line breakdown:
random.randint(1, 20)returns an integer where both 1 and 20 are inclusive endpoints.while Truecreates an infinite loop; only abreakexits it.int(input(...))reads a string from stdin and converts it to an integer.- The if-elif-else chain compares
guessagainstsecret. Whenguess == secret, the else block fires andbreakends the loop.
A sample run:
- Input:
10— Output:Too high. - Input:
5— Output:Too low. - Input:
7— Output:Correct! The number was 7.
Adding a Max-Attempts Limit
Most placement-style variants cap the number of guesses. The version below allows 5 attempts.
import random
secret = random.randint(1, 20)
max_attempts = 5
print(f"Guess a number between 1 and 20. You have {max_attempts} attempts.")
for attempt in range(1, max_attempts + 1):
guess = int(input(f"Attempt {attempt}: "))
if guess < secret:
print("Too low.")
elif guess > secret:
print("Too high.")
else:
print(f"Correct! You got it in {attempt} attempt(s).")
break
else:
print(f"Out of attempts. The number was {secret}.")
Key differences from the basic version:
- A
forloop withrange(1, max_attempts + 1)controls iteration count. - The
elseclause on the for loop executes only when the loop finishes without hittingbreak. This is Python’s for-else pattern: the else block runs if the player never guessed correctly within the allowed attempts. - The
attemptvariable tracks which guess the player is on, useful for the success message.
Why for-else works here
Python’s for-else is unintuitive for many beginners. The rule: the else block runs when the loop terminates normally (exhausts the range), not when break fires. In a guessing game, “exhausts the range” means the player used all attempts without guessing correctly. That maps cleanly to the “you lose” message.
Placement interviewers at service companies sometimes ask candidates to explain for-else during Python walkthroughs. Knowing this pattern and being able to point at a working example saves time during live coding rounds.
Higher-or-Lower Hint Logic
Both versions above already print directional hints. The comparison logic is the same in each:
if guess < secret:
print("Too low.")
elif guess > secret:
print("Too high.")
When guess is less than secret, the hint says “Too low.” When guess is greater than secret, the hint says “Too high.” The else branch (not shown here) handles equality.
A more informative variant adds distance hints:
diff = abs(guess - secret)
if diff <= 2:
print("Very close!")
elif diff <= 5:
print("Close.")
else:
print("Far off.")
This gives the player a sense of proximity without revealing the exact number. You can combine directional and distance hints by printing both on the same turn. For example, print “Too low, but very close” when the guess is below the secret and within 2 of it.
Common Mistakes and Edge Cases
Beginners hit these bugs regularly:
- TypeError from input():
input()returns a string. Comparing a string to an integer with<or>raises a TypeError in Python 3. Always cast withint()before comparison. - Off-by-one in range:
random.randint(1, 20)includes both 1 and 20. If the player is told the range is 1 to 20, the secret number can be exactly 20. Printing “between 1 and 20” is correct here becauserandintis inclusive on both ends. - Forgetting to increment a counter: In the manual-counter version (using
whilewith a counter variable instead offor), forgettingattempts += 1creates an infinite loop. - Non-integer input crash: If the player types “abc”,
int("abc")raises a ValueError. A production version wraps the cast in try-except:
try:
guess = int(input("Your guess: "))
except ValueError:
print("Enter a valid integer.")
continue
The continue statement skips the rest of the loop body and re-prompts without counting that as an attempt.
- Guessing outside the range: If the player enters 25 when the range is 1 to 20, the game still works (the hint will say “Too high”), but you can add an explicit check:
if guess < 1 or guess > 20: print("Out of range."); continue. This saves the player a wasted attempt on an impossible number.
Where This Fits in Your Practice Sequence
This game covers four patterns that repeat across beginner Python problems: random number generation, type-casting input, conditional branching, and loop control. The same patterns appear in a basic calculator program (if-elif on user choice), in comparing two numbers (conditional logic), and across the full set of Python example programs for practice.
If looping through conditionals in a terminal feels comfortable, the next step is building something that responds to natural language instead of fixed menu options. The if guess < secret logic in this tutorial is the same branching pattern you use when routing LLM responses. TinkerLLM gives you a sandbox where that same Python connects to an actual AI model, so your conditional-handling code grows into prompt-response pipelines without switching languages.
Primary sources
Frequently asked questions
How do I handle non-integer input in this game?
Wrap the int(input()) call in a try-except ValueError block. If the conversion fails, print a message like 'Enter a valid integer' and continue the loop without counting that attempt.
Can I change the number range from 1 to 20 to 1 to 100?
Yes. Change the arguments passed to random.randint(). For 1 to 100, use random.randint(1, 100). Increase max_attempts proportionally; 7 guesses covers 1 to 100 optimally using binary search logic.
How do I add a play-again feature after the game ends?
Wrap the entire game in an outer while True loop. After the result prints, ask the player if they want to continue. Break out of the outer loop if they type 'n' or 'no'.
What is the difference between random.randint() and random.random()?
random.randint(a, b) returns a random integer between a and b inclusive. random.random() returns a float between 0.0 and 1.0. For a guessing game with whole numbers, randint() is the correct choice.
Why use while True instead of a for loop here?
A while True loop runs indefinitely until a break statement executes. This suits the basic version where there is no fixed attempt count. A for loop works for the max-attempts variant since the iteration count is known in advance.
A self-paced playground for building with LLMs.
TinkerLLM is FACE Prep's sister property. A guided environment for shipping real LLM applications, the kind of project that earns a paragraph on your resume, not a line.
Try TinkerLLM (₹299 launch)