Post

Build a game where the user guesses a randomly generated number.

Build a game where the user guesses a randomly generated number.

{% raw %}

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

  1. Welcome Message: Display a welcome message and explain the game rules to the user.
  2. Random Number Generation: Generate a random number within a specified range (e.g., 1 to 100).
  3. User Input: Prompt the user to guess the number.
  4. Feedback: Provide feedback on whether the guess is too high, too low, or correct.
  5. Repeat: Allow the user to guess again until they find the correct number.
  6. 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:

  1. 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.
  2. Maximum Attempts: Set a limit on the number of attempts (e.g., 5 or 10 attempts) to increase the challenge.
  3. Hints: Provide hints after a certain number of wrong guesses, such as whether the number is even or odd.
  4. Difficulty Levels: Offer different difficulty levels (easy, medium, hard) that affect the range of numbers and the number of attempts allowed.
  5. Play Again Option: After the game ends, ask if the user wants to play again.
  6. 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 randomdef get_user_guess():    try:        guess = int(input("Enter your guess: "))    except ValueError:            print("Invalid input. Please enter a valid integer.")            get_user_guess()    return guessdef get_random_number():    secret_number = random.randint(1, 100)    return secret_numberdef 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.")            breakif __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 randomdef 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_attemptsdef 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 osimport randomLEADERBOARD_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_attemptsdef 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 tkimport tkinter.simpledialogfrom tkinter import messageboximport randomimport osLEADERBOARD_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()

{% endraw %}

This post is licensed under CC BY 4.0 by the author.