Memory Sequence Game in Python

Project Overview

In this project, you’ll create a Simon Says-style memory game where players must remember and repeat sequences of colored patterns. This is perfect for creating an escape room puzzle that simulates cracking a high-tech security system!

What you’ll learn:

  • How to manage lists (arrays) to store sequences
  • Creating random sequences
  • Making visual animations with turtle graphics
  • Handling user keyboard input
  • Building progressive difficulty systems

Part 1: Setting Up Your Game Interface

Learning Goal

Before we can make a game, we need to create the visual elements that players will see and interact with. Think of this like setting up a stage before a play!

Example: Creating and Positioning Turtles

Let’s start by learning how to create and position turtle objects. Here’s a simple example that creates colored circles on the screen:

import turtle

# Create the screen (like creating a canvas to draw on)
screen = turtle.Screen()
screen.bgcolor("navy")  # Set background color
screen.setup(width=400, height=300)  # Set screen size

# Create our first turtle object
circle1 = turtle.Turtle()
circle1.shape("circle")  # Make it look like a circle
circle1.color("red")     # Make it red
circle1.penup()          # Don't draw lines when moving
circle1.goto(-50, 0)     # Move to position x=-50, y=0

# Create a second turtle object
circle2 = turtle.Turtle()
circle2.shape("circle")
circle2.color("blue")
circle2.penup()
circle2.goto(50, 0)      # Move to position x=50, y=0

# Keep the window open
screen.mainloop()

Key Concepts Explained:

  • turtle.Turtle() creates a new turtle object (like creating a new character)
  • .shape() changes what the turtle looks like
  • .color() changes the turtle’s color
  • .penup() means “don’t draw lines when moving”
  • .goto(x, y) moves the turtle to specific coordinates (x is left/right, y is up/down)
  • screen.mainloop() keeps the window open so you can see your creation

Your Task: Create the Memory Game Interface

Now it’s your turn! Create a memory game interface with:

  1. Four colored square buttons arranged in a 2×2 grid
  2. Text displays for showing messages to the player

Requirements:

  • Use "square" shape for your buttons
  • Colors should be: red, blue, green, yellow
  • Position the buttons like this: RED BLUE (−100,50) (100,50) GREEN YELLOW (−100,−50) (100,−50)

Starter Code Framework:

import turtle
import random

# Set up the screen
wn = turtle.Screen()
wn.bgcolor("black")
wn.setup(width=600, height=450)

# Create your button turtles here
# Remember: shape("square"), penup(), goto(x,y), color()

# Create text display turtles here
# Hint: Use hideturtle() to make text-only turtles invisible

wn.mainloop()

Challenge: Try creating a title turtle that displays “MEMORY SEQUENCE DEVICE” at the top of the screen!


Part 2: Working with Lists and Random Generation

Learning Goal

Games need to store and manage data. In our memory game, we need to create random sequences and store what the player inputs. Lists are perfect for this!

Example: Understanding Lists and Random Numbers

import random

# Creating and working with lists
my_colors = ["red", "blue", "green", "yellow"]
print("First color:", my_colors[0])    # Prints: red
print("Second color:", my_colors[1])   # Prints: blue
print("List length:", len(my_colors))  # Prints: 4

# Adding items to a list
sequence = []  # Start with empty list
sequence.append(2)    # Add the number 2
sequence.append(0)    # Add the number 0
print("My sequence:", sequence)  # Prints: [2, 0]

# Generating random numbers
for i in range(5):  # Do this 5 times
    random_num = random.randint(0, 3)  # Random number from 0 to 3
    print("Random number:", random_num)

# Creating a random sequence
random_sequence = []
for i in range(4):  # Create 4 random numbers
    random_button = random.randint(0, 3)
    random_sequence.append(random_button)
print("Random sequence:", random_sequence)

Key Concepts Explained:

  • Lists store multiple items: my_list = [item1, item2, item3]
  • Access items by position: my_list[0] gets the first item
  • len(my_list) tells you how many items are in the list
  • my_list.append(item) adds a new item to the end
  • random.randint(0, 3) gives you a random number from 0 to 3
  • for i in range(4): repeats something 4 times

Your Task: Create Sequence Management

Add these variables and functions to your memory game:

Required Variables:

# Game data storage
sequence = []           # Will store the pattern to remember
player_sequence = []    # Will store what player enters  
current_level = 1       # What level the player is on
button_colors = ["red", "blue", "green", "yellow"]

Required Function: Create a function that generates a new random sequence. The sequence should get longer as levels increase:

  • Level 1: 3 buttons
  • Level 2: 4 buttons
  • Level 3: 5 buttons
  • etc.

Function Template:

