Building a number-guessing game in Python is a great way to practice control flow, user input, and random number generation. Below are some input ideas and the steps to implement this game.
Game Steps
- Welcome Message: Display a welcome message and explain the game rules to the user.
- Random Number Generation: Generate a random number within a specified range (e.g., 1 to 100).
- User Input: Prompt the user to guess the number.
- Feedback: Provide feedback on whether the guess is too high, too low, or correct.
- Repeat: Allow the user to guess again until they find the correct number.
- End Game: Congratulate the user and display the number of attempts taken.
Input Ideas
Here are some specific inputs you can use to enhance the game:
- Range of Numbers: Allow the user to choose the range (e.g., 1 to 50, 1 to 100, or 1 to 1000) to adjust the difficulty.
- Maximum Attempts: Set a limit on the number of attempts (e.g., 5 or 10 attempts) to increase the challenge.
- Hints: Provide hints after a certain number of wrong guesses, such as whether the number is even or odd.
- Difficulty Levels: Offer different difficulty levels (easy, medium, hard) that affect the range of numbers and the number of attempts allowed.
- Play Again Option: After the game ends, ask if the user wants to play again.
- Input Validation: Ensure the user inputs a valid number within the specified range.
Additional Features
- Scoring System: Introduce a scoring system based on the number of attempts.
- Leaderboard: Track and display the top scores or fastest guesses.
- Graphical Interface: Use a library like Tkinter to create a GUI version of the game.
Solutions
A. Simple CLI Game
The game generates a random number between 1 and 100 using random.randint(1, 100).
User Input: The user is prompted to guess the number.
Feedback: The game provides feedback after each guess:
- If the guess is too low, it prompts the user to guess higher.
- If the guess is too high, it prompts the user to guess lower.
Win Condition: When the user guesses the correct number, the game congratulates the player and displays the number of attempts it took to guess correctly.
import random
def get_user_guess():
try:
guess = int(input("Enter your guess: "))
except ValueError:
print("Invalid input. Please enter a valid integer.")
get_user_guess()
return guess
def get_random_number():
secret_number = random.randint(1, 100)
return secret_number
def number_guessing_game():
"""
A simple number guessing game where the user tries to guess a randomly
generated number between 1 and 100.
"""
# Generate a random number between 1 and 100
secret_number = get_random_number()
attempts = 0
print("Welcome to the Number Guessing Game!")
print("I'm thinking of a number between 1 and 100.")
while True:
attempts += 1
guess = get_user_guess()
# Check if the guess is correct
if guess < secret_number:
print("Too low! Try again.")
elif guess > secret_number:
print("Too high! Try again.")
else:
print(f"Congratulations! You guessed the number in {attempts} attempts.")
break
if __name__ == "__main__":
number_guessing_game()
B. With Difficulty Levels, Play Again Option, Input Validations
- Range of Numbers: The range of numbers is adjusted based on the selected difficulty level.
- Maximum Attempts: The number of attempts is limited based on the difficulty level.
- Hints: A hint is provided after half of the maximum attempts if the player has not yet guessed the correct number.
- Difficulty Levels: Three difficulty levels (Easy, Medium, Hard) determine the range of numbers and the number of attempts.
- Play Again Option: After the game ends, the player is asked if they want to play again.
- Input Validation: The game ensures that the user inputs a valid number within the specified range.
import random
def print_menu():
"""
Function to print menu"""
print("Welcome to the Enhanced Number Guessing Game!")
# Select difficulty level
print("Select difficulty level:")
print("1. Easy (Range: 1-50, 10 attempts)")
print("2. Medium (Range: 1-100, 7 attempts)")
print("3. Hard (Range: 1-1000, 5 attempts)")
def get_min_max_total_attempts(difficulty):
# Set parameters based on difficulty level
if difficulty == 1:
min_value, max_value, max_attempts = 1, 50, 10
elif difficulty == 2:
min_value, max_value, max_attempts = 1, 100, 7
else:
min_value, max_value, max_attempts = 1, 1000, 5
return min_value, max_value, max_attempts
def play(secret_number, min_value, max_value, max_attempts):
attempts = 0
hints_given = False
print(f"\nI'm thinking of a number between {min_value} and {max_value}.")
print(f"You have {max_attempts} attempts to guess it.\n")
while attempts < max_attempts:
guess = get_valid_number(f"Attempt {attempts + 1}: Enter your guess: ", min_value, max_value)
attempts += 1
if guess < secret_number:
print("Too low! Try again.")
elif guess > secret_number:
print("Too high! Try again.")
else:
print(f"Congratulations! You guessed the number in {attempts} attempts.")
break
# Provide a hint after half the attempts if the user hasn't guessed correctly
if attempts == max_attempts // 2 and not hints_given:
hint = "even" if secret_number % 2 == 0 else "odd"
print(f"Hint: The number is {hint}.")
hints_given = True
if attempts == max_attempts and guess != secret_number:
print(f"\nSorry, you've used all {max_attempts} attempts. The correct number was {secret_number}.")
def get_valid_number(prompt, min_value, max_value):
"""Helper function to get a valid number within a specified range."""
while True:
try:
num = int(input(prompt))
if min_value <= num <= max_value:
return num
else:
print(f"Please enter a number between {min_value} and {max_value}.")
except ValueError:
print("Invalid input. Please enter a valid integer.")
def play_again():
# Ask the user if they want to play again
play_again = input("\nDo you want to play again? (yes/no): ").strip().lower()
if play_again == 'yes':
number_guessing_game()
else:
print("Thank you for playing! Goodbye.")
def number_guessing_game():
"""
An enhanced number guessing game where the user selects a difficulty level
and attempts to guess a randomly generated number within a range.
"""
print_menu()
difficulty = get_valid_number("Choose a difficulty level (1, 2, or 3): ", 1, 3)
min_value, max_value, max_attempts = get_min_max_total_attempts(difficulty)
secret_number = random.randint(min_value, max_value)
play(secret_number, min_value, max_value, max_attempts)
play_again()
if __name__ == "__main__":
number_guessing_game()
C. With Leaderboard
import os
import random
LEADERBOARD_FILE = "leaderboard.txt"
def load_leaderboard():
"""Load the leaderboard from a file."""
if os.path.exists(LEADERBOARD_FILE):
with open(LEADERBOARD_FILE, "r") as file:
leaderboard = [line.strip().split(",") for line in file.readlines()]
leaderboard = [(name, int(score)) for name, score in leaderboard]
return sorted(leaderboard, key=lambda x: x[1])
return []
def save_leaderboard(leaderboard):
"""Save the leaderboard to a file."""
with open(LEADERBOARD_FILE, "w") as file:
for name, score in leaderboard:
file.write(f"{name},{score}\n")
def display_leaderboard(leaderboard):
"""Display the top scores from the leaderboard."""
print("\n--- Leaderboard ---")
if leaderboard:
for i, (name, score) in enumerate(leaderboard[:10], start=1):
print(f"{i}. {name}: {score} attempts")
else:
print("No scores yet. Be the first to play!")
print("-------------------\n")
def update_leaderboard(player_name, attempts):
"""Update the leaderboard with the player's score."""
leaderboard = load_leaderboard()
leaderboard.append((player_name, attempts))
leaderboard = sorted(leaderboard, key=lambda x: x[1])[:10] # Keep only top 10 scores
save_leaderboard(leaderboard)
def print_menu():
"""
Function to print menu"""
print("Welcome to the Enhanced Number Guessing Game!")
# Select difficulty level
print("Select difficulty level:")
print("1. Easy (Range: 1-50, 10 attempts)")
print("2. Medium (Range: 1-100, 7 attempts)")
print("3. Hard (Range: 1-1000, 5 attempts)")
def get_min_max_total_attempts(difficulty):
# Set parameters based on difficulty level
if difficulty == 1:
min_value, max_value, max_attempts = 1, 50, 10
elif difficulty == 2:
min_value, max_value, max_attempts = 1, 100, 7
else:
min_value, max_value, max_attempts = 1, 1000, 5
return min_value, max_value, max_attempts
def play(secret_number, min_value, max_value, max_attempts):
attempts = 0
hints_given = False
print(f"\nI'm thinking of a number between {min_value} and {max_value}.")
print(f"You have {max_attempts} attempts to guess it.\n")
while attempts < max_attempts:
guess = get_valid_number(f"Attempt {attempts + 1}: Enter your guess: ", min_value, max_value)
attempts += 1
if guess < secret_number:
print("Too low! Try again.")
elif guess > secret_number:
print("Too high! Try again.")
else:
print(f"Congratulations! You guessed the number in {attempts} attempts.")
player_name = input("Enter your name for the leaderboard: ").strip()
update_leaderboard(player_name, attempts)
break
# Provide a hint after half the attempts if the user hasn't guessed correctly
if attempts == max_attempts // 2 and not hints_given:
hint = "even" if secret_number % 2 == 0 else "odd"
print(f"Hint: The number is {hint}.")
hints_given = True
if attempts == max_attempts and guess != secret_number:
print(f"\nSorry, you've used all {max_attempts} attempts. The correct number was {secret_number}.")
def get_valid_number(prompt, min_value, max_value):
"""Helper function to get a valid number within a specified range."""
while True:
try:
num = int(input(prompt))
if min_value <= num <= max_value:
return num
else:
print(f"Please enter a number between {min_value} and {max_value}.")
except ValueError:
print("Invalid input. Please enter a valid integer.")
def play_again():
# Ask the user if they want to play again
play_again = input("\nDo you want to play again? (yes/no): ").strip().lower()
if play_again == 'yes':
number_guessing_game()
else:
print("Thank you for playing! Goodbye.")
def number_guessing_game():
"""
An enhanced number guessing game where the user selects a difficulty level
and attempts to guess a randomly generated number within a range.
"""
display_leaderboard(load_leaderboard())
print_menu()
difficulty = get_valid_number("Choose a difficulty level (1, 2, or 3): ", 1, 3)
min_value, max_value, max_attempts = get_min_max_total_attempts(difficulty)
secret_number = random.randint(min_value, max_value)
play(secret_number, min_value, max_value, max_attempts)
display_leaderboard(load_leaderboard())
play_again()
if __name__ == "__main__":
number_guessing_game()
D. With TkInter Gui
- Graphical User Interface (GUI): Uses Tkinter to create a window-based interface for the game.
- Difficulty Levels: Players can select from three difficulty levels that adjust the range of numbers and the number of attempts.
- Scoring System: Keeps track of how many attempts it takes the player to guess the correct number.
- Leaderboard: The top 10 scores are saved to a file and can be viewed through the GUI.
- Hints: After half the maximum attempts, the player is provided a hint whether the number is even or odd.
- Input Validation: Ensures that the player inputs a valid integer within the specified range.
- Play Again: After a game ends, the interface resets, allowing the player to start a new game.
import tkinter as tk
import tkinter.simpledialog
from tkinter import messagebox
import random
import os
LEADERBOARD_FILE = "leaderboard.txt"
class NumberGuessingGame:
def __init__(self, root):
self.root = root
self.root.title("Number Guessing Game")
self.min_value = 1
self.max_value = 100
self.max_attempts = 10
self.attempts = 0
self.secret_number = 0
self.player_name = ""
self.hints_given = False
self.create_widgets()
def create_widgets(self):
"""Create the main interface widgets."""
self.difficulty_label = tk.Label(self.root, text="Select Difficulty Level:")
self.difficulty_label.pack(pady=10)
self.difficulty_var = tk.IntVar(value=2)
self.difficulty_easy = tk.Radiobutton(self.root, text="Easy (1-50)", variable=self.difficulty_var, value=1, command=self.set_difficulty)
self.difficulty_medium = tk.Radiobutton(self.root, text="Medium (1-100)", variable=self.difficulty_var, value=2, command=self.set_difficulty)
self.difficulty_hard = tk.Radiobutton(self.root, text="Hard (1-1000)", variable=self.difficulty_var, value=3, command=self.set_difficulty)
self.difficulty_easy.pack()
self.difficulty_medium.pack()
self.difficulty_hard.pack()
self.start_button = tk.Button(self.root, text="Start Game", command=self.start_game)
self.start_button.pack(pady=10)
self.guess_label = tk.Label(self.root, text="Enter your guess:")
self.guess_entry = tk.Entry(self.root)
self.submit_button = tk.Button(self.root, text="Submit Guess", command=self.check_guess)
self.attempts_label = tk.Label(self.root, text="Attempts left: N/A")
self.leaderboard_button = tk.Button(self.root, text="Show Leaderboard", command=self.show_leaderboard)
self.leaderboard_button.pack(pady=10)
def set_difficulty(self):
"""Set the game difficulty based on user selection."""
difficulty = self.difficulty_var.get()
if difficulty == 1:
self.min_value, self.max_value, self.max_attempts = 1, 50, 10
elif difficulty == 2:
self.min_value, self.max_value, self.max_attempts = 1, 100, 7
else:
self.min_value, self.max_value, self.max_attempts = 1, 1000, 5
def start_game(self):
"""Start the game by generating a random number and resetting the attempts."""
self.secret_number = random.randint(self.min_value, self.max_value)
self.attempts = 0
self.hints_given = False
self.difficulty_label.pack_forget()
self.difficulty_easy.pack_forget()
self.difficulty_medium.pack_forget()
self.difficulty_hard.pack_forget()
self.start_button.pack_forget()
self.guess_label.pack(pady=10)
self.guess_entry.pack(pady=10)
self.submit_button.pack(pady=10)
self.attempts_label.pack(pady=10)
self.update_attempts_label()
def update_attempts_label(self):
"""Update the label that shows how many attempts are left."""
attempts_left = self.max_attempts - self.attempts
self.attempts_label.config(text=f"Attempts left: {attempts_left}")
def check_guess(self):
"""Check the user's guess and provide feedback."""
try:
guess = int(self.guess_entry.get())
if guess < self.min_value or guess > self.max_value:
messagebox.showerror("Error", f"Please enter a number between {self.min_value} and {self.max_value}.")
return
except ValueError:
messagebox.showerror("Error", "Please enter a valid integer.")
return
self.attempts += 1
self.update_attempts_label()
if guess < self.secret_number:
messagebox.showinfo("Result", "Too low! Try again.")
elif guess > self.secret_number:
messagebox.showinfo("Result", "Too high! Try again.")
else:
messagebox.showinfo("Congratulations!", f"You guessed the number in {self.attempts} attempts.")
self.record_score()
self.reset_game()
return
if self.attempts == self.max_attempts:
messagebox.showinfo("Game Over", f"Sorry, you've used all {self.max_attempts} attempts. The correct number was {self.secret_number}.")
self.reset_game()
if self.attempts == self.max_attempts // 2 and not self.hints_given:
hint = "even" if self.secret_number % 2 == 0 else "odd"
messagebox.showinfo("Hint", f"Hint: The number is {hint}.")
self.hints_given = True
def record_score(self):
"""Record the player's score and update the leaderboard."""
self.player_name = tkinter.simpledialog.askstring("Name", "Enter your name for the leaderboard:")
if not self.player_name:
self.player_name = "Anonymous"
leaderboard = self.load_leaderboard()
leaderboard.append((self.player_name, self.attempts))
leaderboard = sorted(leaderboard, key=lambda x: x[1])[:10] # Keep only top 10 scores
self.save_leaderboard(leaderboard)
def load_leaderboard(self):
"""Load the leaderboard from a file."""
if os.path.exists(LEADERBOARD_FILE):
with open(LEADERBOARD_FILE, "r") as file:
leaderboard = [line.strip().split(",") for line in file.readlines()]
return [(name, int(score)) for name, score in leaderboard]
return []
def save_leaderboard(self, leaderboard):
"""Save the leaderboard to a file."""
with open(LEADERBOARD_FILE, "w") as file:
for name, score in leaderboard:
file.write(f"{name},{score}\n")
def show_leaderboard(self):
"""Display the top scores from the leaderboard."""
leaderboard = self.load_leaderboard()
if leaderboard:
leaderboard_str = "\n".join([f"{i+1}. {name}: {score} attempts" for i, (name, score) in enumerate(leaderboard)])
else:
leaderboard_str = "No scores yet. Be the first to play!"
messagebox.showinfo("Leaderboard", leaderboard_str)
def reset_game(self):
"""Reset the game to the initial state."""
self.guess_label.pack_forget()
self.guess_entry.pack_forget()
self.submit_button.pack_forget()
self.attempts_label.pack_forget()
self.difficulty_label.pack(pady=10)
self.difficulty_easy.pack()
self.difficulty_medium.pack()
self.difficulty_hard.pack()
self.start_button.pack(pady=10)
if __name__ == "__main__":
root = tk.Tk()
app = NumberGuessingGame(root)
root.mainloop()
