Python Number Guessing Game — Your First Beginner Project
The Game Plan
Imagine you are playing a game where a friend thinks of a secret number between 1 and 100, and you have to guess it. After each guess, your friend tells you whether your guess is too high, too low, or exactly right. You keep guessing until you find the number.
This guide builds that exact game using Python. The computer picks the secret number, you type your guesses into the terminal, and Python tells you whether to guess higher or lower. Building it teaches you several fundamental Python skills in one self-contained project:
- How to store information in variables
- How to make decisions with if/else statements
- How to repeat code with while loops
- How to generate random numbers
- How to handle errors when someone types invalid input
- How to organize code into functions
By the end of this guide you will have a working game you can run and share with friends.
Making a Pick with random.randint()
Before the player can guess, something has to decide what the secret number is. That is where the random module comes in. A module in Python is a collection of pre-written code that you can load into your program and reuse. The random module contains tools for generating random values.
One of those tools is the function randint(a, b). The word “function” here means a named block of code that performs a specific task — you call it by writing its name followed by parentheses. randint takes two numbers as input and returns a random whole number between those two numbers, inclusive. Inclusive means both endpoints are possible choices.
Here is a quick example:
import random # Load the random module
# randint(1, 10) picks a random whole number from 1 to 10, including both 1 and 10
secret = random.randint(1, 10)
print(secret) # Prints whatever random number was chosen
The first line, import random, tells Python to load the random module. Without this line, Python would not know what random.randint means. After importing, you can call randint as many times as you like.
A common mistake involves a similar-looking function called randrange. random.randrange(1, 10) returns a number from 1 up to but NOT including 10. That means the highest possible number is 9, not 10. For this game we want both 1 and 10 to be valid secret numbers, so always use randint when you need the upper bound included.
Getting User Input with input()
Now the computer has picked a secret number. The next step is to ask the player to make a guess. In Python, the input() function displays a prompt on the screen and waits for the player to type something and press Enter. Whatever the player types gets returned as a text value.
An important detail: input() always returns a string. A string is Python’s name for a piece of text — a sequence of characters wrapped in quotes. Even if the player types the number 7, Python treats it as the string "7", not the number 7.
For our guessing game we need to compare the player’s guess against the secret number using mathematical comparison. You cannot compare a string to a number directly in Python — if you try, Python will give you an error or produce unexpected results.
The solution is to convert the player’s input from a string to an integer using the int() function. An integer (often abbreviated as “int”) is a whole number like 1, 42, or -7. Here is how that looks:
# Display the prompt and wait for the player to type
# Whatever they type gets stored in the variable 'guess' as a string
text_input = input("Guess a number between 1 and 10: ")
# Convert the string to an integer so we can compare it mathematically
guess = int(text_input)
# Now 'guess' holds an actual number, not text
print(guess) # Prints the number, not the text
If a player types something that cannot be converted to a whole number — like the word “hello” or the decimal number “3.5” — Python will raise an error when it tries to run int(). The next section shows how to handle that situation gracefully.
Your First Guessing Loop
With the secret number stored and a way to read the player’s guess, it is time to build the core game logic. The player should keep guessing until they get the right answer. A while loop lets you repeat a block of code as long as some condition remains true.
A while loop starts with the keyword while followed by a condition and a colon. Everything indented below runs repeatedly until the condition is false. Inside the loop, you need a way to eventually make that condition false — otherwise the loop runs forever, which is usually not what you want.
For this game, a common pattern is while True, which creates a loop that runs forever unless you explicitly break out of it. When the guess is correct, you break to exit the loop. Here is the full logic:
import random
secret = random.randint(1, 10) # Computer picks the secret number
while True: # Start an infinite loop — it keeps running until we hit 'break'
guess_text = input("Guess a number between 1 and 10: ")
guess = int(guess_text) # Convert the typed text to a number
if guess == secret: # Two equals signs means "is equal to" (comparison)
print("Correct!")
break # Exit the loop — the game is over
elif guess > secret: # Is the guess bigger than the secret number?
print("Too high")
else: # If it is not correct and not too high, it must be too low
print("Too low")
Study the if/elif/else block carefully. This is how Python makes decisions. The if statement checks a condition — if it is true, the indented code below it runs and Python skips the elif and else branches. If the if condition is false, Python checks elif (short for “else if”). If that is false too, the else block runs. Only one of these three branches executes per guess.
Handling Bad Input
The code above has a problem. If the player types “abc” instead of a number, int("abc") crashes the program with a ValueError. A better version wraps the conversion in a try/except block.
Think of try as meaning “attempt this code” and except as meaning “if something goes wrong, handle it like this instead of crashing”:
import random
secret = random.randint(1, 100)
while True:
guess_text = input("Guess a number between 1 and 100: ")
try:
# Attempt to convert the text to an integer
# If the player typed something that is not a whole number,
# Python jumps straight to the 'except' block below
guess = int(guess_text)
except ValueError:
# This runs only if the conversion failed
print("Please enter a whole number, not text or decimals.")
continue # Skip the rest of this loop iteration and start over
if guess == secret:
print("Correct!")
break
elif guess > secret:
print("Too high")
else:
print("Too low")
The continue keyword tells Python to stop the current trip through the loop and go back to the top, asking for a new guess. Notice that continue skips whatever comes after the try/except block — including any attempt counter. Typing invalid input does not cost the player a turn.
Limiting Attempts
The game above lets the player guess forever. A polished version sets a maximum number of attempts. You track attempts using a counter variable — a variable that starts at zero and increases by one each time through the loop. Instead of while True, you loop while attempts < max_attempts. When the counter reaches the limit, the loop ends and the player loses:
import random
secret = random.randint(1, 100)
max_attempts = 7
attempts = 0
while attempts < max_attempts:
# Show which attempt number this is (attempts + 1 because we start counting from 1)
guess_text = input(f"Guess (attempt {attempts + 1}/{max_attempts}): ")
try:
guess = int(guess_text)
except ValueError:
print("Enter a whole number.")
continue # Does not count as an attempt — player can retry the same turn
attempts += 1 # Increase the counter by 1
if guess == secret:
print(f"You got it in {attempts} tries!")
break # Player won, so stop looping
elif guess > secret:
print("Too high")
else:
print("Too low")
else:
# This 'else' on a while loop runs when the loop condition becomes False
# That happens when attempts reaches max_attempts
print(f"Out of attempts. The number was {secret}.")
Notice the f"..." string with curly braces. This is called an f-string (formatted string literal). It lets you insert variables directly inside a string by wrapping them in curly braces. f"You got it in {attempts} tries!" produces text like “You got it in 3 tries!” when attempts equals 3. F-strings, introduced in Python 3.6, let you combine text and variables inline.
The else clause attached to a while loop is a feature many beginners miss. Python runs the else block exactly once, right after the loop condition becomes false. In this game, that moment arrives when the player has used all their attempts without guessing correctly.
Adding Difficulty Levels
To make the game more replayable, offer different difficulty levels. Easy might use numbers 1 to 10, medium 1 to 100, and hard 1 to 1000. A Python dictionary maps difficulty names to their number ranges. A dictionary stores pairs of keys and values — here each difficulty name (“easy”, “medium”, “hard”) is a key that points to its corresponding maximum number:
import random
def play(difficulty):
# A dictionary that holds the maximum number for each difficulty
ranges = {
"easy": 10,
"medium": 100,
"hard": 1000
}
# Guard against invalid difficulty names
if difficulty not in ranges:
print("Unknown difficulty. Use easy, medium, or hard.")
return
# Look up the maximum number for the chosen difficulty
max_number = ranges[difficulty]
secret = random.randint(1, max_number)
attempts = 0
while attempts < 10:
try:
guess = int(input(f"Guess a number between 1 and {max_number}: "))
except ValueError:
print("Enter a whole number.")
continue
attempts += 1
if guess == secret:
print(f"You got it in {attempts} tries!")
return # Exit the function — the game is over for this round
elif guess > secret:
print("Too high")
else:
print("Too low")
print(f"Out of attempts. The number was {secret}.")
# Start a game on medium difficulty
play("medium")
The def play(difficulty): line defines a function. A function is a reusable block of code with a name. Writing play("medium") anywhere in your program runs all the code inside that function. Functions let you organize your code into clear, named steps instead of one long list of instructions.
The if difficulty not in ranges guard prevents a KeyError crash if someone calls play("extreme") or play(42). Always validate external input, even from your own code, before using it as a dictionary key.
Complete Example
Here is the full game combining all the concepts from this guide. Copy it into a file named guess.py and run it with python guess.py:
import random
def play(difficulty="medium"):
ranges = {"easy": 10, "medium": 100, "hard": 1000}
if difficulty not in ranges:
print("Unknown difficulty. Use easy, medium, or hard.")
return
max_number = ranges[difficulty]
secret = random.randint(1, max_number)
max_attempts = 7
attempts = 0
print(f"Guess a number between 1 and {max_number}.")
print(f"You have {max_attempts} attempts.\n")
while attempts < max_attempts:
try:
guess = int(input(f"Attempt {attempts + 1}/{max_attempts} — your guess: "))
except ValueError:
print("Please enter a whole number.\n")
continue
attempts += 1
if guess == secret:
print(f"Correct! You got it in {attempts} attempt(s).\n")
return
elif guess > secret:
print("Too high.\n")
else:
print("Too low.\n")
print(f"Out of attempts. The number was {secret}.\n")
# Start the game
play("medium")
And here is what a sample game looks like when you run it:
Guess a number between 1 and 100.
You have 7 attempts.
Attempt 1/7 — your guess: 50
Too low.
Attempt 2/7 — your guess: 75
Too high.
Attempt 3/7 — your guess: 62
Too low.
Attempt 4/7 — your guess: 68
Correct! You got it in 4 attempt(s).
Summary
Building a number guessing game taught you several core Python concepts working together:
random.randint(a, b)— picks a random whole number between a and b, inclusiveinput()— displays a prompt and reads what the player typesint()— converts a string of digits into an actual numbertry/except— catches errors so your program does not crash on bad inputif/elif/else— makes decisions based on conditionswhileloops — repeats code as long as a condition is truebreakandcontinue— controls exactly when a loop runs or stops- Functions (
def) — groups code into reusable, named blocks - Dictionaries — stores key-value pairs for easy lookup
As a next step, try adding a feature that lets the player play again without restarting the program, keeping track of how many games they have won. You could also build a simple graphical version using the turtle module, which is a fun way to see how the same logic looks on a canvas instead of in a terminal.
See Also
randommodule — Full reference for therandommodule, includingrandint()andrandrange()input()— Full reference for the built-in input functionint()— Full reference for the built-in integer conversion function