def generate_new_sequence():
    global sequence  # This lets us modify the sequence variable
    sequence = []    # Start with empty sequence
    
    # Calculate how long this sequence should be
    sequence_length = 2 + current_level
    
    # Your code here: create sequence_length random numbers (0-3)
    # and append them to the sequence list

Test Your Function:

# Test your function
current_level = 1
generate_new_sequence()
print("Level 1 sequence:", sequence)

current_level = 3  
generate_new_sequence()
print("Level 3 sequence:", sequence)

Part 3: Animation and Visual Feedback

Learning Goal

Games need to show players what’s happening! We’ll learn how to make buttons “light up” and create timed animations.

Example: Color Changes and Timing

import turtle

# Set up
screen = turtle.Screen()
screen.bgcolor("black")

# Create a button
button = turtle.Turtle()
button.shape("square")
button.penup()
button.goto(0, 0)
button.color("red")

# Function to make button flash
def flash_button():
    button.color("pink")      # Change to bright color
    screen.ontimer(reset_button, 500)  # Reset after 500ms (0.5 seconds)

def reset_button():
    button.color("red")       # Change back to normal color

# Function to demonstrate the flash
def start_demo():
    screen.ontimer(flash_button, 1000)  # Flash after 1 second

# Set up keyboard control
screen.listen()
screen.onkey(start_demo, "space")  # Press space to start demo

print("Press space to see the button flash!")
screen.mainloop()

Key Concepts Explained:

  • .color() instantly changes a turtle’s color
  • screen.ontimer(function, milliseconds) calls a function after a delay
  • 1000 milliseconds = 1 second, 500 milliseconds = 0.5 seconds
  • screen.listen() tells the program to watch for keyboard input
  • screen.onkey(function, "key") runs a function when a key is pressed

Example: Showing a Sequence Step by Step

# Example of showing items one at a time
demo_sequence = [0, 2, 1, 3]  # Example sequence
current_position = 0

def show_next_item():
    global current_position
    
    if current_position < len(demo_sequence):
        item = demo_sequence[current_position]
        print(f"Showing item {current_position}: {item}")
        current_position = current_position + 1
        
        # Show next item after 1 second
        screen.ontimer(show_next_item, 1000)
    else:
        print("Sequence finished!")
        current_position = 0  # Reset for next time

Your Task: Create Button Animation System

Add these functions to your memory game:

Required Functions:

  1. Button Lighting Functions:
def light_up_button(button_index):
    # Change button at button_index to its bright color
    # Hint: Use your button_turtles list and bright_colors list
    
def reset_button(button_index):  
    # Change button back to its normal color
    
def reset_all_buttons():
    # Reset all 4 buttons to normal colors
    # Hint: Use a for loop with range(4)

Sequence Display Functions:

def show_sequence():
    global sequence_position
    sequence_position = 0  # Start at beginning
    
    # Display message to player
    status.clear()
    status.write("Watch the sequence...", align="center", font=("Arial", 14, "normal"))
    
    show_sequence_step()  # Start showing the sequence

def show_sequence_step():
    global sequence_position
    
    if sequence_position < len(sequence):
        # Light up the current button in the sequence
        button_index = sequence[sequence_position]
        light_up_button(button_index)
        
        sequence_position = sequence_position + 1
        wn.ontimer(reset_and_continue, 800)  # Reset after 0.8 seconds
    else:
        # Sequence finished - start player input
        start_player_input()

def reset_and_continue():
    # Reset the previous button and continue with next
    if sequence_position > 0:
        prev_button = sequence[sequence_position - 1] 
        reset_button(prev_button)
    
    wn.ontimer(show_sequence_step, 400)  # Next button after 0.4 seconds

Challenge: Create bright color versions of your button colors and store them in a bright_colors list!


Part 4: Handling Player Input

Learning Goal

Now we need to detect when players press keys and check if they’re repeating the sequence correctly.

Example: Keyboard Input and Checking Lists

import turtle

# Set up
screen = turtle.Screen()
player_answer = []  # Store what player types
correct_answer = [1, 3, 2, 0]  # What they should type

def key_pressed(number):
    player_answer.append(number)
    print(f"You pressed: {number}")
    print(f"Your sequence so far: {player_answer}")
    
    # Check if they've entered enough numbers
    if len(player_answer) == len(correct_answer):
        check_answer()

def check_answer():
    print("\nChecking your answer...")
    
    # Compare the two lists
    if player_answer == correct_answer:
        print("Correct! Well done!")
    else:
        print("Incorrect. Try again!")
        player_answer.clear()  # Empty the list to start over

# Set up keyboard controls
def press_1():
    key_pressed(1)
    
def press_2():
    key_pressed(2)
    
def press_3():  
    key_pressed(3)
    
