Category: Fun & Experiments

Creative and playful Python projects to explore coding in a fun way.

  • Level Up Your Web Skills: Creating a Simple “Guess the Number” Game with Django

    Welcome, aspiring web developers and coding enthusiasts! Have you ever wanted to build something interactive on the web, perhaps a simple game, but felt overwhelmed by complex frameworks? Well, you’re in luck! Today, we’re going to dive into the exciting world of Django and create a fun, classic “Guess the Number” game.

    Django is a powerful and popular web framework for Python.
    Web Framework: Think of a web framework as a toolkit that provides all the essential tools and structures you need to build a website or web application quickly and efficiently, without starting entirely from scratch.
    Django helps you build robust web applications with less code, making it perfect for both beginners and experienced developers. While it’s often used for complex sites, its simplicity and clear structure make it surprisingly great for fun, experimental projects like a game!

    By the end of this guide, you’ll have a basic understanding of how Django works and a working “Guess the Number” game you can play right in your browser. Let’s get started!

    What We’ll Build: “Guess the Number”

    Our game will be straightforward:
    * The computer will randomly pick a secret number between 1 and 100.
    * You, the player, will guess a number.
    * The game will tell you if your guess is “too high,” “too low,” or “correct.”
    * It will also keep track of how many guesses you’ve made.

    This game will introduce you to key Django concepts like views, URLs, and templates, along with a touch of Python logic.

    Prerequisites: Getting Ready

    Before we jump into Django, make sure you have these essentials in place:

    • Python: You should have Python installed on your computer (version 3.6 or higher is recommended). If not, head over to python.org to download and install it.
    • Basic Python Knowledge: Familiarity with Python basics like variables, functions, and conditional statements (if/else) will be very helpful.
    • pip: This is Python’s package installer, usually included with Python installations. We’ll use it to install Django.

    Step 1: Setting Up Your Django Project

    It’s good practice to set up a virtual environment for each Django project.

    • Virtual Environment: Imagine a separate, isolated space on your computer where your project’s Python packages live. This prevents conflicts between different projects that might need different versions of the same package.

    Let’s open your terminal or command prompt and get started:

    1. Create a Project Folder:
      First, create a folder for your game project and navigate into it.

      bash
      mkdir django_game
      cd django_game

    2. Create and Activate a Virtual Environment:
      bash
      python -m venv venv

      • On Windows:
        bash
        venv\Scripts\activate
      • On macOS/Linux:
        bash
        source venv/bin/activate

        You’ll see (venv) appearing at the beginning of your terminal prompt, indicating that your virtual environment is active.
    3. Install Django:
      Now that your virtual environment is active, install Django using pip.

      bash
      pip install django

    4. Start a New Django Project:
      A Django project is a collection of settings and applications that together make a website.

      bash
      django-admin startproject guess_the_number_project .

      guess_the_number_project: This is the name of your project.
      .: This tells Django to create the project files in the current directory (your django_game folder), rather than creating another nested folder.

    5. Create a Django App:
      Within your project, you typically create one or more “apps.” An app is a self-contained module that does one specific thing, like handling users, blogs, or, in our case, the game itself. This keeps your code organized.

      bash
      python manage.py startapp game

      This creates a new folder named game with several files inside.

    6. Register Your App:
      Django needs to know about the new app you’ve created. Open the guess_the_number_project/settings.py file and add 'game' to the INSTALLED_APPS list.

      “`python

      guess_the_number_project/settings.py

      INSTALLED_APPS = [
      ‘django.contrib.admin’,
      ‘django.contrib.auth’,
      ‘django.contrib.contenttypes’,
      ‘django.contrib.sessions’,
      ‘django.contrib.messages’,
      ‘django.contrib.staticfiles’,
      ‘game’, # Add your new app here
      ]
      “`

    7. Run Migrations (Optional but Good Practice):
      Django uses migrations to set up and update your database schema (the structure of your database). Even though our simple game won’t use a database for its core logic, it’s good practice to run migrations after creating a project.

      bash
      python manage.py migrate

    Step 2: Defining URLs

    URLs are how users access different parts of your website. We need to tell Django which URL patterns should trigger which parts of our game logic.

    1. Project-Level urls.py:
      First, open guess_the_number_project/urls.py and tell Django to look for URLs defined within our game app.

      “`python

      guess_the_number_project/urls.py

      from django.contrib import admin
      from django.urls import path, include # Import include

      urlpatterns = [
      path(‘admin/’, admin.site.urls),
      path(‘game/’, include(‘game.urls’)), # Include game app URLs
      ]
      ``
      Here,
      path(‘game/’, include(‘game.urls’))means that any URL starting with/game/will be handed over to thegameapp'surls.py` file.

    2. App-Level urls.py:
      Now, inside your game app folder, create a new file named urls.py. This file will define the specific URL patterns for our game.

      “`python

      game/urls.py

      from django.urls import path
      from . import views

      urlpatterns = [
      path(”, views.start_game, name=’start_game’),
      path(‘play/’, views.play_game, name=’play_game’),
      ]
      ``
      -
      path(”, views.start_game, name=’start_game’): When someone visits/game/(because of theinclude(‘game.urls’)above), this will call thestart_gamefunction ingame/views.py.
      -
      path(‘play/’, views.play_game, name=’play_game’): When someone visits/game/play/, this will call theplay_gamefunction ingame/views.py`.

    Step 3: Crafting the Game Logic (Views)

    Django “views” are Python functions that receive a web request, process it, and return a web response (like an HTML page). Our game logic will live here.

    Open game/views.py and replace its content with the following:

    from django.shortcuts import render, redirect
    import random
    
    
    def start_game(request):
        """
        Initializes a new game: generates a secret number and resets guess count.
        """
        request.session['secret_number'] = random.randint(1, 100)
        request.session['guesses'] = 0
        request.session['feedback'] = "I'm thinking of a number between 1 and 100. Can you guess it?"
        return redirect('play_game') # Redirect to the play page
    
    def play_game(request):
        """
        Handles user guesses and provides feedback.
        """
        secret_number = request.session.get('secret_number')
        guesses = request.session.get('guesses')
        feedback = request.session.get('feedback')
    
        if secret_number is None or guesses is None:
            # If session data is missing, start a new game
            return redirect('start_game')
    
        message = feedback
        guess_made = False
    
        if request.method == 'POST':
            # --- Supplementary Explanation: HTTP POST Request ---
            # HTTP POST Request: Used when a web browser sends data to the server,
            # typically from a form submission. It's used here to send the user's guess.
            try:
                user_guess = int(request.POST.get('guess'))
                guesses += 1
                request.session['guesses'] = guesses
                guess_made = True
    
                if user_guess < secret_number:
                    message = "Too low! Try again."
                elif user_guess > secret_number:
                    message = "Too high! Try again."
                else:
                    message = f"Congratulations! You guessed the number {secret_number} in {guesses} guesses!"
                    # Game over, clear session data or offer to restart
                    request.session['secret_number'] = None # Clear secret number
                    request.session['guesses'] = None # Clear guesses
                    request.session['feedback'] = message + " Click 'Restart Game' to play again."
    
            except (ValueError, TypeError):
                message = "Invalid input. Please enter a whole number."
    
            request.session['feedback'] = message # Update feedback for next rendering
    
            # After POST, redirect to the same page to prevent re-submission on refresh
            # This is a common pattern called Post/Redirect/Get (PRG)
            return redirect('play_game')
    
        # For GET requests or after POST-redirect, render the game page
        context = {
            'message': message,
            'guesses': guesses,
            'game_over': request.session.get('secret_number') is None # True if game is over
        }
        return render(request, 'game/game.html', context)
    
    • start_game: This function is called when a new game begins. It generates a random secret number and initializes the guess count, storing them in the user’s session. It then redirects to the play_game view.
    • play_game: This is the main game logic.
      • It retrieves the secret number, guess count, and feedback message from the session.
      • If the request is a POST (meaning the user submitted a guess), it processes the guess: checks if it’s too high, too low, or correct, updates the guess count, and stores new feedback.
      • It uses request.session to store temporary data specific to the current user’s interaction with the website, which is perfect for our game state.
      • Finally, it prepares data (context) and renders the game/game.html template.

    Step 4: Designing the User Interface (Templates)

    Django “templates” are HTML files with special Django syntax that allow you to display dynamic content from your Python views.

    1. Create Template Folders:
      Inside your game app folder, create a new folder named templates, and inside that, another folder named game. This structure (app_name/templates/app_name/your_template.html) helps Django find your templates and keeps them organized.

      django_game/
      ├── guess_the_number_project/
      ├── game/
      │ ├── templates/
      │ │ └── game/
      │ │ └── game.html <-- This is where our game's HTML will go
      │ ├── __init__.py
      │ ├── admin.py
      │ ├── apps.py
      │ ├── models.py
      │ ├── tests.py
      │ ├── urls.py
      │ └── views.py
      ├── manage.py
      └── venv/

    2. Create game.html:
      Now, create a file named game.html inside game/templates/game/ and add the following HTML:

      “`html

      <!DOCTYPE html>




      Guess the Number!


      Guess the Number!

          <p class="message">{{ message }}</p>
      
          {% if game_over %}
              <p>What a game! You can restart below.</p>
              <form action="{% url 'start_game' %}" method="post">
                  {% csrf_token %} {# Required for all Django forms #}
                  <button type="submit">Restart Game</button>
              </form>
          {% else %}
              <form action="{% url 'play_game' %}" method="post">
                  {% csrf_token %} {# Required for all Django forms #}
                  <input type="number" name="guess" min="1" max="100" placeholder="Enter your guess" required autofocus>
                  <button type="submit">Guess</button>
              </form>
              <p class="guesses">Guesses: {{ guesses }}</p>
          {% endif %}
      
      </div>
      



      ``
      * **
      {{ message }}and{{ guesses }}:** These are Django template tags that display themessageandguessesvariables passed from ourplay_gameview function via thecontextdictionary.
      * **
      {% if game_over %}and{% else %}:** These are Django template tags for conditional logic, allowing us to display different content based on whether the game is over or not.
      * **

      :** This creates an HTML form.
      *
      action=”{% url ‘play_game’ %}”: The{% url %}template tag dynamically generates the URL for theplay_gameview, ensuring it's always correct.
      *
      method=”post”: This means the form data will be sent using an HTTP POST request.
      * **
      {% csrf_token %}:** This is a crucial security feature in Django.
      * **CSRF (Cross-Site Request Forgery):** A type of malicious exploit where an attacker tricks a logged-in user into unknowingly submitting a request to a web application. The
      csrf_token` protects your forms from this by ensuring that the request originated from your own website. Always include it in your forms!

    Step 5: Running Your Game

    You’ve done all the hard work! Now it’s time to see your game in action.

    1. Start the Development Server:
      Make sure your virtual environment is active and you are in the django_game directory (the one containing manage.py).

      bash
      python manage.py runserver

      You should see output similar to this:

      “`
      Watching for file changes with StatReloader
      Performing system checks…

      System check identified no issues (0 silenced).

      You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
      Run ‘python manage.py migrate’ to apply them.
      August 09, 2023 – 14:30:00
      Django version 4.2.4, using settings ‘guess_the_number_project.settings’
      Starting development server at http://127.0.0.1:8000/
      Quit the server with CONTROL-C.
      “`

    2. Open in Browser:
      Open your web browser and navigate to http://127.0.0.1:8000/game/.

      You should see your “Guess the Number!” game. Try guessing numbers, and the game will tell you if you’re too high or too low. Once you guess correctly, you’ll see a congratulatory message and a “Restart Game” button.

    What’s Next? Ideas for Improvement

    This simple game is just the beginning! Here are some ideas to expand your project and learn more about Django:

    • Add a High Score List: This would involve creating a Django Model (a Python class that represents a table in your database) to store player names and their number of guesses. You’d then learn how to save and retrieve data from a database.
    • Multiple Difficulty Levels: Allow players to choose a range (e.g., 1-10, 1-1000).
    • User Accounts: Use Django’s built-in authentication system to allow users to create accounts, log in, and track their personal best scores.
    • CSS Styling: Improve the look and feel with more advanced CSS or a CSS framework like Bootstrap.
    • Make it a “Hangman” or “Tic-Tac-Toe” Game: Challenge yourself to implement more complex game logic within the Django framework.

    Conclusion

    Congratulations! You’ve successfully built a basic web-based game using Django. You’ve touched upon setting up a project, defining URLs, writing view logic, and creating HTML templates. Django provides a robust and elegant way to build web applications, and even simple games can be a fantastic way to learn its core concepts. Keep experimenting, keep building, and have fun on your coding journey!


  • Creating a Simple Minesweeper Game with Python

    Introduction: Digging into Fun!

    Welcome, aspiring Pythonistas and game enthusiasts! Today, we’re going to embark on a fun project: building a simplified version of the classic game Minesweeper using Python. Even if you’re new to programming, don’t worry! We’ll break down each step using simple language and clear explanations.

    What is Minesweeper?

    Minesweeper is a single-player puzzle game. The goal is to clear a rectangular board containing hidden “mines” without detonating any of them. If you click on a cell with a mine, you lose! If you click on a safe cell, it reveals a number. This number tells you how many mines are in the eight surrounding cells (including diagonals). These numbers are your clues to figure out where the mines are located.

    Why Build it in Python?

    Python is a fantastic language for beginners because it’s easy to read and write. Creating a game like Minesweeper is an excellent way to practice several core programming concepts:

    • Variables and Data Structures: Storing information like our game board.
    • Loops: Repeating actions, like checking all cells or running the game.
    • Conditional Statements: Making decisions, like “Is this a mine?”
    • Functions: Organizing our code into reusable blocks.
    • User Input: Interacting with the player.

    By the end of this tutorial, you’ll have a working text-based Minesweeper game and a better understanding of how these concepts come together. Let’s get started!

    The Building Blocks of Our Game

    Before we write any code, let’s think about the main parts we need for our game:

    • The Grid (Game Board): This is where all the action happens. We need a way to represent a grid of cells.
    • Mines: These are the hidden dangers. We’ll need to place them randomly on our grid.
    • Numbers (Clues): For every cell that doesn’t have a mine, we need to calculate and store a number indicating how many mines are nearby.
    • Player Actions: The player needs to be able to “click” (or choose) a cell on the board.
    • Display: We need to show the player what the board looks like, hiding unrevealed cells and showing numbers or mines for revealed ones.

    Setting Up Your Python Project

    The great news is you don’t need to install anything special for this project! Python comes with everything we need. Just make sure you have Python installed on your computer. You can write your code in any text editor and run it from your terminal or command prompt.

    Step-by-Step Implementation

    We’ll build our game step by step, explaining each piece of code.

    1. Representing the Game Board

    How do we represent a grid in Python? The easiest way for a game board is using a “list of lists,” also known as a 2D list or nested list.
    Imagine a spreadsheet: each row is a list, and all those row lists are put together into one big list.

    We’ll need two main grids:
    * board: This will store the actual content of each cell (either a mine 'M' or a number 0-8).
    * display_board: This is what the player sees. Initially, all cells are hidden (e.g., '-'). When a player reveals a cell, we update display_board with the content from board.

    Let’s start by initializing these boards.

    import random
    
    def initialize_boards(rows, cols):
        """
        Creates two empty boards: one for game logic and one for display.
    
        Args:
            rows (int): The number of rows in the board.
            cols (int): The number of columns in the board.
    
        Returns:
            tuple: A tuple containing (board, display_board).
                   'board' holds '0' for empty cells initially.
                   'display_board' holds '-' for hidden cells.
        """
        board = [['0' for _ in range(cols)] for _ in range(rows)]
        display_board = [['-' for _ in range(cols)] for _ in range(rows)]
        return board, display_board
    

    2. Placing the Mines

    Now, let’s randomly place our mines on the board. We’ll use Python’s built-in random module for this.

    Technical Term: random module
    The random module in Python provides functions to generate random numbers. random.randint(a, b) will give you a random whole number between a and b (inclusive). This is perfect for picking random row and column numbers.

    def place_mines(board, num_mines):
        """
        Randomly places mines ('M') on the game board.
    
        Args:
            board (list of lists): The game board where mines will be placed.
            num_mines (int): The total number of mines to place.
        """
        rows = len(board)
        cols = len(board[0])
        mines_placed = 0
    
        while mines_placed < num_mines:
            r = random.randint(0, rows - 1) # Pick a random row
            c = random.randint(0, cols - 1) # Pick a random column
    
            if board[r][c] != 'M': # If there isn't already a mine here
                board[r][c] = 'M'
                mines_placed += 1
    

    3. Calculating the Clues (Numbers)

    After placing mines, we need to calculate the numbers for all the non-mine cells. For each cell that is not a mine, we look at its eight surrounding neighbors (up, down, left, right, and diagonals) and count how many of them contain a mine.

    Technical Term: Adjacent Cells
    “Adjacent” simply means “next to.” In a grid, a cell typically has 8 adjacent cells: one directly above, below, left, right, and one in each of the four diagonal directions.

    def calculate_numbers(board):
        """
        Calculates the number of adjacent mines for each non-mine cell.
    
        Args:
            board (list of lists): The game board with mines placed.
        """
        rows = len(board)
        cols = len(board[0])
    
        for r in range(rows):
            for c in range(cols):
                if board[r][c] == 'M':
                    continue # Skip if it's a mine
    
                mine_count = 0
                # Check all 8 adjacent cells
                for dr in [-1, 0, 1]: # Delta row: -1 (up), 0 (same row), 1 (down)
                    for dc in [-1, 0, 1]: # Delta col: -1 (left), 0 (same col), 1 (right)
                        if dr == 0 and dc == 0: # Skip the current cell itself
                            continue
    
                        nr, nc = r + dr, c + dc # Neighbor row, neighbor col
    
                        # Check if the neighbor is within the board boundaries
                        if 0 <= nr < rows and 0 <= nc < cols:
                            if board[nr][nc] == 'M':
                                mine_count += 1
                board[r][c] = str(mine_count) # Store the count as a string
    

    4. Displaying the Board to the Player

    This function will print the display_board to the console, making it readable for the player. We’ll also add row and column numbers to help the player choose cells.

    def print_display_board(display_board):
        """
        Prints the current state of the display board to the console.
        """
        rows = len(display_board)
        cols = len(display_board[0])
    
        # Print column numbers
        print("  ", end="")
        for c in range(cols):
            print(f" {c}", end="")
        print()
    
        # Print a separator line
        print("  " + "---" * cols)
    
        # Print row numbers and board content
        for r in range(rows):
            print(f"{r} |", end="")
            for c in range(cols):
                print(f" {display_board[r][c]}", end="")
            print(" |")
        print("  " + "---" * cols)
    

    5. Handling Player Moves

    The game needs to ask the player for their desired move (row and column) and make sure it’s a valid choice.

    def get_player_move(rows, cols):
        """
        Prompts the player to enter their move (row and column).
    
        Args:
            rows (int): Total number of rows on the board.
            cols (int): Total number of columns on the board.
    
        Returns:
            tuple: (row, col) if input is valid, otherwise asks again.
        """
        while True:
            try:
                move_input = input(f"Enter your move (row column, e.g., 0 0): ").split()
                r, c = int(move_input[0]), int(move_input[1])
    
                if 0 <= r < rows and 0 <= c < cols:
                    return r, c
                else:
                    print("Invalid input. Row and column must be within board limits.")
            except (ValueError, IndexError):
                print("Invalid input format. Please enter two numbers separated by a space.")
    

    6. Putting It All Together: The Game Loop

    This is where the magic happens! The play_game function will bring all our previous functions together, managing the game flow, checking win/loss conditions, and letting the player keep playing until the game ends.

    Technical Term: Game Loop
    A “game loop” is a fundamental concept in game programming. It’s a while loop that continuously runs the main actions of the game: getting player input, updating the game state, and displaying the game, until a condition (like game over or win) is met.

    def play_game():
        """
        Main function to run the Minesweeper game.
        """
        print("Welcome to Simple Minesweeper!")
    
        # You can change these values to make the board bigger or smaller
        board_rows = 5
        board_cols = 5
        number_of_mines = 4 
    
        # Initialize the board and display board
        game_board, current_display = initialize_boards(board_rows, board_cols)
        place_mines(game_board, number_of_mines)
        calculate_numbers(game_board)
    
        game_over = False
        mines_hit = False
        safe_cells_revealed = 0
        total_safe_cells = (board_rows * board_cols) - number_of_mines
    
        while not game_over:
            print_display_board(current_display)
    
            # Get player move
            row, col = get_player_move(board_rows, board_cols)
    
            # Check if the cell is already revealed
            if current_display[row][col] != '-':
                print("This cell is already revealed. Choose another one.")
                continue
    
            # Reveal the cell
            cell_content = game_board[row][col]
            current_display[row][col] = cell_content # Update what the player sees
    
            if cell_content == 'M':
                mines_hit = True
                game_over = True
                print("\nBOOM! You hit a mine. Game Over!")
            else:
                safe_cells_revealed += 1
                if safe_cells_revealed == total_safe_cells:
                    game_over = True
                    print("\nCongratulations! You've cleared all the safe cells. You Win!")
    
        # After game over, reveal the full board for review
        print("\n--- Game Board Revealed ---")
        # Temporarily copy game_board content to display to show all mines
        final_display = [['0' for _ in range(board_cols)] for _ in range(board_rows)]
        for r in range(board_rows):
            for c in range(board_cols):
                final_display[r][c] = game_board[r][c]
        print_display_board(final_display)
    
    if __name__ == "__main__":
        play_game()
    

    The Complete Simple Minesweeper Code

    Here’s the entire code for your simple Minesweeper game:

    import random
    
    def initialize_boards(rows, cols):
        """
        Creates two empty boards: one for game logic and one for display.
    
        Args:
            rows (int): The number of rows in the board.
            cols (int): The number of columns in the board.
    
        Returns:
            tuple: A tuple containing (board, display_board).
                   'board' holds '0' for empty cells initially.
                   'display_board' holds '-' for hidden cells.
        """
        board = [['0' for _ in range(cols)] for _ in range(rows)]
        display_board = [['-' for _ in range(cols)] for _ in range(rows)]
        return board, display_board
    
    def place_mines(board, num_mines):
        """
        Randomly places mines ('M') on the game board.
    
        Args:
            board (list of lists): The game board where mines will be placed.
            num_mines (int): The total number of mines to place.
        """
        rows = len(board)
        cols = len(board[0])
        mines_placed = 0
    
        while mines_placed < num_mines:
            r = random.randint(0, rows - 1) # Pick a random row
            c = random.randint(0, cols - 1) # Pick a random column
    
            if board[r][c] != 'M': # If there isn't already a mine here
                board[r][c] = 'M'
                mines_placed += 1
    
    def calculate_numbers(board):
        """
        Calculates the number of adjacent mines for each non-mine cell.
    
        Args:
            board (list of lists): The game board with mines placed.
        """
        rows = len(board)
        cols = len(board[0])
    
        for r in range(rows):
            for c in range(cols):
                if board[r][c] == 'M':
                    continue # Skip if it's a mine
    
                mine_count = 0
                # Check all 8 adjacent cells
                for dr in [-1, 0, 1]: # Delta row: -1 (up), 0 (same row), 1 (down)
                    for dc in [-1, 0, 1]: # Delta col: -1 (left), 0 (same col), 1 (right)
                        if dr == 0 and dc == 0: # Skip the current cell itself
                            continue
    
                        nr, nc = r + dr, c + dc # Neighbor row, neighbor col
    
                        # Check if the neighbor is within the board boundaries
                        if 0 <= nr < rows and 0 <= nc < cols:
                            if board[nr][nc] == 'M':
                                mine_count += 1
                board[r][c] = str(mine_count) # Store the count as a string
    
    def print_display_board(display_board):
        """
        Prints the current state of the display board to the console.
        """
        rows = len(display_board)
        cols = len(display_board[0])
    
        # Print column numbers
        print("  ", end="")
        for c in range(cols):
            print(f" {c}", end="")
        print()
    
        # Print a separator line
        print("  " + "---" * cols)
    
        # Print row numbers and board content
        for r in range(rows):
            print(f"{r} |", end="")
            for c in range(cols):
                print(f" {display_board[r][c]}", end="")
            print(" |")
        print("  " + "---" * cols)
    
    def get_player_move(rows, cols):
        """
        Prompts the player to enter their move (row and column).
    
        Args:
            rows (int): Total number of rows on the board.
            cols (int): Total number of columns on the board.
    
        Returns:
            tuple: (row, col) if input is valid, otherwise asks again.
        """
        while True:
            try:
                move_input = input(f"Enter your move (row column, e.g., 0 0): ").split()
                r, c = int(move_input[0]), int(move_input[1])
    
                if 0 <= r < rows and 0 <= c < cols:
                    return r, c
                else:
                    print("Invalid input. Row and column must be within board limits.")
            except (ValueError, IndexError):
                print("Invalid input format. Please enter two numbers separated by a space.")
    
    def play_game():
        """
        Main function to run the Minesweeper game.
        """
        print("Welcome to Simple Minesweeper!")
    
        # You can change these values to make the board bigger or smaller
        board_rows = 5
        board_cols = 5
        number_of_mines = 4 
    
        # Initialize the board and display board
        game_board, current_display = initialize_boards(board_rows, board_cols)
        place_mines(game_board, number_of_mines)
        calculate_numbers(game_board)
    
        game_over = False
        safe_cells_revealed = 0
        total_safe_cells = (board_rows * board_cols) - number_of_mines
    
        while not game_over:
            print_display_board(current_display)
    
            # Get player move
            row, col = get_player_move(board_rows, board_cols)
    
            # Check if the cell is already revealed
            if current_display[row][col] != '-':
                print("This cell is already revealed. Choose another one.")
                continue
    
            # Reveal the cell
            cell_content = game_board[row][col]
            current_display[row][col] = cell_content # Update what the player sees
    
            if cell_content == 'M':
                game_over = True
                print("\nBOOM! You hit a mine. Game Over!")
            else:
                safe_cells_revealed += 1
                if safe_cells_revealed == total_safe_cells:
                    game_over = True
                    print("\nCongratulations! You've cleared all the safe cells. You Win!")
    
        # After game over, reveal the full board for review
        print("\n--- Game Board Revealed ---")
        # Temporarily copy game_board content to display to show all mines
        final_display = [['0' for _ in range(board_cols)] for _ in range(board_rows)]
        for r in range(board_rows):
            for c in range(board_cols):
                final_display[r][c] = game_board[r][c]
        print_display_board(final_display)
    
    if __name__ == "__main__":
        play_game()
    

    How to Play Your Game

    1. Save the Code: Save the entire code block above into a file named minesweeper.py (or any name ending with .py).
    2. Open a Terminal/Command Prompt: Navigate to the directory where you saved your file.
    3. Run the Game: Type python minesweeper.py and press Enter.
    4. Enter Moves: The game will prompt you to enter a row and column number (e.g., 0 0 for the top-left corner).
    5. Try to Win!: Avoid mines and reveal all the safe cells. Good luck!

    Conclusion: You’ve Swept the Mines!

    Congratulations! You’ve successfully built a basic Minesweeper game using Python. You’ve learned about creating 2D lists, using the random module, implementing loops and conditionals, defining functions, and managing game flow.

    This is a great foundation! You can further enhance this game by adding features like:
    * Allowing players to “flag” potential mine locations.
    * Implementing the automatic revealing of empty cells and their neighbors.
    * Adding difficulty levels (changing board size and mine count).
    * Creating a graphical user interface (GUI) instead of a text-based one.

    Keep experimenting and happy coding!

  • Building a Simple Photo Gallery App with Flask

    Hello there, aspiring web developers and curious minds! Have you ever wanted to create your own little corner on the internet to display your favorite pictures? Today, we’re going to embark on a fun and beginner-friendly journey to build a simple photo gallery web application using Flask.

    Flask is a fantastic, lightweight web framework for Python. Think of a web framework as a toolkit that provides a structure and common tools to help you build websites and web applications more easily, without having to write everything from scratch. Flask is known for being “micro” because it keeps the core simple but allows you to add features as you need them. It’s perfect for learning and for smaller projects like our photo gallery!

    By the end of this guide, you’ll have a basic web app running on your computer that can display images from a folder. It’s a great stepping stone into the world of web development with Python!

    What You’ll Need

    Before we dive in, make sure you have these essentials:

    • Python: Version 3.6 or higher. If you don’t have it, you can download it from the official Python website.
    • A text editor: Like VS Code, Sublime Text, or Atom, to write your code.
    • A web browser: To view your amazing photo gallery!

    Setting Up Your Project

    First things first, let’s create a dedicated space for our project.

    1. Create a Project Folder

    Open your terminal or command prompt and create a new directory (folder) for our project.

    mkdir photo_gallery_app
    cd photo_gallery_app
    

    2. Set Up a Virtual Environment

    A virtual environment is like a clean, isolated workspace for your Python project. It ensures that the packages (libraries) you install for this project don’t interfere with other Python projects on your computer. It’s a best practice!

    python3 -m venv venv
    
    • python3 -m venv venv: This command tells Python to create a virtual environment named venv inside your photo_gallery_app folder.

    Now, activate your virtual environment:

    • On macOS/Linux:
      bash
      source venv/bin/activate
    • On Windows (Command Prompt):
      bash
      venv\Scripts\activate
    • On Windows (PowerShell):
      powershell
      .\venv\Scripts\Activate.ps1

      You’ll know it’s active when you see (venv) at the beginning of your terminal prompt.

    3. Install Flask

    With your virtual environment active, let’s install Flask:

    pip install Flask
    
    • pip: This is Python’s package installer. It’s how we download and install Python libraries like Flask.

    Building the Flask Application

    Now for the exciting part – writing some code!

    1. Create Your Main Application File (app.py)

    Inside your photo_gallery_app folder, create a new file named app.py. This will contain the core logic of our Flask application.

    import os
    from flask import Flask, render_template, url_for
    
    app = Flask(__name__)
    
    IMAGE_FOLDER = os.path.join('static', 'images')
    app.config['UPLOAD_FOLDER'] = IMAGE_FOLDER
    
    @app.route('/')
    def index():
        image_names = []
        # Check if the image folder exists, if not, create it
        if not os.path.exists(app.config['UPLOAD_FOLDER']):
            os.makedirs(app.config['UPLOAD_FOLDER'])
    
        # Loop through all files in the image folder
        for filename in os.listdir(app.config['UPLOAD_FOLDER']):
            # Only add files that look like images
            if filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')):
                image_names.append(filename)
    
        # Render the 'index.html' template and pass the list of image names to it
        return render_template('index.html', images=image_names)
    
    if __name__ == '__main__':
        # Make sure the 'static/images' folder exists before running
        os.makedirs(os.path.join('static', 'images'), exist_ok=True)
        # Run the Flask development server
        # debug=True allows for automatic reloading and helpful error messages
        app.run(debug=True)
    
    • Flask(__name__): This creates your Flask application instance. __name__ helps Flask find resources.
    • @app.route('/'): This is a decorator that associates the index() function with the URL path / (the root of your website). When someone visits this URL, the index() function will be executed.
    • os.path.join('static', 'images'): This intelligently combines path components, making sure it works correctly on different operating systems (Windows, macOS, Linux).
    • os.listdir(): This function from Python’s os module gets a list of all files and folders inside a given directory.
    • render_template('index.html', images=image_names): This is where the magic of displaying our web page happens. It tells Flask to find a file named index.html (which we’ll create next) and send it to the user’s browser. We’re also passing a list of image_names to this template, so it can use them to display pictures.

    2. Create the Templates Folder and HTML File

    Flask looks for HTML files in a special folder named templates.
    Create a new folder named templates inside your photo_gallery_app directory.
    Inside templates, create a file named index.html.

    Your project structure should now look like this:

    photo_gallery_app/
    ├── venv/
    ├── app.py
    ├── templates/
    │   └── index.html
    └── static/  (we'll create this next)
    

    Now, open templates/index.html and add the following code:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>My Simple Photo Gallery</title>
        <style>
            body {
                font-family: Arial, sans-serif;
                margin: 0;
                padding: 20px;
                background-color: #f8f8f8;
                color: #333;
            }
            h1 {
                text-align: center;
                color: #2c3e50;
                margin-bottom: 40px;
            }
            .gallery {
                display: grid; /* This helps us arrange items in a grid easily */
                grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); /* Responsive grid columns */
                gap: 25px; /* Space between grid items */
                max-width: 1200px;
                margin: 0 auto;
                padding: 20px;
            }
            .gallery-item {
                background-color: #ffffff;
                border: 1px solid #e0e0e0;
                border-radius: 10px;
                overflow: hidden; /* Ensures image corners match border-radius */
                box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
                transition: transform 0.2s ease-in-out;
            }
            .gallery-item:hover {
                transform: translateY(-5px); /* Little lift effect on hover */
                box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
            }
            .gallery-item img {
                width: 100%;
                height: 200px; /* Fixed height for consistency */
                object-fit: cover; /* Ensures images cover the area without distortion */
                display: block;
                border-bottom: 1px solid #eee;
            }
            .gallery-item p {
                padding: 15px;
                margin: 0;
                text-align: center;
                font-size: 0.95em;
                color: #555;
                word-wrap: break-word; /* Helps with long filenames */
            }
            .no-images {
                text-align: center;
                font-size: 1.2em;
                color: #777;
                margin-top: 50px;
            }
        </style>
    </head>
    <body>
        <h1>My Awesome Photo Gallery!</h1>
    
        <div class="gallery">
            <!-- This is Jinja2 templating syntax, specific to Flask templates -->
            {% if images %}
                {% for image_name in images %}
                <div class="gallery-item">
                    <!-- url_for('static', ...) generates the correct path to our image -->
                    <img src="{{ url_for('static', filename='images/' + image_name) }}" alt="{{ image_name }}">
                    <p>{{ image_name }}</p>
                </div>
                {% endfor %}
            {% else %}
                <p class="no-images">No images found yet! Add some pictures to the 'static/images' folder.</p>
            {% endif %}
        </div>
    </body>
    </html>
    
    • <!DOCTYPE html>: Standard declaration for HTML5.
    • <style> tags: This section contains simple CSS (Cascading Style Sheets) to make our gallery look a bit nicer. CSS defines how HTML elements are displayed.
    • {% for image_name in images %}: This is Jinja2 templating syntax. Jinja2 is the template engine Flask uses. It allows us to write Python-like logic directly in our HTML. Here, it loops through the images list that we passed from app.py.
    • {{ url_for('static', filename='images/' + image_name) }}: This is crucial! Flask uses the url_for function to dynamically generate URLs. For static files (like our images), we tell it to look in the static folder and then specify the filename. This ensures the path is always correct, even if your application moves.

    3. Create the Static Folder and Add Your Images

    Now we need a place for our actual pictures. Create a folder named static inside your main photo_gallery_app directory.
    Inside static, create another folder named images.

    Your final project structure should look like this:

    photo_gallery_app/
    ├── venv/
    ├── app.py
    ├── templates/
    │   └── index.html
    └── static/
        └── images/
            ├── your_photo1.jpg
            └── another_photo.png
    

    Important: Place some .jpg, .png, or .gif image files inside the static/images folder. These are the pictures your gallery will display! If you don’t have any handy, just drag and drop a few from your computer into this new folder.

    Running Your Application

    You’re all set! Now let’s see your gallery in action.

    1. Ensure your virtual environment is active. (You should see (venv) in your terminal prompt). If not, activate it again using the source or .\venv\Scripts\activate command from earlier.
    2. Navigate to your photo_gallery_app directory in the terminal.
    3. Run your Flask application:

      bash
      python app.py

    You should see output similar to this:

     * Serving Flask app 'app'
     * Debug mode: on
    WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
     * Running on http://127.0.0.1:5000
    Press CTRL+C to quit
     * Restarting with stat
     * Debugger is active!
     * Debugger PIN: XXX-XXX-XXX
    

    Open your web browser and go to http://127.0.0.1:5000. You should now see your very own photo gallery, displaying the images you placed in the static/images folder!

    Next Steps and Improvements

    Congratulations! You’ve successfully built a simple photo gallery with Flask. But this is just the beginning. Here are some ideas to expand your app:

    • Upload functionality: Allow users to upload new images directly through the web interface.
    • Delete functionality: Add buttons to delete images.
    • Image descriptions/metadata: Store and display more information about each photo.
    • Better styling: Use a CSS framework like Bootstrap to make it look even more professional.
    • Search/Filter: Add a search bar to find specific images.
    • Pagination: If you have many images, display them across multiple pages.

    Conclusion

    Building a simple photo gallery with Flask is a fantastic way to grasp fundamental web development concepts, including setting up an environment, routing, templating, and serving static files. Flask’s simplicity makes it an ideal tool for beginners to quickly get a working application up and running. I hope you enjoyed this journey and feel inspired to create more exciting projects with Python and Flask! Happy coding!

  • Web Scraping for Fun: Building a Random Quote Generator

    Welcome, budding developers and curious minds! Today, we're going to embark on a fun and educational journey into the world of **web scraping**. Don't worry if you're new to this; we'll break down every step in a way that's easy to follow. Our goal? To build a simple, yet delightful, random quote generator!
    
    ## What is Web Scraping?
    
    Before we dive into coding, let's understand what web scraping is.
    
    *   **Web Scraping:** Imagine you want to collect a lot of information from a website, like all the product prices on an online store, or in our case, a bunch of inspiring quotes. Manually copying and pasting each piece of information would be incredibly time-consuming and tedious. Web scraping is the process of using computer programs to automatically extract this data from websites. It's like having a super-fast robot assistant that can read and copy things for you.
    
    ## Why Build a Random Quote Generator?
    
    It's a fantastic way to learn:
    
    *   **Basic Python concepts:** We'll be using Python, a popular and beginner-friendly programming language.
    *   **Web scraping libraries:** You'll get hands-on experience with powerful tools that make web scraping possible.
    *   **Data handling:** We'll learn how to process the information we collect.
    *   **Project building:** It's a small, achievable project that gives you a sense of accomplishment.
    
    ## Our Tools of the Trade
    
    To build our quote generator, we'll need a few essential tools:
    
    1.  **Python:** If you don't have Python installed, you can download it from [python.org](https://www.python.org/).
    2.  **`requests` library:** This library allows us to fetch the content of a webpage. Think of it as the tool that goes to the website and brings back the raw HTML code.
    3.  **`Beautiful Soup` library:** This is our "parser." Once we have the HTML code, `Beautiful Soup` helps us navigate and extract specific pieces of information from it. It's like having a magnifying glass that can find exactly what you're looking for within the code.
    
    ### Installing Libraries
    
    If you have Python installed, you can install these libraries using `pip`, Python's package installer. Open your terminal or command prompt and type:
    
    ```bash
    pip install requests beautifulsoup4
    

    This command tells your computer to download and install the requests and beautifulsoup4 packages.

    Finding Our Quote Source

    For this project, we need a website that lists many quotes. A great source for this is quotes.toscrape.com. This website is specifically designed for practicing web scraping, so it’s a perfect starting point.

    When you visit quotes.toscrape.com in your browser, you’ll see a page filled with quotes, each with its author and tags. We want to extract the text of these quotes.

    Let’s Start Coding!

    Now for the exciting part – writing the code! We’ll go step-by-step.

    Step 1: Fetching the Webpage Content

    First, we need to get the HTML content of the quotes.toscrape.com homepage.

    import requests
    
    url = "http://quotes.toscrape.com/"
    response = requests.get(url)
    
    if response.status_code == 200:
        html_content = response.text
        print("Successfully fetched the webpage!")
    else:
        print(f"Failed to fetch webpage. Status code: {response.status_code}")
    
    • import requests: This line brings in the requests library so we can use its functions.
    • url = "http://quotes.toscrape.com/": We define the address of the website we want to scrape.
    • response = requests.get(url): This is where the requests library does its magic. It sends a request to the url and stores the website’s response in the response variable.
    • response.status_code == 200: Websites send back status codes to indicate if a request was successful. 200 means everything is fine. If you see a different number, it might mean there was an error (like a 404 for “not found”).
    • html_content = response.text: If the request was successful, response.text contains the entire HTML code of the webpage as a string of text.

    Step 2: Parsing the HTML with Beautiful Soup

    Now that we have the HTML, we need to make it easier to work with. This is where Beautiful Soup comes in.

    from bs4 import BeautifulSoup
    
    
    if response.status_code == 200:
        html_content = response.text
        soup = BeautifulSoup(html_content, 'html.parser')
        print("Successfully parsed the HTML!")
    else:
        print(f"Failed to fetch webpage. Status code: {response.status_code}")
    
    • from bs4 import BeautifulSoup: This imports the BeautifulSoup class from the bs4 library.
    • soup = BeautifulSoup(html_content, 'html.parser'): We create a BeautifulSoup object. We pass it the html_content we fetched and tell it to use 'html.parser', which is a built-in Python parser for HTML. Now, soup is an object that we can use to “look around” the HTML structure.

    Step 3: Finding the Quotes

    We need to inspect the HTML of quotes.toscrape.com to figure out how the quotes are structured. If you right-click on a quote on the website and select “Inspect” (or “Inspect Element”) in your browser, you’ll see the HTML code.

    You’ll notice that each quote is inside a div element with the class quote. Inside this div, the actual quote text is within a span element with the class text.

    Let’s use Beautiful Soup to find all these quote elements.

    if response.status_code == 200:
        html_content = response.text
        soup = BeautifulSoup(html_content, 'html.parser')
    
        # Find all div elements with the class 'quote'
        quote_elements = soup.find_all('div', class_='quote')
    
        # Extract the text from each quote element
        quotes = []
        for quote_element in quote_elements:
            text_element = quote_element.find('span', class_='text')
            if text_element:
                quotes.append(text_element.text.strip()) # .text gets the content, .strip() removes extra whitespace
    
        print(f"Found {len(quotes)} quotes!")
        # print(quotes) # Uncomment to see the list of quotes
    
    else:
        print(f"Failed to fetch webpage. Status code: {response.status_code}")
    
    • soup.find_all('div', class_='quote'): This is a powerful Beautiful Soup method. It searches the soup object for all div tags that have the attribute class set to 'quote'. It returns a list of all matching elements.
    • quote_element.find('span', class_='text'): For each quote_element we found, we now look inside it for a span tag with the class 'text'.
    • text_element.text.strip(): If we find the span, text_element.text gets the actual text content from inside that span. .strip() is a handy string method that removes any leading or trailing whitespace (like extra spaces or newlines), making our quote cleaner.
    • quotes.append(...): We add the cleaned quote text to our quotes list.

    Step 4: Displaying a Random Quote

    Now that we have a list of quotes, we can pick one randomly. Python’s random module is perfect for this.

    import requests
    from bs4 import BeautifulSoup
    import random
    
    url = "http://quotes.toscrape.com/"
    response = requests.get(url)
    
    if response.status_code == 200:
        html_content = response.text
        soup = BeautifulSoup(html_content, 'html.parser')
    
        quote_elements = soup.find_all('div', class_='quote')
    
        quotes = []
        for quote_element in quote_elements:
            text_element = quote_element.find('span', class_='text')
            if text_element:
                quotes.append(text_element.text.strip())
    
        # Check if we actually found any quotes
        if quotes:
            random_quote = random.choice(quotes)
            print("\n--- Your Random Quote ---")
            print(random_quote)
            print("-----------------------")
        else:
            print("No quotes found on the page.")
    
    else:
        print(f"Failed to fetch webpage. Status code: {response.status_code}")
    
    • import random: We import the random module.
    • random_quote = random.choice(quotes): This function randomly selects one item from the quotes list.
    • The if quotes: check ensures we don’t try to pick a random item from an empty list, which would cause an error.

    Putting It All Together

    Here’s the complete script:

    import requests
    from bs4 import BeautifulSoup
    import random
    
    def get_random_quote():
        """
        Fetches quotes from quotes.toscrape.com and returns a random one.
        """
        url = "http://quotes.toscrape.com/"
        try:
            response = requests.get(url, timeout=10) # Added a timeout for safety
            response.raise_for_status() # Raises an HTTPError for bad responses (4xx or 5xx)
    
            html_content = response.text
            soup = BeautifulSoup(html_content, 'html.parser')
    
            quote_elements = soup.find_all('div', class_='quote')
    
            quotes = []
            for quote_element in quote_elements:
                text_element = quote_element.find('span', class_='text')
                if text_element:
                    quotes.append(text_element.text.strip())
    
            if quotes:
                return random.choice(quotes)
            else:
                return "Could not find any quotes on the page."
    
        except requests.exceptions.RequestException as e:
            return f"An error occurred while fetching the webpage: {e}"
        except Exception as e:
            return f"An unexpected error occurred: {e}"
    
    if __name__ == "__main__":
        quote = get_random_quote()
        print("\n--- Your Random Quote ---")
        print(quote)
        print("-----------------------")
    
    • def get_random_quote():: We’ve wrapped our logic in a function. This makes our code more organized and reusable.
    • try...except block: This is a way to handle potential errors. If something goes wrong (like the website being down, or a network issue), the program won’t crash but will instead print a helpful error message.
    • response.raise_for_status(): This is a convenient way to check if the HTTP request was successful. If it wasn’t (e.g., a 404 Not Found error), it will raise an exception, which our except block will catch.
    • timeout=10: This tells requests to wait a maximum of 10 seconds for a response from the server. This prevents your program from hanging indefinitely if the server is slow or unresponsive.
    • if __name__ == "__main__":: This is a standard Python construct. It means the code inside this block will only run when the script is executed directly (not when it’s imported as a module into another script).

    What’s Next?

    This is just the beginning! You can expand on this project by:

    • Scraping multiple pages of quotes.
    • Extracting the author and tags along with the quote.
    • Saving the quotes to a file.
    • Building a simple web application to display the quotes.

    Web scraping is a powerful skill that can be used for many purposes, from data analysis to automating tasks. Have fun experimenting!

  • Let’s Gobble! Create a Simple Pac-Man Game with Python (Beginner-Friendly)

    Have you ever wanted to build your own video game? It might sound complicated, but with Python, one of the most popular and beginner-friendly programming languages, it’s totally achievable! Today, we’re going to dive into creating a very simple version of the classic arcade game, Pac-Man. Don’t worry if you’re new to programming; we’ll break down every step using clear, simple language.

    This project is a fantastic way to learn some fundamental game development concepts like creating game objects, handling user input, detecting collisions, and keeping score. We’ll use a special Python module called turtle for our graphics, which is perfect for getting started with visual programming.

    Why Python and the Turtle Module?

    Python is a fantastic language for beginners because its syntax (the rules for writing code) is very readable, almost like plain English. This makes it easier to understand what your code is doing.

    The turtle module is a built-in Python library that lets you create simple graphics and animations. Think of it like drawing with a robot turtle on a canvas. You tell the turtle to move forward, turn, lift its pen, or put its pen down, and it draws on the screen. It’s an excellent tool for visualizing how programming commands translate into actions on a screen, making it ideal for our simple Pac-Man game.

    • Python: A versatile (meaning it can do many different things) and easy-to-read programming language.
    • Turtle Module: A Python library for creating graphics by issuing commands to a virtual “turtle” that draws on a screen.

    What Will Our Simple Pac-Man Game Do?

    Our version of Pac-Man will be quite basic, focusing on the core elements:
    * A player-controlled Pac-Man.
    * Multiple food pellets (dots) for Pac-Man to eat.
    * Pac-Man moving around the screen using keyboard controls.
    * A scoring system that increases when Pac-Man eats food.
    * Food pellets disappearing when eaten.

    We won’t be adding ghosts or complex mazes in this beginner-friendly version, as that would add too much complexity for our first game. But once you understand these basics, you’ll be well-equipped to add more features!

    Setting Up Your Development Environment

    Before we start coding, you’ll need Python installed on your computer. If you don’t have it, you can download it from the official Python website (python.org). Most operating systems come with a basic text editor, but a more advanced one like Visual Studio Code (VS Code) or PyCharm can make coding easier. For running our simple game, a basic text editor and command prompt will work perfectly.

    Step-by-Step Game Creation

    Let’s build our game piece by piece.

    1. Initialize the Game Window

    First, we need to set up the game window where everything will appear.

    import turtle
    import math # We'll use this later for distance calculations
    
    wn = turtle.Screen() # This creates our game window
    wn.setup(width=600, height=600) # Sets the size of the window
    wn.bgcolor("black") # Sets the background color to black
    wn.title("Simple Pac-Man") # Gives our window a title
    wn.tracer(0) # This turns off screen updates, we'll update manually for smoother animation
    
    • import turtle: This line brings in the turtle module so we can use its functions.
    • wn = turtle.Screen(): We create an object called wn (short for window) which represents our game screen.
    • wn.setup(width=600, height=600): This makes our game window 600 pixels wide and 600 pixels tall. A pixel is a tiny dot on your screen.
    • wn.bgcolor("black"): Sets the background color of our game window.
    • wn.title("Simple Pac-Man"): Puts “Simple Pac-Man” in the title bar of the window.
    • wn.tracer(0): This is a very important line for game animation. By default, turtle updates the screen every time something moves. This can make animations look choppy. wn.tracer(0) tells turtle to not update automatically. We’ll manually update the screen later using wn.update() to make movements smoother.

    2. Create the Player (Pac-Man)

    Now, let’s create our Pac-Man character. We’ll use another turtle object for this.

    player = turtle.Turtle() # Creates a new turtle object for our player
    player.shape("circle") # Makes the player look like a circle
    player.color("yellow") # Sets Pac-Man's color
    player.penup() # Lifts the "pen" so it doesn't draw lines when moving
    player.goto(0, 0) # Sets Pac-Man's starting position at the center of the screen
    player.direction = "stop" # A variable to keep track of Pac-Man's current movement direction
    
    • player = turtle.Turtle(): We create an object named player that is a turtle.
    • player.shape("circle"): We change the default arrow shape of the turtle to a circle.
    • player.color("yellow"): Our Pac-Man will be yellow!
    • player.penup(): When a turtle moves, it usually draws a line. penup() lifts its “pen” so it moves without drawing. pendown() would put the pen back down.
    • player.goto(0, 0): In turtle graphics, the center of the screen is (0, 0). X-coordinates go left-right, Y-coordinates go up-down.
    • player.direction = "stop": We create a custom variable direction for our player turtle to store which way it’s supposed to move. Initially, it’s “stop”.

    3. Create the Food Pellets

    We need some food for Pac-Man to eat! We’ll create a list of turtle objects for our food.

    foods = []
    
    food_positions = [
        (-200, 200), (-150, 200), (-100, 200), (-50, 200), (0, 200), (50, 200), (100, 200), (150, 200), (200, 200),
        (-200, 150), (-100, 150), (0, 150), (100, 150), (200, 150),
        (-200, 100), (-150, 100), (-50, 100), (50, 100), (150, 100), (200, 100),
        (-200, 0), (-100, 0), (0, 0), (100, 0), (200, 0), # Note: (0,0) is player start, we'll remove it later
        (-200, -100), (-150, -100), (-50, -100), (50, -100), (150, -100), (200, -100),
        (-200, -150), (-100, -150), (0, -150), (100, -150), (200, -150),
        (-200, -200), (-150, -200), (-100, -200), (-50, -200), (0, -200), (50, -200), (100, -200), (150, -200), (200, -200)
    ]
    
    for pos in food_positions:
        food = turtle.Turtle()
        food.shape("circle")
        food.color("white")
        food.shapesize(0.5) # Makes the food circles smaller
        food.penup()
        food.goto(pos)
        foods.append(food) # Add each food pellet to our 'foods' list
    
    for food in foods:
        if food.distance(player) < 1: # If food is very close to the player
            food.hideturtle() # Make it invisible
            foods.remove(food) # Remove it from our list
            break # Exit the loop once found and removed
    
    • foods = []: This creates an empty list. A list is like a container that can hold multiple items. We’ll store all our food turtle objects here.
    • food_positions = [...]: We define a list of (x, y) coordinates where our food pellets will appear.
    • for pos in food_positions:: This is a for loop, which means it will repeat the code inside it for each item in food_positions. For each pos (position):
      • We create a new food turtle.
      • Set its shape to “circle”, color to “white”, and make it smaller with shapesize(0.5).
      • Move it to the current pos.
      • foods.append(food): We add this newly created food turtle to our foods list.
    • food.distance(player) < 1: The distance() method calculates the distance between two turtles. If it’s less than 1, they are essentially at the same spot.
    • food.hideturtle(): Makes the food turtle invisible.
    • foods.remove(food): Deletes the food turtle from our foods list.

    4. Implement Player Movement

    We need functions to tell Pac-Man which way to go when the user presses a key.

    def go_up():
        player.direction = "up"
    
    def go_down():
        player.direction = "down"
    
    def go_left():
        player.direction = "left"
    
    def go_right():
        player.direction = "right"
    
    wn.listen() # Tells the window to listen for keyboard input
    wn.onkeypress(go_up, "w") # When 'w' is pressed, call go_up()
    wn.onkeypress(go_down, "s") # When 's' is pressed, call go_down()
    wn.onkeypress(go_left, "a") # When 'a' is pressed, call go_left()
    wn.onkeypress(go_right, "d") # When 'd' is pressed, call go_right()
    
    wn.onkeypress(go_up, "Up")
    wn.onkeypress(go_down, "Down")
    wn.onkeypress(go_left, "Left")
    wn.onkeypress(go_right, "Right")
    
    • go_up(), go_down(), etc.: These are simple functions that just update our player.direction variable. Pac-Man won’t move immediately when a key is pressed; instead, we’ll check this direction variable inside our main game loop to move him consistently.
    • wn.listen(): This line is crucial; it tells the game window to start listening for keyboard presses.
    • wn.onkeypress(function, key): This connects a key press to a function. For example, when the ‘w’ key is pressed, the go_up() function will be called.

    5. Display the Score

    We need a way to show the player’s score. We’ll use another turtle for this, but this turtle will only write text.

    score = 0
    
    score_display = turtle.Turtle()
    score_display.speed(0) # Fastest animation speed
    score_display.color("white")
    score_display.penup()
    score_display.hideturtle() # We don't want to see the turtle itself, just its writing
    score_display.goto(0, 260) # Position it near the top of the screen
    score_display.write("Score: 0", align="center", font=("Courier", 24, "normal")) # Display initial score
    
    • score = 0: Initializes our score variable.
    • score_display = turtle.Turtle(): Creates a turtle for displaying text.
    • score_display.hideturtle(): We don’t want to see the turtle drawing the score, just the score text itself.
    • score_display.goto(0, 260): Moves the turtle to the top of the screen.
    • score_display.write(...): This command makes the turtle write text.
      • "Score: 0": The actual text to display.
      • align="center": Centers the text.
      • font=("Courier", 24, "normal"): Sets the font style, size, and weight.

    6. The Main Game Loop

    This is the heart of our game. The game loop runs continuously, updating everything on the screen and checking for actions.

    while True: # This loop will run forever until the program is closed
        wn.update() # Manually update the screen (because we used wn.tracer(0))
    
        # Move the player
        if player.direction == "up":
            y = player.ycor() # Get current Y coordinate
            player.sety(y + 2) # Move up by 2 pixels
        if player.direction == "down":
            y = player.ycor()
            player.sety(y - 2)
        if player.direction == "left":
            x = player.xcor() # Get current X coordinate
            player.setx(x - 2) # Move left by 2 pixels
        if player.direction == "right":
            x = player.xcor()
            player.setx(x + 2)
    
        # Wrap around the edges (simple boundary)
        if player.xcor() > 290: # If Pac-Man goes too far right
            player.setx(-290) # Warp to the left side
        if player.xcor() < -290: # If Pac-Man goes too far left
            player.setx(290) # Warp to the right side
        if player.ycor() > 290: # If Pac-Man goes too far up
            player.sety(-290) # Warp to the bottom side
        if player.ycor() < -290: # If Pac-Man goes too far down
            player.sety(290) # Warp to the top side
    
        # Check for collision with food
        # We iterate backwards through the list to safely remove items
        for i in range(len(foods) - 1, -1, -1):
            food = foods[i]
            if player.distance(food) < 15: # If Pac-Man is close enough to the food (adjust 15 as needed)
                food.hideturtle() # Make the food disappear
                foods.pop(i) # Remove the food from the list
                score += 10 # Increase the score
                score_display.clear() # Clear the old score text
                score_display.write(f"Score: {score}", align="center", font=("Courier", 24, "normal")) # Write the new score
    
        # Check for game over (all food eaten)
        if not foods: # If the 'foods' list is empty
            score_display.clear()
            score_display.goto(0, 0) # Move score display to center
            score_display.write(f"GAME OVER! Your Score: {score}", align="center", font=("Courier", 30, "bold"))
            player.hideturtle() # Hide Pac-Man
            wn.update() # Update one last time
            break # Exit the game loop
    
    • while True:: This creates an infinite loop. The code inside will run again and again until the program is closed or a break statement is encountered.
    • wn.update(): This is where we manually refresh the screen. Because wn.tracer(0) is on, all movements and changes only become visible after wn.update() is called.
    • player.ycor() / player.xcor(): These functions get the current Y (vertical) or X (horizontal) coordinate of the player turtle.
    • player.sety(y + 2) / player.setx(x - 2): These functions set the new Y or X coordinate. We add or subtract 2 to move Pac-Man in the desired direction. This ‘2’ represents his speed.
    • Wrap around edges: These if statements check if Pac-Man has gone off one side of the screen and, if so, goto() the opposite side. This creates a classic Pac-Man “wrap-around” effect.
    • for i in range(len(foods) - 1, -1, -1):: This loop goes through the foods list backwards. This is a common and safe practice when you might be removing items from a list while you’re looping through it. If you iterate forwards and remove an item, the list shortens and the indices (positions of items) shift, which can lead to errors.
    • player.distance(food) < 15: This checks if Pac-Man is close enough to a food pellet to “eat” it. The number 15 is a radius; you can adjust it if you want Pac-Man to have to be closer or further away to eat food.
    • foods.pop(i): This removes the food item at index i from the foods list.
    • score_display.clear(): Before writing a new score, we clear the old one so it doesn’t overlap.
    • if not foods:: This checks if the foods list is empty. If it is, it means Pac-Man has eaten all the food, and the game ends!

    Putting It All Together (Complete Code)

    Here’s the complete code for your simple Pac-Man game. You can copy and paste this into a Python file (e.g., pacman_simple.py) and run it.

    import turtle
    import math
    
    wn = turtle.Screen()
    wn.setup(width=600, height=600)
    wn.bgcolor("black")
    wn.title("Simple Pac-Man")
    wn.tracer(0) # Turn off screen updates for smoother animation
    
    player = turtle.Turtle()
    player.shape("circle")
    player.color("yellow")
    player.penup()
    player.goto(0, 0)
    player.direction = "stop" # Initial direction
    
    foods = []
    food_positions = [
        (-200, 200), (-150, 200), (-100, 200), (-50, 200), (0, 200), (50, 200), (100, 200), (150, 200), (200, 200),
        (-200, 150), (-100, 150), (0, 150), (100, 150), (200, 150),
        (-200, 100), (-150, 100), (-50, 100), (50, 100), (150, 100), (200, 100),
        (-200, 0), (-100, 0), (100, 0), (200, 0), # (0,0) excluded here to avoid overlap with player start
        (-200, -100), (-150, -100), (-50, -100), (50, -100), (150, -100), (200, -100),
        (-200, -150), (-100, -150), (0, -150), (100, -150), (200, -150),
        (-200, -200), (-150, -200), (-100, -200), (-50, -200), (0, -200), (50, -200), (100, -200), (150, -200), (200, -200)
    ]
    
    for pos in food_positions:
        food = turtle.Turtle()
        food.shape("circle")
        food.color("white")
        food.shapesize(0.5)
        food.penup()
        food.goto(pos)
        foods.append(food)
    
    def go_up():
        player.direction = "up"
    def go_down():
        player.direction = "down"
    def go_left():
        player.direction = "left"
    def go_right():
        player.direction = "right"
    
    wn.listen()
    wn.onkeypress(go_up, "w")
    wn.onkeypress(go_down, "s")
    wn.onkeypress(go_left, "a")
    wn.onkeypress(go_right, "d")
    wn.onkeypress(go_up, "Up")
    wn.onkeypress(go_down, "Down")
    wn.onkeypress(go_left, "Left")
    wn.onkeypress(go_right, "Right")
    
    score = 0
    score_display = turtle.Turtle()
    score_display.speed(0)
    score_display.color("white")
    score_display.penup()
    score_display.hideturtle()
    score_display.goto(0, 260)
    score_display.write("Score: 0", align="center", font=("Courier", 24, "normal"))
    
    while True:
        wn.update() # Manually update the screen
    
        # Move the player
        if player.direction == "up":
            y = player.ycor()
            player.sety(y + 2)
        elif player.direction == "down": # Use elif to ensure only one direction is processed
            y = player.ycor()
            player.sety(y - 2)
        elif player.direction == "left":
            x = player.xcor()
            player.setx(x - 2)
        elif player.direction == "right":
            x = player.xcor()
            player.setx(x + 2)
    
        # Wrap around the edges
        if player.xcor() > 290:
            player.setx(-290)
        elif player.xcor() < -290:
            player.setx(290)
        elif player.ycor() > 290:
            player.sety(-290)
        elif player.ycor() < -290:
            player.sety(290)
    
        # Check for collision with food
        for i in range(len(foods) - 1, -1, -1): # Loop backwards
            food = foods[i]
            if player.distance(food) < 15: # Collision distance
                food.hideturtle()
                foods.pop(i)
                score += 10
                score_display.clear()
                score_display.write(f"Score: {score}", align="center", font=("Courier", 24, "normal"))
    
        # Check for game over (all food eaten)
        if not foods:
            score_display.clear()
            score_display.goto(0, 0)
            score_display.write(f"GAME OVER! Your Score: {score}", align="center", font=("Courier", 30, "bold"))
            player.hideturtle()
            wn.update()
            break # Exit the game loop
    

    How to Run Your Game

    1. Save: Save the code above into a file named pacman_simple.py (or any name ending with .py).
    2. Open Terminal/Command Prompt: Navigate to the folder where you saved your file using your terminal or command prompt.
    3. Run: Type python pacman_simple.py and press Enter.

    A new window should pop up, showing your black game screen, a yellow Pac-Man, and white food pellets. Use the ‘W’, ‘A’, ‘S’, ‘D’ keys or the arrow keys to move Pac-Man and start gobbling up those pellets!

    Next Steps and Improvements

    Congratulations! You’ve just created your very own simple game in Python. This is just the beginning. Here are some ideas to expand your game:

    • Add Walls/Maze: You could create simple “walls” using more turtle objects or by drawing lines and preventing Pac-Man from passing through them.
    • Introduce Ghosts: This is a big step, but you could create other turtle objects (ghosts) that move independently and end the game if they touch Pac-Man.
    • Different Food Types: Add larger pellets that give more points or special power-ups.
    • Levels: Once all food is eaten, reset the game with more food or a different layout.
    • Sounds: Python has modules (like winsound on Windows or pygame.mixer) to play sound effects when food is eaten or the game ends.

    Conclusion

    Building games is a fantastic way to learn programming. The turtle module in Python provides an intuitive and visual way to understand core programming concepts without getting bogged down in complex graphics libraries. You’ve taken your first steps into game development, and hopefully, you’ve seen how a few lines of code can bring an idea to life. Keep experimenting, keep coding, and most importantly, have fun!


  • Building Your First Quiz App with Flask: A Beginner’s Guide

    Hello aspiring web developers! Have you ever wanted to build your own interactive web application? Something fun, like a quiz? Well, you’re in luck! Today, we’re going to dive into the exciting world of web development using Flask, a super lightweight and beginner-friendly framework for Python.

    By the end of this guide, you’ll have a fully functional (albeit simple) quiz application running right on your computer. We’ll cover everything from setting up your development environment to writing the Python code and creating the HTML pages. Don’t worry if you’re new to Flask or even web development; I’ll explain things in simple terms.

    1. Getting Started: Setting Up Your Workspace

    Before we write any code, we need to prepare our computer. Think of it like gathering your tools before starting a project.

    1.1 What You’ll Need

    • Python: Make sure you have Python installed on your system (version 3.7 or newer is recommended). You can download it from the official Python website.
    • A Text Editor: Any text editor will do, but I recommend Visual Studio Code, Sublime Text, or Atom for a better experience.

    1.2 Creating a Virtual Environment

    This is a crucial step! A virtual environment is like a segregated container for your project’s dependencies (the libraries and tools your project needs). It keeps your project’s specific Flask version and other packages separate from other Python projects you might have, preventing conflicts.

    Let’s create one:

    1. Open your terminal or command prompt.
    2. Navigate to where you want to store your project. For example:
      bash
      cd Documents
      mkdir my-quiz-app
      cd my-quiz-app
    3. Create the virtual environment:
      bash
      python -m venv venv

      • python -m venv: This command tells Python to run the venv module.
      • venv: This is the name of the directory where your virtual environment will be created. You can name it anything, but venv is a common convention.
    4. Activate the virtual environment:

      • On Windows:
        bash
        .\venv\Scripts\activate
      • On macOS/Linux:
        bash
        source venv/bin/activate

        You’ll know it’s active when you see (venv) at the beginning of your terminal prompt.

    1.3 Installing Flask

    With your virtual environment active, you can now install Flask safely.

    pip install Flask
    
    • pip: This is Python’s package installer, used to install libraries.
    • install Flask: This tells pip to download and install the Flask framework.

    2. Understanding the Basics of Flask (A Quick Refresher)

    Flask is a micro web framework for Python. This means it provides the essential tools to build web applications without forcing you into a rigid structure.

    Here are a few core concepts we’ll use:

    • Flask object: This is the main application object. It’s the heart of your Flask app.
    • @app.route(): This is a decorator. Think of it as a special label you put above a Python function. It tells Flask which URL (web address) should trigger that function. For example, @app.route('/') means the function below it will run when someone visits the homepage of your app.
    • render_template(): Web applications often use templates (HTML files) to display dynamic content. This function helps Flask find and show those HTML files to the user.
    • request object: When a user interacts with your website (like clicking a button or submitting a form), their browser sends data to your server. The request object holds all this incoming information, which we can then process.
    • HTTP Methods (GET and POST): These are common ways a browser communicates with a server.
      • GET: Used to request data (like asking for a web page).
      • POST: Used to send data to the server (like submitting a form with your quiz answers).

    3. Structuring Your Quiz Data

    Before we build the app, let’s think about our quiz questions. We’ll store them in a simple Python list of dictionaries. Each dictionary will represent one question and contain its text, possible options, and the correct answer.

    In your my-quiz-app directory, create a new file named app.py. This will be the main file for our Flask application.

    quiz_data = [
        {
            "question": "What is the capital of France?",
            "options": ["Berlin", "Madrid", "Paris", "Rome"],
            "answer": "Paris"
        },
        {
            "question": "Which planet is known as the Red Planet?",
            "options": ["Earth", "Mars", "Jupiter", "Venus"],
            "answer": "Mars"
        },
        {
            "question": "What is the largest ocean on Earth?",
            "options": ["Atlantic", "Indian", "Arctic", "Pacific"],
            "answer": "Pacific"
        },
        {
            "question": "Who painted the Mona Lisa?",
            "options": ["Vincent van Gogh", "Pablo Picasso", "Leonardo da Vinci", "Claude Monet"],
            "answer": "Leonardo da Vinci"
        }
    ]
    

    4. Crafting Your Flask Application (app.py)

    Now, let’s add the core Flask logic to app.py.

    from flask import Flask, render_template, request
    
    app = Flask(__name__) # Initialize the Flask application
    
    
    @app.route('/')
    def index():
        # This function runs when someone visits the root URL (e.g., http://127.0.0.1:5000/)
        return render_template('index.html')
    
    @app.route('/quiz', methods=['GET', 'POST'])
    def quiz():
        if request.method == 'POST':
            # This block runs when the user submits their answers (POST request)
            score = 0
            user_answers = {}
            # Loop through each question in our quiz data to check answers
            for i, q in enumerate(quiz_data):
                question_key = f'q{i}' # e.g., 'q0', 'q1'
                selected_option = request.form.get(question_key) # Get user's selection for this question
                user_answers[q['question']] = selected_option # Store user's answer
    
                if selected_option == q['answer']:
                    score += 1 # Increment score if correct
    
            # After checking all answers, render the results page
            return render_template('results.html', score=score, total_questions=len(quiz_data))
        else:
            # This block runs when the user first visits /quiz (GET request)
            # It displays all the questions for the user to answer
            return render_template('quiz.html', questions=quiz_data)
    
    if __name__ == '__main__':
        # This block ensures the server runs only when the script is executed directly
        # debug=True: This enables debug mode. It will automatically restart the server
        # when you make changes and show helpful error messages in the browser.
        app.run(debug=True)
    

    5. Designing Your HTML Templates (templates/)

    Flask looks for HTML files in a special folder called templates. Create a new directory named templates inside your my-quiz-app directory.

    Inside the templates folder, create three HTML files: index.html, quiz.html, and results.html.

    5.1 templates/index.html

    This is our simple starting page.

    <!-- templates/index.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Welcome to the Quiz App!</title>
        <style>
            body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; background-color: #f4f4f4; }
            .container { background-color: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); display: inline-block; }
            button { padding: 10px 20px; font-size: 18px; cursor: pointer; background-color: #007bff; color: white; border: none; border-radius: 5px; }
            button:hover { background-color: #0056b3; }
        </style>
    </head>
    <body>
        <div class="container">
            <h1>Welcome to Our Awesome Quiz!</h1>
            <p>Test your knowledge with some fun questions.</p>
            <a href="/quiz"><button>Start Quiz</button></a>
        </div>
    </body>
    </html>
    

    5.2 templates/quiz.html

    This page will display all the questions and options using a form.

    <!-- templates/quiz.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Take the Quiz!</title>
        <style>
            body { font-family: Arial, sans-serif; margin: 20px; background-color: #f4f4f4; }
            .quiz-container { background-color: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); max-width: 800px; margin: 20px auto; }
            h1 { text-align: center; color: #333; }
            .question { margin-bottom: 20px; border-bottom: 1px solid #eee; padding-bottom: 15px; }
            .question:last-child { border-bottom: none; }
            p { font-weight: bold; margin-bottom: 10px; color: #555; }
            .options label { display: block; margin-bottom: 8px; cursor: pointer; }
            .options input[type="radio"] { margin-right: 10px; }
            button { display: block; width: 100%; padding: 12px; font-size: 18px; cursor: pointer; background-color: #28a745; color: white; border: none; border-radius: 5px; margin-top: 20px; }
            button:hover { background-color: #218838; }
        </style>
    </head>
    <body>
        <div class="quiz-container">
            <h1>Quiz Time!</h1>
            <form action="/quiz" method="post">
                {% for question in questions %}
                <div class="question">
                    <p>{{ loop.index }}. {{ question.question }}</p>
                    <div class="options">
                        {% for option in question.options %}
                            <label>
                                <input type="radio" name="q{{ loop.parent.loop.index - 1 }}" value="{{ option }}" required>
                                {{ option }}
                            </label>
                        {% endfor %}
                    </div>
                </div>
                {% endfor %}
                <button type="submit">Submit Answers</button>
            </form>
        </div>
    </body>
    </html>
    
    • {% for ... in ... %}: This is Jinja2 syntax, Flask’s default templating engine. It allows us to loop through Python data (like our questions list) directly in the HTML.
    • {{ variable }}: This is how we display the value of a Python variable (e.g., question.question) in our HTML.
    • name="q{{ loop.parent.loop.index - 1 }}": This creates unique names for each radio button group (q0, q1, etc.). This is crucial because when the form is submitted, Flask uses these name attributes to identify which option was selected for each question. loop.parent.loop.index gets the current question’s index.

    5.3 templates/results.html

    This page will show the user’s score after they submit the quiz.

    <!-- templates/results.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Quiz Results</title>
        <style>
            body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; background-color: #f4f4f4; }
            .results-container { background-color: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); display: inline-block; }
            h1 { color: #333; }
            p { font-size: 20px; color: #555; }
            .score { font-size: 3em; font-weight: bold; color: #007bff; margin: 20px 0; }
            a { text-decoration: none; }
            button { padding: 10px 20px; font-size: 18px; cursor: pointer; background-color: #007bff; color: white; border: none; border-radius: 5px; }
            button:hover { background-color: #0056b3; }
        </style>
    </head>
    <body>
        <div class="results-container">
            <h1>Quiz Complete!</h1>
            <p>You scored:</p>
            <div class="score">{{ score }} / {{ total_questions }}</div>
            <a href="/"><button>Play Again</button></a>
        </div>
    </body>
    </html>
    

    6. Running Your Quiz App

    You’ve done all the hard work! Now, let’s see your creation in action.

    1. Make sure your virtual environment is still active. (You should see (venv) in your terminal prompt). If not, activate it again (refer to section 1.2).
    2. Open your terminal in the my-quiz-app directory (where app.py is located).
    3. Run your Flask application:
      bash
      python app.py

      You should see output similar to this:
      “`

      • Serving Flask app ‘app’
      • Debug mode: on
        WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
      • Running on http://127.0.0.1:5000
        Press CTRL+C to quit
      • Restarting with stat
      • Debugger is active!
      • Debugger PIN: XXX-XXX-XXX
        “`
    4. Open your web browser and go to http://127.0.0.1:5000/.

    Voilà! You should see your “Welcome to Our Awesome Quiz!” page. Click “Start Quiz,” answer the questions, submit, and see your score!

    To stop the server, go back to your terminal and press CTRL+C (or Cmd+C on macOS).

    7. What’s Next? Ideas for Improvement

    This is a very basic quiz app, but it’s a fantastic starting point! Here are some ideas to enhance it:

    • One Question at a Time: Instead of showing all questions at once, modify the quiz() route to display one question, process the answer, and then show the next. This would involve using Flask’s session object to keep track of the user’s progress.
    • Add CSS Styling: Make it look even better! Link a separate CSS file to your HTML templates.
    • Feedback for Correct/Incorrect Answers: On the results page, show which questions were answered correctly and which were not.
    • Different Question Types: Implement true/false questions, or questions with text input.
    • Store Results: Use a database (like SQLite with Flask-SQLAlchemy) to store quiz scores or even user data.
    • Timer: Add a timer to the quiz!

    Conclusion

    Congratulations! You’ve just built your very first simple quiz application using Flask. You’ve learned how to set up a Python project with a virtual environment, understand basic Flask routing and templating, handle web forms, and display dynamic content. This is a solid foundation for building more complex web applications in the future. Keep experimenting and building!

  • Jump, Run, and Code! Build Your First Platformer Game with Python and Pygame

    Hello there, fellow adventurers and aspiring game developers! Have you ever dreamed of creating your own video game, even if it’s just a simple one? Well, today is your lucky day! We’re going to embark on an exciting journey to build a basic platformer game using Python and a fantastic library called Pygame.

    Platformer games are a classic genre where you control a character who runs, jumps, and sometimes climbs across different platforms to reach a goal. Think Super Mario Bros. or Celeste! They’re not only incredibly fun to play but also a great starting point for learning game development because they introduce fundamental concepts like player movement, gravity, and collision detection.

    By the end of this guide, you’ll have a simple but functional game where you can control a little rectangle (our hero!) that can jump and move across a basic ground platform. Ready to bring your ideas to life? Let’s dive in!

    What You’ll Need

    Before we start coding, we need to make sure you have the right tools. Don’t worry, it’s pretty straightforward!

    • Python: You’ll need Python installed on your computer. We recommend Python 3. If you don’t have it, you can download it from the official Python website: python.org.
    • Pygame: This is a powerful library that makes game development with Python much easier. It handles things like graphics, sounds, and user input.

    Installing Pygame

    Once Python is installed, opening your computer’s terminal or command prompt and running a single command will install Pygame.

    pip install pygame
    
    • pip (Package Installer for Python): This is Python’s standard package manager, used to install and manage software packages (libraries) written in Python.

    If the installation is successful, you’re all set!

    Game Basics: The Window and Game Loop

    Every game needs a window to display its visuals and a “game loop” that continuously runs to update the game world and handle player actions.

    Setting up Pygame and the Display

    First, we’ll initialize Pygame and create our game window.

    import pygame
    import sys
    
    pygame.init()
    
    SCREEN_WIDTH = 800
    SCREEN_HEIGHT = 600
    SCREEN = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    
    pygame.display.set_caption("My Simple Platformer")
    
    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)
    RED = (255, 0, 0)
    BLUE = (0, 0, 255)
    GREEN = (0, 255, 0)
    

    The Heart of the Game: The Game Loop

    The game loop is an endless cycle where the game checks for inputs (like keyboard presses), updates game elements (like player position), and then draws everything on the screen.

    running = True
    while running:
        # 1. Event Handling: Check for user input (keyboard, mouse, closing window)
        for event in pygame.event.get():
            if event.type == pygame.QUIT: # If the user clicks the 'X' to close the window
                running = False # Stop the game loop
        # Technical Term: Event Handling - This is how our game listens for and responds to anything that happens, like a key press or mouse click.
        # Technical Term: pygame.QUIT - This is a specific event that occurs when the user tries to close the game window.
    
        # 2. Update game state (we'll add player movement here later)
    
        # 3. Drawing: Clear the screen and draw game objects
        SCREEN.fill(BLUE) # Fill the background with blue (our sky)
    
        # (We'll draw our player and ground here soon!)
    
        # 4. Update the display to show what we've drawn
        pygame.display.flip()
        # Technical Term: pygame.display.flip() - This updates the entire screen to show everything that has been drawn since the last update.
    
    pygame.quit()
    sys.exit()
    

    If you run this code now, you’ll see a blue window pop up and stay there until you close it. That’s our basic game structure!

    Our Player: A Simple Rectangle

    Let’s give our game a hero! For simplicity, our player will be a red rectangle. We’ll define its size, position, and properties needed for movement.

    player_width = 30
    player_height = 50
    player_x = SCREEN_WIDTH // 2 - player_width // 2 # Start in the middle
    player_y = SCREEN_HEIGHT - player_height - 50 # Start a bit above the bottom
    player_velocity_x = 0 # Horizontal speed
    player_velocity_y = 0 # Vertical speed (for jumping and gravity)
    player_speed = 5
    jump_power = -15 # Negative because y-axis increases downwards
    gravity = 0.8
    is_grounded = False # To check if the player is on a surface
    

    Now, let’s add code to draw our player inside the game loop, right before pygame.display.flip().

    player_rect = pygame.Rect(player_x, player_y, player_width, player_height)
    pygame.draw.rect(SCREEN, RED, player_rect)
    

    Bringing in Gravity and Jumping

    Gravity is what makes things fall! We’ll apply it to our player, and then allow the player to defy gravity with a jump.

    Implementing Gravity

    Gravity will constantly pull our player downwards by increasing player_velocity_y.

    player_velocity_y += gravity
    player_y += player_velocity_y
    

    If you run this now, our red rectangle will fall off the screen! We need a ground to land on.

    Making a Ground

    Let’s create a green rectangle at the bottom of the screen to serve as our ground.

    ground_height = 20
    ground_x = 0
    ground_y = SCREEN_HEIGHT - ground_height
    ground_width = SCREEN_WIDTH
    
    ground_rect = pygame.Rect(ground_x, ground_y, ground_width, ground_height)
    
    pygame.draw.rect(SCREEN, GREEN, ground_rect)
    

    Collision Detection: Player and Ground

    Our player currently falls through the ground. We need to detect when the player’s rectangle hits the ground’s rectangle and stop its vertical movement.

    if player_rect.colliderect(ground_rect):
        player_y = ground_y - player_height # Place player on top of ground
        player_velocity_y = 0 # Stop vertical movement
        is_grounded = True # Player is now on the ground
    else:
        is_grounded = False # Player is in the air
    

    Now your player should fall and stop on the green ground!

    Adding the Jump

    We’ll make the player jump when the spacebar is pressed, but only if they are is_grounded.

    if event.type == pygame.KEYDOWN: # If a key is pressed down
        if event.key == pygame.K_SPACE and is_grounded: # If it's the spacebar and player is on ground
            player_velocity_y = jump_power # Apply upward velocity for jump
            is_grounded = False # Player is no longer grounded
    

    Try it out! Your player can now jump!

    Horizontal Movement

    What’s a platformer without being able to move left and right? We’ll use the left and right arrow keys.

    Pygame has a convenient function, pygame.key.get_pressed(), which tells us which keys are currently held down. This is great for continuous movement.

    keys = pygame.key.get_pressed()
    
    player_velocity_x = 0 # Reset horizontal velocity each frame
    if keys[pygame.K_LEFT]:
        player_velocity_x = -player_speed
    if keys[pygame.K_RIGHT]:
        player_velocity_x = player_speed
    
    player_x += player_velocity_x
    

    Now, combine everything, and you’ve got a basic platformer!

    Putting It All Together: The Complete Code

    Here’s the full code for our simple platformer game. Copy and paste this into a Python file (e.g., platformer.py) and run it!

    import pygame
    import sys
    
    pygame.init()
    
    SCREEN_WIDTH = 800
    SCREEN_HEIGHT = 600
    SCREEN = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    
    pygame.display.set_caption("My Simple Platformer")
    
    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)
    RED = (255, 0, 0)
    BLUE = (0, 0, 255)
    GREEN = (0, 255, 0)
    
    player_width = 30
    player_height = 50
    player_x = SCREEN_WIDTH // 2 - player_width // 2 # Start in the middle horizontally
    player_y = SCREEN_HEIGHT - player_height - 50    # Start a bit above the bottom
    player_velocity_x = 0
    player_velocity_y = 0
    player_speed = 5
    jump_power = -15
    gravity = 0.8
    is_grounded = False
    
    ground_height = 20
    ground_x = 0
    ground_y = SCREEN_HEIGHT - ground_height
    ground_width = SCREEN_WIDTH
    ground_rect = pygame.Rect(ground_x, ground_y, ground_width, ground_height)
    
    running = True
    clock = pygame.time.Clock() # For controlling frame rate
    
    while running:
        # 8. Event Handling
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE and is_grounded:
                    player_velocity_y = jump_power
                    is_grounded = False
    
        # 9. Handle horizontal movement with continuous key presses
        keys = pygame.key.get_pressed()
        player_velocity_x = 0 # Reset horizontal velocity each frame
        if keys[pygame.K_LEFT]:
            player_velocity_x = -player_speed
        if keys[pygame.K_RIGHT]:
            player_velocity_x = player_speed
    
        # 10. Update player's horizontal position
        player_x += player_velocity_x
    
        # 11. Apply gravity
        player_velocity_y += gravity
        player_y += player_velocity_y
    
        # 12. Create player rectangle for collision detection and drawing
        player_rect = pygame.Rect(player_x, player_y, player_width, player_height)
    
        # 13. Collision detection with ground
        if player_rect.colliderect(ground_rect):
            player_y = ground_y - player_height # Place player on top of ground
            player_velocity_y = 0               # Stop vertical movement
            is_grounded = True                  # Player is now on the ground
        else:
            is_grounded = False                 # Player is in the air
    
        # 14. Keep player within screen bounds horizontally
        if player_x < 0:
            player_x = 0
        if player_x > SCREEN_WIDTH - player_width:
            player_x = SCREEN_WIDTH - player_width
    
        # 15. Drawing
        SCREEN.fill(BLUE) # Fill background with blue
    
        pygame.draw.rect(SCREEN, GREEN, ground_rect) # Draw the ground
        pygame.draw.rect(SCREEN, RED, player_rect)   # Draw the player
    
        # 16. Update the display
        pygame.display.flip()
    
        # 17. Cap the frame rate (e.g., to 60 FPS)
        clock.tick(60) # This makes sure our game doesn't run too fast
        # Technical Term: FPS (Frames Per Second) - How many times the game updates and draws everything in one second. 60 FPS is generally a smooth experience.
    
    pygame.quit()
    sys.exit()
    

    Next Steps for Fun & Experiments!

    You’ve built the foundation of a platformer! Now the real fun begins: customizing and expanding your game. Here are some ideas:

    • Add more platforms: Instead of just one ground, create multiple pygame.Rect objects for platforms at different heights.
    • Collectibles: Draw small squares or circles that disappear when the player touches them.
    • Enemies: Introduce simple enemies that move back and forth, and figure out what happens when the player collides with them.
    • Sprites: Replace the plain red rectangle with actual character images (sprites). Pygame makes it easy to load and display images.
    • Backgrounds: Add a fancy background image instead of a solid blue color.
    • Level design: Create more complex layouts for your platforms.
    • Game over conditions: What happens if the player falls off the bottom of the screen?

    Conclusion

    Congratulations! You’ve successfully built your very first platformer game from scratch using Python and Pygame. You’ve learned about game loops, event handling, player movement, gravity, and collision detection – all core concepts in game development.

    This project is just the beginning. Game development is a creative and rewarding field, and with the basics you’ve learned today, you have a solid foundation to explore more advanced techniques and build even more amazing games. Keep experimenting, keep coding, and most importantly, have fun! Happy coding!

  • Building a Simple Hangman Game with Flask

    Welcome, aspiring web developers and game enthusiasts! Have you ever wanted to create your own web application but felt overwhelmed by complex frameworks? Today, we’re going to dive into the wonderful world of Flask, a lightweight Python web framework, and build a classic game: Hangman!

    This project is perfect for beginners because it introduces core web development concepts like routing, templates, and session management in a fun and interactive way. By the end of this guide, you’ll have a fully functional web-based Hangman game running right in your browser. Let’s get started and have some fun with Python and Flask!

    What is Flask? (A Quick Introduction)

    Before we start coding, let’s briefly understand what Flask is.

    • Flask: Imagine Flask as a small, easy-to-use toolkit for building websites and web applications using Python. It’s often called a “microframework” because it doesn’t try to do everything for you. Instead, it provides the essential tools, and you can add other components as needed. This makes it perfect for simpler projects or for learning the basics without getting bogged down by too many features.
    • Web Framework: A web framework is a collection of libraries and modules that allows developers to create web applications easily without having to handle low-level details like protocols, sockets, or thread management. It gives you a structure to build your website upon.

    Prerequisites

    To follow along with this tutorial, you’ll need a few things:

    • Python: Make sure you have Python installed on your computer (version 3.6 or newer is recommended). You can download it from the official Python website.
    • Pip: This is Python’s package installer, and it usually comes bundled with Python. We’ll use it to install Flask.
    • A Text Editor: Any code editor like VS Code, Sublime Text, or even Notepad will work.

    Setting Up Your Environment

    First, let’s create a dedicated space for our project to keep things organized.

    1. Create a Project Folder:
      Make a new folder for your game, for example, flask_hangman.
      bash
      mkdir flask_hangman
      cd flask_hangman

    2. Create a Virtual Environment:
      It’s good practice to use a virtual environment for each Python project. This keeps your project’s dependencies separate from other Python projects and your system’s global Python installation.

      • Virtual Environment (venv): Think of it as a secluded little box where you can install Python libraries specifically for your current project, without affecting other projects on your computer.

      To create one:
      bash
      python -m venv venv

      This command creates a folder named venv inside your project folder.

    3. Activate the Virtual Environment:

      • On Windows:
        bash
        venv\Scripts\activate
      • On macOS/Linux:
        bash
        source venv/bin/activate

        You’ll notice (venv) appear at the beginning of your command prompt, indicating that the virtual environment is active.
    4. Install Flask:
      Now that your virtual environment is active, install Flask using pip.

      • Pip: A command-line tool that lets you install and manage Python software packages.

      bash
      pip install Flask

      Flask and its necessary components will be installed within your virtual environment.

    Understanding the Hangman Game Logic

    Before we write code, let’s break down how Hangman works:

    1. Secret Word: The game starts with a hidden word.
    2. Guesses: The player guesses letters one by one.
    3. Correct Guess: If the letter is in the word, it’s revealed in all its positions.
    4. Incorrect Guess: If the letter is not in the word, the player loses a “life” (or a part of the hangman figure is drawn).
    5. Win Condition: The player wins if they guess all letters in the word before running out of lives.
    6. Lose Condition: The player loses if they run out of lives before guessing the word.
    7. Previously Guessed Letters: Players shouldn’t be able to guess the same letter multiple times.

    For our web game, we’ll need to store the game’s state (secret word, guessed letters, remaining lives) as the user makes multiple requests to the server. Flask’s session feature is perfect for this!

    • Session: In web development, a session is a way for a web server to remember information about a specific user over multiple requests. Since web pages are “stateless” (they don’t remember what happened before), sessions help maintain continuity, like remembering a user’s logged-in status or, in our case, the current game’s progress.

    Building the Flask Application (app.py)

    Create a file named app.py in your flask_hangman folder. This will contain all our Python code for the game logic.

    1. Initial Setup and Imports

    from flask import Flask, render_template, request, redirect, url_for, session
    import random
    
    app = Flask(__name__)
    app.secret_key = 'your_secret_key_here' # IMPORTANT: Change this for production!
    
    WORDS = [
        "python", "flask", "hangman", "programming", "developer",
        "challenge", "computer", "internet", "website", "application"
    ]
    
    • from flask import ...: Imports necessary tools from Flask.
      • Flask: The main class to create your application.
      • render_template: Used to display HTML files.
      • request: Allows us to access incoming request data (like form submissions).
      • redirect, url_for: Used to send the user to a different page.
      • session: For storing game state across requests.
    • import random: We’ll use this to pick a random word from our list.
    • app = Flask(__name__): Initializes our Flask application.
    • app.secret_key = ...: Crucial for sessions! Flask uses this key to securely sign session cookies. Without it, sessions won’t work, or they’ll be insecure. Remember to change 'your_secret_key_here' to a long, random string for any real-world application!
    • WORDS: Our list of potential secret words.

    2. Helper Functions

    Let’s create a few helper functions to manage the game logic.

    def get_masked_word(word, guessed_letters):
        masked = ""
        for letter in word:
            if letter in guessed_letters:
                masked += letter
            else:
                masked += "_"
        return masked
    
    def is_game_won(word, guessed_letters):
        return all(letter in guessed_letters for letter in word)
    
    def is_game_lost(lives):
        return lives <= 0
    
    • get_masked_word: Takes the secret word and the letters guessed so far. It returns a string like p_th_n if ‘p’, ‘t’, ‘h’, ‘n’ have been guessed for “python”.
    • is_game_won: Checks if every letter in the secret word has been guessed.
    • is_game_lost: Checks if the player has run out of lives.

    3. Routes (Handling Web Pages)

    Flask uses “routes” to map URLs to Python functions.

    • Route: A route defines what happens when a user visits a specific URL on your website. For example, the / route usually refers to the homepage.

    The Homepage (/)

    @app.route('/')
    def index():
        # If starting a new game or no game in session, initialize game state
        if 'secret_word' not in session or request.args.get('new_game'):
            session['secret_word'] = random.choice(WORDS).lower()
            session['guessed_letters'] = []
            session['lives'] = 6 # Standard Hangman starts with 6-7 lives
            session['message'] = "Guess a letter!"
    
        secret_word = session['secret_word']
        guessed_letters = session['guessed_letters']
        lives = session['lives']
        message = session['message']
    
        masked_word = get_masked_word(secret_word, guessed_letters)
    
        # Check for win/loss conditions to display appropriate messages
        if is_game_won(secret_word, guessed_letters):
            message = f"Congratulations! You guessed the word: '{secret_word}'"
        elif is_game_lost(lives):
            message = f"Game Over! The word was '{secret_word}'."
    
        return render_template('index.html',
                               masked_word=masked_word,
                               guessed_letters=sorted(guessed_letters), # Display sorted for readability
                               lives=lives,
                               message=message,
                               game_over=is_game_won(secret_word, guessed_letters) or is_game_lost(lives))
    
    • @app.route('/'): This decorator tells Flask that the index function should run when someone visits the root URL (/) of our application.
    • session['secret_word'] = ...: We store the chosen word in the user’s session.
    • request.args.get('new_game'): Checks if the URL contains ?new_game=True, which would signal a request to start over.
    • render_template('index.html', ...): This function looks for an HTML file named index.html in a folder called templates (which we’ll create next) and sends it to the user’s browser. We pass variables (like masked_word, lives) to the template so they can be displayed.

    The Guess Endpoint (/guess)

    @app.route('/guess', methods=['POST'])
    def guess():
        secret_word = session.get('secret_word')
        guessed_letters = session.get('guessed_letters', [])
        lives = session.get('lives', 6)
    
        # Prevent further guesses if the game is already over
        if is_game_won(secret_word, guessed_letters) or is_game_lost(lives):
            return redirect(url_for('index'))
    
        guess_letter = request.form['letter'].lower()
        session['message'] = "" # Clear previous messages
    
        if len(guess_letter) != 1 or not guess_letter.isalpha():
            session['message'] = "Please enter a single letter."
        elif guess_letter in guessed_letters:
            session['message'] = f"You already guessed '{guess_letter}'. Try another letter!"
        else:
            guessed_letters.append(guess_letter)
            session['guessed_letters'] = guessed_letters # Update session
    
            if guess_letter not in secret_word:
                lives -= 1
                session['lives'] = lives
                session['message'] = f"'{guess_letter}' is not in the word. You lost a life!"
            else:
                session['message'] = f"Good guess! '{guess_letter}' is in the word."
    
        # Redirect back to the index page to display updated game state
        return redirect(url_for('index'))
    
    • @app.route('/guess', methods=['POST']): This route only accepts POST requests, which is standard for form submissions.
    • request.form['letter']: This accesses the data sent from the HTML form (specifically the input field named ‘letter’).
    • Game Logic Updates: We check if the guess is valid, if it’s already guessed, if it’s in the word, and update guessed_letters, lives, and message in the session accordingly.
    • redirect(url_for('index')): After processing the guess, we redirect the user back to the homepage (/). This is a common pattern called “Post/Redirect/Get” which prevents duplicate form submissions if the user refreshes the page.

    4. Running the App

    if __name__ == '__main__':
        app.run(debug=True)
    
    • if __name__ == '__main__':: This standard Python construct ensures that app.run() is called only when you run app.py directly (not when imported as a module).
    • app.run(debug=True): Starts the Flask development server. debug=True means that the server will automatically reload when you make changes to your code, and it will show you detailed error messages in the browser. Always set debug=False in production environments for security.

    Creating the HTML Template (templates/index.html)

    Flask expects your HTML templates to be in a folder named templates within your project directory. So, create a new folder called templates inside flask_hangman, and then create a file named index.html inside templates.

    Your project structure should now look like this:

    flask_hangman/
    ├── venv/
    ├── app.py
    └── templates/
        └── index.html
    

    Now, open templates/index.html and add the following HTML code:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Flask Hangman Game</title>
        <style>
            body {
                font-family: Arial, sans-serif;
                background-color: #f4f4f4;
                color: #333;
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: center;
                min-height: 100vh;
                margin: 0;
            }
            .container {
                background-color: #fff;
                padding: 30px 50px;
                border-radius: 8px;
                box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
                text-align: center;
                max-width: 500px;
                width: 90%;
            }
            h1 {
                color: #0056b3;
                margin-bottom: 20px;
            }
            .word-display {
                font-size: 3em;
                letter-spacing: 5px;
                margin: 30px 0;
                font-weight: bold;
                color: #28a745;
            }
            .message {
                margin-top: 20px;
                font-size: 1.2em;
                color: #dc3545; /* For error/game over messages */
            }
            .message.success {
                color: #28a745; /* For success messages */
            }
            .message.info {
                color: #007bff; /* For general info */
            }
            .guessed-letters {
                margin: 20px 0;
                font-size: 1.1em;
            }
            .lives {
                font-size: 1.1em;
                color: #ffc107;
                font-weight: bold;
            }
            form {
                margin-top: 30px;
                display: flex;
                justify-content: center;
                align-items: center;
            }
            input[type="text"] {
                padding: 10px;
                border: 1px solid #ddd;
                border-radius: 4px;
                width: 60px;
                text-align: center;
                font-size: 1.2em;
                margin-right: 10px;
                text-transform: lowercase;
            }
            button {
                background-color: #007bff;
                color: white;
                padding: 10px 20px;
                border: none;
                border-radius: 4px;
                cursor: pointer;
                font-size: 1.1em;
                transition: background-color 0.3s ease;
            }
            button:hover {
                background-color: #0056b3;
            }
            .new-game-button {
                background-color: #6c757d;
                margin-top: 20px;
                padding: 10px 20px;
                border-radius: 4px;
                color: white;
                text-decoration: none;
                display: inline-block;
                font-size: 1.1em;
                transition: background-color 0.3s ease;
            }
            .new-game-button:hover {
                background-color: #5a6268;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <h1>Hangman Game</h1>
    
            <p class="message {% if 'Good guess' in message %}success{% elif 'already guessed' in message or 'not in the word' in message %}danger{% else %}info{% endif %}">
                {{ message }}
            </p>
    
            <div class="word-display">
                {{ masked_word }}
            </div>
    
            <p class="lives">
                Lives Left: {{ lives }}
            </p>
    
            <p class="guessed-letters">
                Guessed Letters: {{ guessed_letters | join(', ') }}
            </p>
    
            {% if not game_over %}
            <form action="{{ url_for('guess') }}" method="post">
                <label for="letter">Guess a letter:</label>
                <input type="text" id="letter" name="letter" maxlength="1" required autocomplete="off">
                <button type="submit">Guess</button>
            </form>
            {% else %}
            <a href="{{ url_for('index', new_game='true') }}" class="new-game-button">Start New Game</a>
            {% endif %}
        </div>
    </body>
    </html>
    
    • Jinja Templating: Flask uses a templating engine called Jinja2. This allows you to embed Python-like logic directly into your HTML.
      • {{ variable_name }}: Used to display the value of a variable passed from your Flask application.
      • {% if condition %} / {% else %} / {% endif %}: Used for conditional logic.
      • {{ list_variable | join(', ') }}: A Jinja filter that joins items in a list with a comma and space.
    • masked_word: Displays the word with underscores for unguessed letters.
    • lives: Shows how many lives are left.
    • guessed_letters: Lists all the letters the user has tried.
    • <form action="{{ url_for('guess') }}" method="post">: This form sends the user’s guess to our /guess route using the POST method. url_for('guess') dynamically generates the URL for the guess function.
    • input type="text" id="letter" name="letter" maxlength="1" required: An input field where the user types their guess. name="letter" is important because Flask’s request.form['letter'] uses this name to get the value. maxlength="1" ensures only one character can be entered.
    • {% if not game_over %}: This block ensures the guess form is only visible if the game is still active. If the game is over, a “Start New Game” button appears instead.
    • <a href="{{ url_for('index', new_game='true') }}" ...>: This link will restart the game by sending a new_game=true parameter to the index route.

    Running Your Hangman Game!

    You’re all set! Now, let’s run your Flask application.

    1. Ensure your virtual environment is active. (If you closed your terminal, cd flask_hangman and reactivate it using the commands from “Setting Up Your Environment” section).
    2. Navigate to your flask_hangman directory in the terminal.
    3. Set the FLASK_APP environment variable:
      • On Windows:
        bash
        set FLASK_APP=app.py
      • On macOS/Linux:
        bash
        export FLASK_APP=app.py
      • FLASK_APP: This environment variable tells Flask where to find your application file.
    4. Run the Flask application:
      bash
      flask run

    You should see output similar to this:

     * Debug mode: on
    WARNING: This is a development server. Do not use it in a production deployment.
    Use a production WSGI server instead.
     * Running on http://127.0.0.1:5000
    Press CTRL+C to quit
     * Restarting with stat
     * Debugger is active!
     * Debugger PIN: ...
    

    Open your web browser and go to http://127.0.0.1:5000. You should now see your Hangman game! Try guessing letters, win, lose, and start new games.

    Conclusion

    Congratulations! You’ve successfully built a simple but fully functional Hangman game using Python and Flask. You’ve learned about:

    • Setting up a Flask project with a virtual environment.
    • Defining routes to handle different web pages.
    • Using Flask’s session to manage game state across requests.
    • Rendering HTML templates with Jinja2 to display dynamic content.
    • Handling form submissions (POST requests).

    This project is a great foundation. From here, you could enhance it by:

    • Adding CSS to make it look much prettier (we included a basic style block, but you can move it to a separate static/style.css file!).
    • Creating a proper graphical representation of the hangman figure.
    • Adding more words or allowing users to input their own.
    • Implementing user accounts and high scores.

    Keep experimenting, keep building, and happy coding!

  • Web Scraping for Fun: Building a Meme Scraper

    Welcome, fellow digital adventurers! Have you ever stumbled upon a website filled with hilarious memes and wished you could easily save a bunch of them to share with your friends later? Or perhaps you’re just curious about how websites work and want to try a fun, hands-on project. Well, today, we’re going to dive into the exciting world of “web scraping” to build our very own meme scraper!

    Don’t worry if you’re new to coding or web technologies. We’ll break down everything step by step, using simple language and providing explanations for any technical terms along the way. By the end of this guide, you’ll have a basic Python script that can automatically grab memes from a website – a truly fun and experimental project!

    What is Web Scraping?

    Imagine you’re browsing the internet. Your web browser (like Chrome, Firefox, or Safari) sends a request to a website’s server, and the server sends back a bunch of information, mainly in a language called HTML. Your browser then reads this HTML and displays it as the nice-looking webpage you see.

    Web scraping is like doing what your browser does, but automatically with a computer program. Instead of just showing the content, your program reads the raw HTML data and picks out specific pieces of information you’re interested in, such as text, links, or in our case, image URLs (the web addresses where images are stored).

    • HTML (HyperText Markup Language): This is the standard language used to create web pages. Think of it as the skeleton of a webpage, defining its structure (headings, paragraphs, images, links, etc.). When you view a webpage, your browser interprets this HTML and displays it visually.

    Why scrape memes? For fun, of course! It’s a fantastic way to learn about how websites are structured, practice your Python skills, and get a neat collection of your favorite internet humor.

    Tools We’ll Need

    To build our meme scraper, we’ll be using Python, a popular and easy-to-learn programming language. Alongside Python, we’ll use two powerful libraries:

    1. requests: This library helps your Python program act like a web browser. It allows you to send requests to websites and get their content back.
    2. BeautifulSoup: Once you have the raw HTML content, BeautifulSoup helps you navigate through it, find specific elements (like image tags), and extract the information you need. It’s like a magical librarian for HTML!

    3. Python Library: In programming, a “library” is a collection of pre-written code that you can use in your own programs. It helps you avoid writing common tasks from scratch, making your coding faster and more efficient.

    Let’s Get Started! Your First Scraper

    Step 1: Setting Up Your Environment

    First, you need to have Python installed on your computer. If you don’t, you can download it from the official Python website (python.org). Most modern operating systems (like macOS and Linux) often come with Python pre-installed.

    Once Python is ready, we need to install our requests and BeautifulSoup libraries. Open your computer’s command prompt or terminal and type the following commands:

    pip install requests
    pip install beautifulsoup4
    
    • pip: This is Python’s package installer. It’s a command-line tool that lets you easily install and manage Python libraries.

    Step 2: Choose Your Meme Source

    For this tutorial, we’ll pick a simple website where memes are displayed. It’s crucial to understand that not all websites allow scraping, and some have complex structures that are harder for beginners. Always check a website’s robots.txt file (e.g., example.com/robots.txt) to understand their scraping policies. For educational purposes, we’ll use a hypothetical simplified meme gallery URL.

    Let’s assume our target website is http://www.example.com/meme-gallery. In a real scenario, you’d find a website with images that you can legally and ethically scrape for personal use.

    • robots.txt: This is a file that webmasters create to tell web crawlers (like search engines or our scraper) which parts of their site they don’t want to be accessed. It’s like a polite “keep out” sign for automated programs. Always respect it!

    Step 3: Fetch the Web Page

    Now, let’s write our first bit of Python code to download the webpage content. Create a new Python file (e.g., meme_scraper.py) and add the following:

    import requests
    
    url = "http://www.example.com/meme-gallery"
    
    try:
        # Send a GET request to the URL
        response = requests.get(url)
    
        # Check if the request was successful (status code 200 means OK)
        response.raise_for_status() # Raises an HTTPError for bad responses (4xx or 5xx)
    
        print(f"Successfully fetched {url}")
        # You can print a part of the content to see what it looks like
        # print(response.text[:500]) # Prints the first 500 characters of the HTML
    
    except requests.exceptions.RequestException as e:
        print(f"Error fetching the page: {e}")
    

    When you run this script (python meme_scraper.py in your terminal), it will attempt to download the content of the specified URL. If successful, it prints a confirmation message.

    Step 4: Parse the HTML with BeautifulSoup

    Once we have the raw HTML, BeautifulSoup comes into play to help us make sense of it. We’ll create a “soup object” from the HTML content.

    Add the following to your script:

    import requests
    from bs4 import BeautifulSoup # Import BeautifulSoup
    
    url = "http://www.example.com/meme-gallery"
    
    try:
        response = requests.get(url)
        response.raise_for_status()
    
        # Create a BeautifulSoup object to parse the HTML
        soup = BeautifulSoup(response.text, 'html.parser')
        print("HTML parsed successfully!")
    
    except requests.exceptions.RequestException as e:
        print(f"Error fetching the page: {e}")
    
    • html.parser: This is a built-in Python library that BeautifulSoup uses to understand and break down the HTML code into a structure that Python can easily work with.

    Step 5: Find the Meme Images

    This is where the real fun begins! We need to tell BeautifulSoup what kind of elements to look for that contain our memes. Memes are typically images, and images on a webpage are defined by <img> tags in HTML. Inside an <img> tag, the src attribute holds the actual URL of the image.

    To find out how image tags are structured on a specific website, you’d usually use your browser’s “Inspect Element” tool (right-click on an image and select “Inspect”). You’d look for the <img> tag and any parent <div> or <figure> tags that might contain useful classes or IDs to pinpoint the images accurately.

    For our simplified example.com/meme-gallery, let’s assume images are directly within <img> tags, or perhaps within a div with a specific class, like <div class="meme-container">. We’ll start by looking for all <img> tags.

    import requests
    from bs4 import BeautifulSoup
    import os # To handle file paths and create directories
    
    url = "http://www.example.com/meme-gallery"
    meme_urls = [] # List to store URLs of memes
    
    try:
        response = requests.get(url)
        response.raise_for_status()
        soup = BeautifulSoup(response.text, 'html.parser')
    
        # Find all <img> tags in the HTML
        # We might want to refine this if the website uses specific classes for meme images
        # For example: images = soup.find_all('img', class_='meme-image')
        images = soup.find_all('img')
    
        for img in images:
            img_url = img.get('src') # Get the value of the 'src' attribute
            if img_url:
                # Sometimes image URLs are relative (e.g., '/images/meme.jpg')
                # We need to make them absolute (e.g., 'http://www.example.com/images/meme.jpg')
                if not img_url.startswith('http'):
                    # Simple concatenation, might need more robust URL joining for complex cases
                    img_url = url + img_url
                meme_urls.append(img_url)
    
        print(f"Found {len(meme_urls)} potential meme images.")
        # For demonstration, print the first few URLs
        # for i, meme_url in enumerate(meme_urls[:5]):
        #     print(f"Meme {i+1}: {meme_url}")
    
    
    except requests.exceptions.RequestException as e:
        print(f"Error fetching or parsing the page: {e}")
    

    Step 6: Download the Memes

    Finally, we’ll iterate through our list of meme URLs and download each image. We’ll save them into a new folder to keep things tidy.

    import requests
    from bs4 import BeautifulSoup
    import os
    
    url = "http://www.example.com/meme-gallery"
    meme_urls = []
    
    output_folder = "downloaded_memes"
    os.makedirs(output_folder, exist_ok=True) # Creates the folder if it doesn't exist
    
    try:
        response = requests.get(url)
        response.raise_for_status()
        soup = BeautifulSoup(response.text, 'html.parser')
    
        images = soup.find_all('img')
    
        for img in images:
            img_url = img.get('src')
            if img_url:
                if not img_url.startswith('http'):
                    # Basic absolute URL construction (may need refinement)
                    img_url = requests.compat.urljoin(url, img_url) # More robust URL joining
                meme_urls.append(img_url)
    
        print(f"Found {len(meme_urls)} potential meme images. Starting download...")
    
        for i, meme_url in enumerate(meme_urls):
            try:
                # Get the image content
                image_response = requests.get(meme_url, stream=True)
                image_response.raise_for_status()
    
                # Extract filename from the URL
                image_name = os.path.basename(meme_url).split('?')[0] # Remove query parameters
                if not image_name: # Handle cases where URL doesn't have a clear filename
                    image_name = f"meme_{i+1}.jpg" # Fallback filename
    
                file_path = os.path.join(output_folder, image_name)
    
                # Save the image content to a file
                with open(file_path, 'wb') as f:
                    for chunk in image_response.iter_content(chunk_size=8192):
                        f.write(chunk)
                print(f"Downloaded: {image_name}")
    
            except requests.exceptions.RequestException as e:
                print(f"Could not download {meme_url}: {e}")
            except Exception as e:
                print(f"An unexpected error occurred while downloading {meme_url}: {e}")
    
        print(f"\nFinished downloading memes to the '{output_folder}' folder!")
    
    except requests.exceptions.RequestException as e:
        print(f"Error fetching or parsing the page: {e}")
    

    Putting It All Together (Full Script)

    Here’s the complete script incorporating all the steps:

    import requests
    from bs4 import BeautifulSoup
    import os
    
    def build_meme_scraper(target_url, output_folder="downloaded_memes"):
        """
        Scrapes images from a given URL and saves them to a specified folder.
        """
        meme_urls = []
    
        # Create the output directory if it doesn't exist
        os.makedirs(output_folder, exist_ok=True)
        print(f"Output folder '{output_folder}' ensured.")
    
        try:
            # Step 1: Fetch the Web Page
            print(f"Attempting to fetch content from: {target_url}")
            response = requests.get(target_url, timeout=10) # Added a timeout for safety
            response.raise_for_status() # Check for HTTP errors
    
            # Step 2: Parse the HTML with BeautifulSoup
            print("Page fetched successfully. Parsing HTML...")
            soup = BeautifulSoup(response.text, 'html.parser')
    
            # Step 3: Find the Meme Images
            # This part might need adjustment based on the target website's HTML structure
            # We're looking for all <img> tags for simplicity.
            # You might want to filter by specific classes or parent elements.
            images = soup.find_all('img')
    
            print(f"Found {len(images)} <img> tags.")
    
            for img in images:
                img_url = img.get('src') # Get the 'src' attribute
                if img_url:
                    # Resolve relative URLs to absolute URLs
                    full_img_url = requests.compat.urljoin(target_url, img_url)
                    meme_urls.append(full_img_url)
    
            print(f"Identified {len(meme_urls)} potential meme image URLs.")
    
            # Step 4: Download the Memes
            downloaded_count = 0
            for i, meme_url in enumerate(meme_urls):
                try:
                    print(f"Downloading image {i+1}/{len(meme_urls)}: {meme_url}")
                    image_response = requests.get(meme_url, stream=True, timeout=10)
                    image_response.raise_for_status()
    
                    # Get a clean filename from the URL
                    image_name = os.path.basename(meme_url).split('?')[0].split('#')[0]
                    if not image_name:
                        image_name = f"meme_{i+1}.jpg" # Fallback
    
                    file_path = os.path.join(output_folder, image_name)
    
                    # Save the image content
                    with open(file_path, 'wb') as f:
                        for chunk in image_response.iter_content(chunk_size=8192):
                            f.write(chunk)
                    print(f"Successfully saved: {file_path}")
                    downloaded_count += 1
    
                except requests.exceptions.RequestException as e:
                    print(f"Skipping download for {meme_url} due to network error: {e}")
                except Exception as e:
                    print(f"Skipping download for {meme_url} due to unexpected error: {e}")
    
            print(f"\nFinished scraping. Downloaded {downloaded_count} memes to '{output_folder}'.")
    
        except requests.exceptions.RequestException as e:
            print(f"An error occurred during page fetching or parsing: {e}")
        except Exception as e:
            print(f"An unexpected error occurred: {e}")
    
    if __name__ == "__main__":
        # IMPORTANT: Replace this with the actual URL of a website you want to scrape.
        # Always ensure you have permission and respect their robots.txt file.
        # For this example, we're using a placeholder.
        target_meme_url = "http://www.example.com/meme-gallery" # <--- CHANGE THIS URL
    
        # You can specify a different folder name if you like
        scraper_output_folder = "my_funny_memes" 
    
        print("Starting meme scraper...")
        build_meme_scraper(target_meme_url, scraper_output_folder)
        print("Meme scraper script finished.")
    

    Remember to replace "http://www.example.com/meme-gallery" with the actual URL of a meme website you’re interested in scraping!

    Important Considerations (Ethics & Legality)

    Before you go wild scraping the entire internet, it’s really important to understand the ethical and legal aspects of web scraping:

    • Respect robots.txt: Always check a website’s robots.txt file. If it forbids scraping, you should respect that.
    • Don’t Overload Servers: Make your requests at a reasonable pace. Sending too many requests too quickly can overwhelm a website’s server, potentially leading to them blocking your IP address or even legal action. Adding time.sleep() between requests can help.
    • Copyright: Most content on the internet, including memes, is copyrighted. Scraping for personal use is generally less problematic than redistributing or using scraped content commercially without permission. Always be mindful of content ownership.
    • Terms of Service: Many websites have terms of service that explicitly prohibit scraping. Violating these can have consequences.

    This guide is for educational purposes and personal experimentation. Always scrape responsibly!

    Conclusion

    Congratulations! You’ve just built a basic web scraper using Python, requests, and BeautifulSoup. You’ve learned how to:

    • Fetch webpage content.
    • Parse HTML to find specific elements.
    • Extract image URLs.
    • Download and save images to your computer.

    This is just the tip of the iceberg for web scraping. You can use these fundamental skills to gather all sorts of public data from the web for personal projects, research, or just plain fun. Keep experimenting, stay curious, and happy scraping!


  • Building Your First Maze Game in Python (No Experience Needed!)

    Hello future game developers and Python enthusiasts! Have you ever wanted to create your own simple game but felt intimidated by complex coding? Well, you’re in luck! Today, we’re going to build a fun, text-based maze game using Python. This project is perfect for beginners and will introduce you to some core programming concepts in a playful way.

    By the end of this guide, you’ll have a playable maze game, and you’ll understand how to:
    * Represent a game world using simple data structures.
    * Handle player movement and input.
    * Implement basic game logic and win conditions.
    * Use fundamental Python concepts like lists, loops, and conditional statements.

    Let’s dive in!

    What is a Text-Based Maze Game?

    Imagine a maze drawn with characters like # for walls, . for paths, P for your player, and E for the exit. That’s exactly what we’re going to create! Your goal will be to navigate your player ‘P’ through the maze to reach ‘E’ without running into any walls.

    What You’ll Need

    • Python: Make sure you have Python installed on your computer (version 3.x is recommended). You can download it from the official Python website.
    • A Text Editor: Any basic text editor like Notepad (Windows), TextEdit (Mac), VS Code, Sublime Text, or Atom will work. This is where you’ll write your code.
      • Supplementary Explanation: Text Editor: Think of a text editor as a special notebook designed for writing computer code. It helps keep your code organized and sometimes even highlights errors!
    • Enthusiasm! That’s the most important one.

    Step 1: Setting Up Our Maze

    First, we need to define our maze. We’ll represent it as a “list of lists” (also known as a 2D array). Each inner list will be a row in our maze, and each character within that list will be a part of the maze (wall, path, player, exit).

    Supplementary Explanation: List and List of Lists:
    * A list in Python is like a shopping list – an ordered collection of items. For example, ["apple", "banana", "cherry"].
    * A list of lists is a list where each item is itself another list. This is perfect for creating grids, like our maze, where each inner list represents a row.

    Let’s define a simple maze:

    maze = [
        "#######E#####",
        "#P...........#",
        "#.###########",
        "#.#.........#",
        "#.#.#######.#",
        "#.#.........#",
        "#.###########",
        "#.............#",
        "###############"
    ]
    
    for i in range(len(maze)):
        maze[i] = list(maze[i])
    

    In this maze:
    * The P is at row 1, column 1.
    * The E is at row 0, column 7.

    Step 2: Displaying the Maze

    We need a way to show the maze to the player after each move. Let’s create a function for this.

    Supplementary Explanation: Function: A function is like a mini-program or a recipe for a specific task. You give it a name, and you can “call” it whenever you need that task done. This helps keep your code organized and reusable.

    def display_maze(maze):
        """
        Prints the current state of the maze to the console.
        Each character is joined back into a string for display.
        """
        for row in maze:
            print("".join(row)) # Join the list of characters back into a string for printing
        print("-" * len(maze[0])) # Print a separator line for clarity
    

    Now, if you call display_maze(maze) after the setup, you’ll see your maze printed in the console!

    Step 3: Player Position and Initial Setup

    We need to know where our player is at all times. We’ll find the ‘P’ in our maze and store its coordinates.

    Supplementary Explanation: Variables: Think of a variable as a labeled box where you can store information, like a number, a piece of text, or even the coordinates of our player.

    player_row = 0
    player_col = 0
    
    for r in range(len(maze)):
        for c in range(len(maze[r])):
            if maze[r][c] == 'P':
                player_row = r
                player_col = c
                break # Found the player, no need to search further in this row
        if 'P' in maze[r]: # If 'P' was found in the current row, break outer loop too
            break
    

    We now have player_row and player_col holding the player’s current position.

    Step 4: Handling Player Movement

    This is the core of our game logic. We need a function that takes a direction (like ‘w’ for up, ‘s’ for down, etc.) and updates the player’s position, but only if the move is valid (not hitting a wall or going out of bounds).

    Supplementary Explanation: Conditional Statements (if/elif/else): These are like decision-making tools for your code. “IF something is true, THEN do this. ELSE IF something else is true, THEN do that. ELSE (if neither is true), do this other thing.”

    def move_player(maze, player_row, player_col, move):
        """
        Calculates the new player position based on the move.
        Checks for walls and boundaries.
        Returns the new row and column, or the old ones if the move is invalid.
        """
        new_row, new_col = player_row, player_col
    
        # Determine the target coordinates based on the input move
        if move == 'w': # Up
            new_row -= 1
        elif move == 's': # Down
            new_row += 1
        elif move == 'a': # Left
            new_col -= 1
        elif move == 'd': # Right
            new_col += 1
        else:
            print("Invalid move. Use 'w', 'a', 's', 'd'.")
            return player_row, player_col # No valid move, return current position
    
        # Check if the new position is within the maze boundaries
        # len(maze) gives us the number of rows
        # len(maze[0]) gives us the number of columns (assuming all rows are same length)
        if 0 <= new_row < len(maze) and 0 <= new_col < len(maze[0]):
            # Check if the new position is a wall
            if maze[new_row][new_col] == '#':
                print("Ouch! You hit a wall!")
                return player_row, player_col # Can't move, return current position
            else:
                # Valid move! Update the maze:
                # 1. Clear the old player position (replace 'P' with '.')
                maze[player_row][player_col] = '.'
                # 2. Place 'P' at the new position
                maze[new_row][new_col] = 'P'
                return new_row, new_col # Return the new position
        else:
            print("You can't go off the map!")
            return player_row, player_col # Can't move, return current position
    

    Step 5: The Game Loop!

    Now we bring everything together in a “game loop.” This loop will continuously:
    1. Display the maze.
    2. Ask the player for their next move.
    3. Update the player’s position.
    4. Check if the player has reached the exit.

    Supplementary Explanation: Loop (while True): A while loop repeatedly executes a block of code as long as a certain condition is true. while True means it will run forever until it hits a break statement inside the loop. This is perfect for games that run continuously.

    game_over = False
    
    while not game_over:
        display_maze(maze)
    
        # Get player input
        # input() waits for the user to type something and press Enter
        player_move = input("Enter your move (w/a/s/d): ").lower() # .lower() converts input to lowercase
    
        # Update player position
        # The move_player function returns the new coordinates
        old_player_row, old_player_col = player_row, player_col
        player_row, player_col = move_player(maze, player_row, player_col, player_move)
    
        # Check for win condition: Did the player move onto the 'E' cell?
        # Note: We check if the *old* 'P' position was replaced by 'E' after moving
        # This logic is a bit tricky if 'E' is *just* walked onto.
        # A cleaner way is to check the cell *before* moving 'P' to it.
        # Let's adjust move_player slightly or check the target cell directly.
    
        # Revised win condition check within the loop:
        # We need to know if the *target* cell was 'E' *before* the player moved there.
        # Let's refine the move_player to return a status, or check after the fact.
    
        # Simpler win condition check: Check if the current player_row/col is where E was.
        # This requires us to know the E's original position. Let's find E's position too.
        exit_row, exit_col = -1, -1
        for r in range(len(maze)):
            for c in range(len(maze[r])):
                if maze[r][c] == 'E': # Find the original 'E'
                    exit_row, exit_col = r, c
                    # Important: If 'E' is overwritten by 'P', the original 'E' is gone.
                    # So we need to check if the new 'P' position *matches* E's initial position.
                    break
            if exit_row != -1:
                break
    
        # If the player is now at the exit's original position (which is now 'P' after the move)
        if player_row == exit_row and player_col == exit_col:
            display_maze(maze) # Show the final maze with 'P' at 'E'
            print("Congratulations! You found the exit!")
            game_over = True
    

    Putting It All Together (Full Code)

    Here’s the complete code for your simple maze game:

    maze_blueprint = [
        "#######E#####",
        "#P...........#",
        "#.###########",
        "#.#.........#",
        "#.#.#######.#",
        "#.#.........#",
        "#.###########",
        "#.............#",
        "###############"
    ]
    
    maze = []
    for row_str in maze_blueprint:
        maze.append(list(row_str))
    
    player_row = 0
    player_col = 0
    for r in range(len(maze)):
        for c in range(len(maze[r])):
            if maze[r][c] == 'P':
                player_row = r
                player_col = c
                break
        if 'P' in maze_blueprint[r]: # Check blueprint to see if 'P' was found in row
            break
    
    exit_row = 0
    exit_col = 0
    for r in range(len(maze)):
        for c in range(len(maze[r])):
            if maze[r][c] == 'E':
                exit_row = r
                exit_col = c
                break
        if 'E' in maze_blueprint[r]: # Check blueprint to see if 'E' was found in row
            break
    
    def display_maze(current_maze):
        """
        Prints the current state of the maze to the console.
        """
        for row in current_maze:
            print("".join(row))
        print("-" * len(current_maze[0])) # Separator
    
    def move_player(current_maze, p_row, p_col, move):
        """
        Calculates the new player position based on the move.
        Checks for walls and boundaries.
        Returns the new row and column, or the old ones if the move is invalid.
        """
        new_row, new_col = p_row, p_col
    
        if move == 'w': # Up
            new_row -= 1
        elif move == 's': # Down
            new_row += 1
        elif move == 'a': # Left
            new_col -= 1
        elif move == 'd': # Right
            new_col += 1
        else:
            print("Invalid move. Use 'w', 'a', 's', 'd'.")
            return p_row, p_col
    
        # Check boundaries
        if not (0 <= new_row < len(current_maze) and 0 <= new_col < len(current_maze[0])):
            print("You can't go off the map!")
            return p_row, p_col
    
        # Check for walls
        if current_maze[new_row][new_col] == '#':
            print("Ouch! You hit a wall!")
            return p_row, p_col
    
        # Valid move: Update maze
        current_maze[p_row][p_col] = '.' # Clear old position
        current_maze[new_row][new_col] = 'P' # Set new position
        return new_row, new_col
    
    game_over = False
    print("Welcome to the Maze Game!")
    print("Navigate 'P' to 'E' using w (up), a (left), s (down), d (right).")
    
    while not game_over:
        display_maze(maze)
    
        player_move = input("Enter your move (w/a/s/d): ").lower()
    
        # Store old position for comparison, then update
        player_row, player_col = move_player(maze, player_row, player_col, player_move)
    
        # Check for win condition
        if player_row == exit_row and player_col == exit_col:
            display_maze(maze) # Show final state
            print("Congratulations! You found the exit!")
            game_over = True
    

    How to Play

    1. Save the code: Open your text editor, paste the entire code, and save it as maze_game.py (or any name ending with .py).
    2. Open a terminal/command prompt: Navigate to the directory where you saved your file.
    3. Run the game: Type python maze_game.py and press Enter.
    4. Play! The maze will appear, and you can type w, a, s, or d (and press Enter) to move your player. Try to reach the E!

    Going Further (Ideas for Enhancements!)

    You’ve built a solid foundation! Here are some ideas to make your game even better:

    • More Complex Mazes: Design larger and more intricate mazes. You could even read maze designs from a separate text file!
    • Move Counter: Keep track of how many moves the player makes and display it at the end.
    • Different Characters: Use S for start and G for goal (goal!).
    • Traps/Treasures: Add special squares that do something (e.g., T for treasure that gives points, X for a trap that sends you back a few spaces).
    • Clear Screen: Learn how to clear the console screen between moves for a smoother experience (e.g., import os; os.system('cls' if os.name == 'nt' else 'clear')).
    • Graphical Interface: If you’re feeling adventurous, you could explore libraries like Pygame to turn your text maze into a graphical one!

    Conclusion

    Congratulations! You’ve just created your very first interactive game in Python. You’ve learned about representing game worlds, handling user input, making decisions with conditional logic, and repeating actions with loops. These are fundamental skills that will serve you well in any programming journey.

    Keep experimenting, keep coding, and most importantly, keep having fun! If you ran into any issues, don’t worry, that’s a normal part of learning. Just go back through the steps, check for typos, and try again. Happy coding!