Category: Fun & Experiments

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

  • 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!

  • Drawing Your First Lines: Building a Simple Drawing App with Django

    Welcome, aspiring web developers! Have you ever wanted to create something interactive and fun, even if you’re just starting your journey into web development? Today, we’re going to combine the power of Django – a fantastic web framework – with some client-side magic to build a super simple, interactive drawing application. This project falls into our “Fun & Experiments” category because it’s a great way to learn basic concepts while seeing immediate, visible results.

    By the end of this guide, you’ll have a basic webpage where you can draw directly in your browser using your mouse. It’s a perfect project for beginners to understand how Django serves web pages and how client-side JavaScript can bring those pages to life!

    What is Django?

    Before we dive in, let’s quickly understand what Django is.
    Django is a high-level Python web framework that encourages rapid development and clean, pragmatic design. Think of it as a toolkit that helps you build powerful websites quickly, taking care of many common web development tasks so you can focus on your unique application.

    Setting Up Your Environment

    First things first, let’s get your computer ready. We’ll assume you have Python and pip (Python’s package installer) already installed. If not, please install Python from its official website.

    It’s good practice to create a virtual environment for each project. A virtual environment is like an isolated space for your project’s dependencies, preventing conflicts between different projects.

    1. Create a virtual environment:
      Navigate to the folder where you want to create your project in your terminal or command prompt.
      bash
      python -m venv venv

      • python -m venv: This command uses Python’s built-in venv module to create a virtual environment.
      • venv: This is the name we’re giving to our virtual environment folder.
    2. Activate the virtual environment:

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

        You’ll know it’s active when you see (venv) at the beginning of your terminal prompt.
    3. Install Django:
      With your virtual environment active, install Django using pip.
      bash
      pip install Django

    Starting a New Django Project

    Now that Django is installed, let’s create our project and an app within it. In Django, a project is a collection of settings and apps that together make up a complete web application. An app is a web application that does something specific (e.g., a blog app, a drawing app).

    1. Create the Django project:
      Make sure you are in the same directory where you created your virtual environment.
      bash
      django-admin startproject mysketchbook .

      • django-admin: This is Django’s command-line utility.
      • startproject mysketchbook: This tells Django to create a new project named mysketchbook.
      • .: This is important! It tells Django to create the project files in the current directory, rather than creating an extra nested mysketchbook folder.
    2. Create a Django app:
      bash
      python manage.py startapp drawingapp

      • python manage.py: manage.py is a script automatically created with your project that helps you manage your Django project.
      • startapp drawingapp: This creates a new app named drawingapp within your mysketchbook project. This app will contain all the code specific to our drawing functionality.

    Integrating Your App into the Project

    For Django to know about your new drawingapp, you need to register it in your project’s settings.

    1. Edit mysketchbook/settings.py:
      Open the mysketchbook/settings.py file in your code editor. Find the INSTALLED_APPS list and add 'drawingapp' to it.

      “`python

      mysketchbook/settings.py

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

    Basic URL Configuration

    Next, we need to tell Django how to direct web requests (like someone typing /draw/ into their browser) to our drawingapp. This is done using URLs.

    1. Edit the project’s mysketchbook/urls.py:
      This file acts as the main dispatcher for your project. We’ll include our app’s URLs here.

      “`python

      mysketchbook/urls.py

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

      urlpatterns = [
      path(‘admin/’, admin.site.urls),
      path(‘draw/’, include(‘drawingapp.urls’)), # Direct requests starting with ‘draw/’ to drawingapp
      ]
      ``
      *
      include(‘drawingapp.urls’): This means that any request starting with/draw/will be handed over to theurls.pyfile inside yourdrawingapp` for further processing.

    2. Create drawingapp/urls.py:
      Now, create a new file named urls.py inside your drawingapp folder (drawingapp/urls.py). This file will define the specific URLs for your drawing application.

      “`python

      drawingapp/urls.py

      from django.urls import path
      from . import views # Import views from the current app

      urlpatterns = [
      path(”, views.draw_view, name=’draw_view’), # Map the root of this app to draw_view
      ]
      ``
      *
      path(”, views.draw_view, name=’draw_view’): This tells Django that when a request comes to the root of ourdrawingapp(which is/draw/because of our project'surls.py), it should call a function nameddraw_viewfrom ourviews.pyfile.name=’draw_view’` gives this URL a handy name for later use.

    Creating Your View

    A view in Django is a function that takes a web request and returns a web response, typically an HTML page.

    1. Edit drawingapp/views.py:
      Open drawingapp/views.py and add the following code:

      “`python

      drawingapp/views.py

      from django.shortcuts import render

      def draw_view(request):
      “””
      Renders the drawing application’s main page.
      “””
      return render(request, ‘drawingapp/draw.html’)
      ``
      *
      render(request, ‘drawingapp/draw.html’): This function is a shortcut provided by Django. It takes the incomingrequest, loads the specified **template** (drawingapp/draw.html`), and returns it as an HTTP response. A template is essentially an HTML file that Django can fill with dynamic content.

    Crafting Your Template (HTML, CSS, and JavaScript)

    This is where the magic happens on the user’s browser! We’ll create an HTML file that contains our drawing canvas, some styling (CSS), and the JavaScript code to make the drawing interactive.

    1. Create the templates directory:
      Inside your drawingapp folder, create a new folder named templates. Inside templates, create another folder named drawingapp. This structure (drawingapp/templates/drawingapp/) is a common Django convention that helps keep your templates organized and prevents name clashes between different apps.

    2. Create drawingapp/templates/drawingapp/draw.html:
      Now, create a file named draw.html inside drawingapp/templates/drawingapp/ and paste the following code:

      “`html
      <!DOCTYPE html>




      Simple Drawing App