def press_4():
    key_pressed(4)

screen.listen()
screen.onkey(press_1, "1")
screen.onkey(press_2, "2") 
screen.onkey(press_3, "3")
screen.onkey(press_4, "4")

print("Press keys 1, 2, 3, 4 to enter sequence: [1, 3, 2, 0]")
screen.mainloop()

Key Concepts Explained:

  • list.clear() empties a list completely
  • list1 == list2 checks if two lists contain exactly the same items
  • We create separate functions for each key to avoid advanced programming concepts
  • Each key press adds a number to our tracking list

Example: Checking Input Step by Step

# Instead of waiting for complete sequence, check each step
def check_step_by_step(player_input):
    current_position = len(player_input) - 1  # Position of newest input
    
    if player_input[current_position] == correct_answer[current_position]:
        print(f"Step {current_position + 1} correct!")
        
        # Check if sequence is complete
        if len(player_input) == len(correct_answer):
            print("Entire sequence correct!")
    else:
        print("Wrong! Starting over...")
        player_input.clear()

Your Task: Add Player Input System

Add these components to your memory game:

Required Variables:

game_state = "waiting"  # Can be "waiting", "showing", "input", "complete"

Required Functions:

  1. Input Management:
def start_player_input():
    global game_state, player_sequence
    game_state = "input"
    player_sequence = []  # Clear previous attempts
    
    # Show instructions to player
    status.clear()
    status.write("Repeat the sequence! Press 1,2,3,4 for buttons", 
                align="center", font=("Arial", 12, "normal"))

def player_press_button(button_number):
    global player_sequence
    
    if game_state == "input":  # Only accept input during input phase
        # Add button to player's sequence
        player_sequence.append(button_number)
        
        # Light up the button they pressed
        light_up_button(button_number)
        wn.ontimer(reset_pressed_button, 300)
        
        # Check their progress
        check_player_input()

Input Checking:

def check_player_input():
    # Check if current input is correct so far
    current_pos = len(player_sequence) - 1
    
    if player_sequence[current_pos] == sequence[current_pos]:
        # Correct so far!
        if len(player_sequence) == len(sequence):
            # Complete sequence correct!
            level_completed()
    else:
        # Wrong button pressed
        sequence_failed()

def reset_pressed_button():
    # Reset the last button the player pressed
    if len(player_sequence) > 0:
        last_button = player_sequence[-1]  # -1 gets the last item
        reset_button(last_button)

Keyboard Setup:

# Create separate functions for each key (required for Trinket)
def press_button_1():
    player_press_button(0)  # Button 0 = red button

def press_button_2():
    player_press_button(1)  # Button 1 = blue button
    
def press_button_3():
    player_press_button(2)  # Button 2 = green button
    
def press_button_4():
    player_press_button(3)  # Button 3 = yellow button

# Set up keyboard controls
wn.listen()
wn.onkey(press_button_1, "1")
wn.onkey(press_button_2, "2")
wn.onkey(press_button_3, "3") 
wn.onkey(press_button_4, "4")

Part 5: Game Logic and Level Progression

Learning Goal

Now we’ll add the “game” part – handling success, failure, and moving between levels!

Example: Simple Win/Lose Logic

import turtle

# Set up
screen = turtle.Screen()
message = turtle.Turtle()
message.hideturtle()
message.penup()
message.goto(0, 0)

score = 0
lives = 3

def player_wins():
    global score
    score = score + 1
    message.clear()
    message.color("green")
    message.write(f"Success! Score: {score}", align="center", font=("Arial", 16, "bold"))

def player_loses():
    global lives
    lives = lives - 1
    message.clear()
    
    if lives > 0:
        message.color("red") 
        message.write(f"Try again! Lives left: {lives}", align="center", font=("Arial", 16, "normal"))
    else:
        message.color("red")
        message.write("Game Over!", align="center", font=("Arial", 20, "bold"))

def reset_game():
    global score, lives
    score = 0
    lives = 3
    message.clear()
    message.color("white")
    message.write("Game Reset - Press 'w' to win, 'l' to lose", align="center", font=("Arial", 12, "normal"))

# Test controls
screen.listen()
screen.onkey(player_wins, "w")
screen.onkey(player_loses, "l") 
screen.onkey(reset_game, "r")

reset_game()
screen.mainloop()

Key Concepts Explained:

  • Global variables let functions modify values that persist between function calls
  • We can change text color with .color() before writing
  • .clear() erases previous text before showing new text

Example: Level Progression System

current_level = 1
max_levels = 5

def advance_level():
    global current_level
    
    if current_level < max_levels:
        current_level = current_level + 1
        print(f"Advancing to level {current_level}")
        start_level()  # Start the new level
    else:
        print("You won the entire game!")
        game_complete()

def start_level():
    print(f"Starting level {current_level}")
    print(f"This level will have {2 + current_level} items to remember")
    
def game_complete():
    print("Congratulations! You've mastered the memory sequence!")

Your Task: Complete the Game Logic

Add these final functions to complete your memory game:

Required Functions:

  1. Success Handling:
def level_completed():
    global current_level
    
    # Show success message
    status.clear()
    status.color("green")
    level_text = "Level " + str(current_level) + " Complete!"
    status.write(level_text, align="center", font=("Arial", 16, "bold"))
    
    # Advance to next level
    current_level = current_level + 1
    
    if current_level > max_levels:
        device_unlocked()  # Game completed!
    else:
        wn.ontimer(start_next_level, 2000)  # Next level after 2 seconds

Failure Handling:

def sequence_failed():
    global game_state
    game_state = "waiting"
    
    # Show failure message
    status.clear()
    status.color("red")
    status.write("Wrong sequence! Try again...", 
                align="center", font=("Arial", 14, "normal"))
    
    # Flash all buttons red to show failure
    for button in button_turtles:
        button.color("red")
    
    wn.ontimer(reset_after_failure, 1000)

def reset_after_failure():
    reset_all_buttons()
    wn.ontimer(restart_level, 1000)

def restart_level():
    # Restart the current level
    status.clear()
    status.color("cyan")
    level_text = "Level " + str(current_level) + " - Get ready!"
    status.write(level_text, align="center", font=("Arial", 12, "normal"))
    wn.ontimer(show_sequence, 1500)
  1. Game Completion:
def device_unlocked():
    global game_state
    game_state = "complete"
    
    # Clear old messages
    status.clear()
    instructions.clear()
    
    # Show victory message
    title.clear()
    title.color("gold")
    title.write("DEVICE UNLOCKED!", align="center", font=("Arial", 24, "bold"))
    title.goto(0, 120)
    title.write("Access Granted to Secure System", align="center", font=("Arial", 14, "normal"))
    
    # Light up all buttons in victory colors
    for i in range(4):
        button_turtles[i].color(bright_colors[i])

Game Initialization:

def start_game():
    global current_level, game_state
    current_level = 1
    game_state = "waiting"
    
    title.clear()
    title.write("MEMORY SEQUENCE DEVICE", align="center", font=("Arial", 16, "bold"))
    
    generate_new_sequence()
    wn.ontimer(show_sequence, 1000)

def start_next_level():
    status.clear()
    status.color("cyan")
    level_text = "Level " + str(current_level) + " - Get ready!"
    status.write(level_text, align="center", font=("Arial", 12, "normal"))
    
    generate_new_sequence()
    wn.ontimer(show_sequence, 1500)

# Add space bar to start game
wn.onkey(start_game, "space")

Final Assembly and Testing

Your Complete Game Structure

By now, you should have all these components:

  1. Visual Interface: 4 colored buttons and text displays
  2. Data Management: Lists to store sequences and track progress
  3. Animation System: Functions to light up buttons and show sequences
  4. Input System: Keyboard controls and input validation
  5. Game Logic: Level progression, win/lose conditions

Initial Display Setup

Add this at the end of your code (before wn.mainloop()):

# Set up initial display
title.write("SECURITY PROTOCOL ACTIVE", align="center", font=("Arial", 18, "bold"))
title.goto(0, 120)
title.write("Memory Sequence Required for Access", align="center", font=("Arial", 12, "normal"))

instructions.write("Press SPACE to start | Use keys 1,2,3,4 for buttons", 
                  align="center", font=("Arial", 10, "normal"))
status.write("Security Protocol Ready", align="center", font=("Arial", 12, "normal"))

Testing Your Game

  1. Run your code – you should see the interface
  2. Press SPACE – the game should start and show a sequence
  3. Watch the sequence – buttons should light up one by one
  4. Press 1,2,3,4 to repeat the sequence
  5. Complete levels – the game should get progressively harder
  6. Test failure – deliberately press wrong buttons to test error handling

Troubleshooting Tips

If buttons don’t light up:

  • Check that your button_turtles list contains all 4 button objects
  • Verify your bright_colors list has 4 colors
  • Make sure light_up_button() uses the correct index

If sequences don’t generate:

  • Test your generate_new_sequence() function with print statements
  • Check that you’re using global sequence in the function

If keyboard input doesn’t work:

  • Ensure you have wn.listen() before setting up key bindings
  • Check that your button press functions call player_press_button() with correct numbers (0-3)

If timing feels wrong:

  • Adjust the numbers in wn.ontimer() calls (values are in milliseconds)
  • 1000 = 1 second, 500 = 0.5 seconds