Simon Says Memory Game using Arduino Uno – Complete Guide with Code

 Project Overview

Simon Says Memory Game using Arduino Uno

Build an interactive Simon Says Memory Game using the popular Arduino Uno. This beginner-friendly electronics project improves memory skills while teaching LEDs, push buttons, buzzer tones, arrays, loops, and debouncing techniques.

The game generates a random LED sequence that the player must repeat correctly. Each round increases difficulty by adding one more step to the pattern.

You can build this on a breadboard or simulate it using the Wokwi platform.


Project Overview

This Simon Says game includes:

  • 4 Colored LEDs (Red, Green, Blue, Yellow)

  • 4 Push Buttons (one for each LED)

  •  Piezo Buzzer for sound feedback

  •  Increasing difficulty levels

  •  Speed progression system

  •  Button debouncing logic

  •  Musical tone feedback for each color


Components Required

  • Arduino Uno

  • 4 LEDs (Red, Green, Blue, Yellow)

  • 4 × 220Ω resistors (LED current limiting)

  • 4 Push Buttons

  • 10kΩ resistors (optional if not using INPUT_PULLUP)

  • Piezo Buzzer

  • Breadboard

  • Jumper wires


 Pin Configuration

ComponentArduino Pin
Red LED2
Green LED3
Blue LED4
Yellow LED5
Button 16
Button 27
Button 38
Button 49
Buzzer10

Buttons use INPUT_PULLUP, so external resistors are optional.


 How the Game Works

  1. Arduino generates a random LED sequence.

  2. LEDs blink one-by-one with sound.

  3. Player repeats the sequence using buttons.

  4. If correct → next round adds one more step.

  5. Every 5 rounds → level increases and speed increases.

  6. If wrong → game over sound plays and game resets.


 Game Logic Features

🔹 Random Sequence Generation

Uses:

sequence[sequenceLength] = random(0, 4);

Each number represents a color.


🔹 Speed Progression System

  • Initial delay: 500 ms

  • Speed reduces every 5 rounds

  • Minimum speed: 200 ms

This increases difficulty gradually.


🔹 Button Debouncing

Prevents false triggering using:

  • millis() timing

  • 50ms debounce delay

  • State comparison logic


🔹 Timeout System

If player doesn't respond within 5 seconds:

Timeout → Game Over

 Sound System

Each color has a musical tone:

ColorFrequencyNote
Red262 HzC
Green330 HzE
Blue392 HzG
Yellow494 HzB

Special sounds:

  •  Correct: 800 Hz short beeps

  •  Level Up: 659 Hz celebratory tone

  •  Game Over: 200 Hz low tone


 Learning Concepts

This project teaches:

  • Arrays in Arduino

  • Random number generation

  • Digital input & output

  • INPUT_PULLUP usage

  • Buzzer tone generation

  • Game loop structure

  • State management using Boolean flags

  • Debouncing using millis()

  • Progressive difficulty algorithm


 Wokwi Simulation

To simulate:

  1. Open Wokwi

  2. Create new Arduino Uno project

  3. Paste your provided diagram.json

  4. Upload the Arduino code

  5. Click Run ▶️

You’ll see LEDs blink in sequence and can press buttons to repeat.


 Possible Upgrades

You can extend this project with:

  •  16x2 LCD score display

  •  EEPROM high-score saving

  •  MP3 sound module

  •  RGB LED version

  •  Bluetooth control

  •  8-button advanced mode

  •  Multiplayer mode


 Final Result

You’ve built a complete interactive memory game using Arduino that includes:

  • Real-time input handling

  • Progressive game difficulty

  • Audio-visual feedback

  • Embedded system logic

This project is perfect for:

  •  School robotics labs

  •  Brain training games

  •  Beginner Arduino learners

  •  STEM workshops

Code:
/*
 * Simon Says Memory Game
 * 4 colored LEDs + buttons with sound feedback
 * Increasing difficulty levels
 *
 * Hardware connections:
 * - Red LED: Pin 2, Button: Pin 6
 * - Green LED: Pin 3, Button: Pin 7
 * - Blue LED: Pin 4, Button: Pin 8
 * - Yellow LED: Pin 5, Button: Pin 9
 * - Buzzer: Pin 10
 */

// Pin definitions
const int LED_PINS[] = {2, 3, 4, 5};        // Red, Green, Blue, Yellow LEDs
const int BUTTON_PINS[] = {6, 7, 8, 9};     // Corresponding buttons
const int BUZZER_PIN = 10;

// Tone frequencies for each color
const int TONES[] = {262, 330, 392, 494};   // C, E, G, B notes

// Game constants
const int MAX_SEQUENCE = 50;
const int INITIAL_SPEED = 500;
const int SPEED_DECREMENT = 20;
const int MIN_SPEED = 200;

// Game variables
int sequence[MAX_SEQUENCE];
int sequenceLength = 0;
int currentSpeed = INITIAL_SPEED;
int level = 1;
bool gameActive = false;

// Button debouncing
unsigned long lastDebounceTime[] = {0, 0, 0, 0};
const unsigned long debounceDelay = 50;
bool lastButtonState[] = {HIGH, HIGH, HIGH, HIGH};

void setup() {
  Serial.begin(9600);
 
  // Initialize LED pins as outputs
  for (int i = 0; i < 4; i++) {
    pinMode(LED_PINS[i], OUTPUT);
    digitalWrite(LED_PINS[i], LOW);
  }
 
  // Initialize button pins as inputs with pullup
  for (int i = 0; i < 4; i++) {
    pinMode(BUTTON_PINS[i], INPUT_PULLUP);
  }
 
  // Initialize buzzer
  pinMode(BUZZER_PIN, OUTPUT);
 
  // Seed random number generator
  randomSeed(analogRead(A0));
 
  // Welcome sequence
  welcomeAnimation();
 
  Serial.println("Simon Says Memory Game");
  Serial.println("Press any button to start!");
  Serial.println("==========================");
}

void loop() {
  if (!gameActive) {
    // Wait for any button press to start
    if (checkAnyButton()) {
      startNewGame();
    }
  } else {
    playRound();
  }
}

void welcomeAnimation() {
  // Flash all LEDs in sequence
  for (int repeat = 0; repeat < 2; repeat++) {
    for (int i = 0; i < 4; i++) {
      digitalWrite(LED_PINS[i], HIGH);
      tone(BUZZER_PIN, TONES[i], 150);
      delay(150);
      digitalWrite(LED_PINS[i], LOW);
      delay(50);
    }
  }
 
  // Flash all together
  for (int i = 0; i < 4; i++) {
    digitalWrite(LED_PINS[i], HIGH);
  }
  tone(BUZZER_PIN, 523, 300);
  delay(300);
  for (int i = 0; i < 4; i++) {
    digitalWrite(LED_PINS[i], LOW);
  }
  noTone(BUZZER_PIN);
  delay(500);
}

void startNewGame() {
  sequenceLength = 0;
  currentSpeed = INITIAL_SPEED;
  level = 1;
  gameActive = true;
 
  Serial.println("\n>>> NEW GAME STARTED <<<");
  Serial.println("Level 1");
  delay(1000);
}

void playRound() {
  // Add new color to sequence
  addToSequence();
 
  Serial.print("Round ");
  Serial.print(sequenceLength);
  Serial.print(" - Level ");
  Serial.println(level);
 
  // Show sequence to player
  delay(1000);
  playSequence();
 
  // Get player input
  if (getUserInput()) {
    // Correct! Celebrate and continue
    correctFeedback();
   
    // Increase difficulty every 5 rounds
    if (sequenceLength % 5 == 0) {
      level++;
      currentSpeed = max(MIN_SPEED, currentSpeed - SPEED_DECREMENT);
      Serial.print(">>> LEVEL UP! Now at Level ");
      Serial.println(level);
      levelUpAnimation();
    }
   
    delay(1500);
  } else {
    // Wrong! Game over
    gameOver();
  }
}

void addToSequence() {
  sequence[sequenceLength] = random(0, 4);
  sequenceLength++;
}

void playSequence() {
  for (int i = 0; i < sequenceLength; i++) {
    int color = sequence[i];
   
    // Light up LED and play tone
    digitalWrite(LED_PINS[color], HIGH);
    tone(BUZZER_PIN, TONES[color]);
    delay(currentSpeed);
   
    // Turn off
    digitalWrite(LED_PINS[color], LOW);
    noTone(BUZZER_PIN);
    delay(200);
  }
}

bool getUserInput() {
  for (int i = 0; i < sequenceLength; i++) {
    int expectedColor = sequence[i];
    int pressedButton = waitForButtonPress();
   
    if (pressedButton == -1) {
      return false; // Timeout
    }
   
    // Light up the pressed button
    digitalWrite(LED_PINS[pressedButton], HIGH);
    tone(BUZZER_PIN, TONES[pressedButton], 200);
    delay(200);
    digitalWrite(LED_PINS[pressedButton], LOW);
    noTone(BUZZER_PIN);
   
    if (pressedButton != expectedColor) {
      Serial.print("Wrong! Expected: ");
      Serial.print(getColorName(expectedColor));
      Serial.print(", Got: ");
      Serial.println(getColorName(pressedButton));
      return false;
    }
   
    delay(200);
  }
 
  return true;
}

int waitForButtonPress() {
  unsigned long startTime = millis();
  const unsigned long timeout = 5000; // 5 second timeout
 
  while (millis() - startTime < timeout) {
    for (int i = 0; i < 4; i++) {
      int reading = digitalRead(BUTTON_PINS[i]);
     
      if (reading != lastButtonState[i]) {
        lastDebounceTime[i] = millis();
      }
     
      if ((millis() - lastDebounceTime[i]) > debounceDelay) {
        if (reading == LOW) {
          // Button pressed
          while (digitalRead(BUTTON_PINS[i]) == LOW) {
            delay(10); // Wait for release
          }
          lastButtonState[i] = HIGH;
          return i;
        }
      }
     
      lastButtonState[i] = reading;
    }
  }
 
  Serial.println("Timeout!");
  return -1; // Timeout
}

bool checkAnyButton() {
  for (int i = 0; i < 4; i++) {
    if (digitalRead(BUTTON_PINS[i]) == LOW) {
      delay(300); // Debounce
      while (digitalRead(BUTTON_PINS[i]) == LOW) {
        delay(10);
      }
      return true;
    }
  }
  return false;
}

void correctFeedback() {
  Serial.println("✓ Correct!");
 
  // Quick success sound
  for (int i = 0; i < 3; i++) {
    tone(BUZZER_PIN, 800, 100);
    delay(150);
  }
  noTone(BUZZER_PIN);
}

void levelUpAnimation() {
  // Celebratory light show
  for (int repeat = 0; repeat < 3; repeat++) {
    for (int i = 0; i < 4; i++) {
      digitalWrite(LED_PINS[i], HIGH);
    }
    tone(BUZZER_PIN, 659, 200);
    delay(200);
   
    for (int i = 0; i < 4; i++) {
      digitalWrite(LED_PINS[i], LOW);
    }
    delay(100);
  }
  noTone(BUZZER_PIN);
}

void gameOver() {
  Serial.println("\n*** GAME OVER ***");
  Serial.print("Final Score: ");
  Serial.print(sequenceLength - 1);
  Serial.print(" (Level ");
  Serial.print(level);
  Serial.println(")");
 
  // Game over sound and animation
  for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 4; j++) {
      digitalWrite(LED_PINS[j], HIGH);
    }
    tone(BUZZER_PIN, 200, 300);
    delay(300);
   
    for (int j = 0; j < 4; j++) {
      digitalWrite(LED_PINS[j], LOW);
    }
    delay(200);
  }
  noTone(BUZZER_PIN);
 
  delay(1000);
  Serial.println("\nPress any button to play again!");
 
  gameActive = false;
}

String getColorName(int colorIndex) {
  switch(colorIndex) {
    case 0: return "Red";
    case 1: return "Green";
    case 2: return "Blue";
    case 3: return "Yellow";
    default: return "Unknown";
  }
}



How It Works

  1. Arduino generates a random LED sequence.

  2. LEDs blink one by one with sound.

  3. Player repeats the sequence by pressing buttons.

  4. If correct → next level adds one more step.

  5. If wrong → buzzer sounds and game resets.


 Pin Configuration

Diagram.json:
{
  "version": 1,
  "author": "Claude",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-uno", "id": "uno", "top": 0, "left": 0, "attrs": {} },
    {
      "type": "wokwi-led",
      "id": "led1",
      "top": -86.4,
      "left": -134.6,
      "attrs": { "color": "red" }
    },
    {
      "type": "wokwi-led",
      "id": "led2",
      "top": -86.4,
      "left": -48.2,
      "attrs": { "color": "green" }
    },
    {
      "type": "wokwi-led",
      "id": "led3",
      "top": -86.4,
      "left": 38.2,
      "attrs": { "color": "blue" }
    },
    {
      "type": "wokwi-led",
      "id": "led4",
      "top": -86.4,
      "left": 124.6,
      "attrs": { "color": "yellow" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r1",
      "top": -28.8,
      "left": -124.8,
      "attrs": { "value": "220" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r2",
      "top": -28.8,
      "left": -38.4,
      "attrs": { "value": "220" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r3",
      "top": -28.8,
      "left": 48,
      "attrs": { "value": "220" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r4",
      "top": -28.8,
      "left": 134.4,
      "attrs": { "value": "220" }
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn1",
      "top": 179,
      "left": -144,
      "attrs": { "color": "red" }
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn2",
      "top": 182.4,
      "left": -57.6,
      "attrs": { "color": "green" }
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn3",
      "top": 182.4,
      "left": 28.8,
      "attrs": { "color": "blue" }
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn4",
      "top": 182.4,
      "left": 115.2,
      "attrs": { "color": "yellow" }
    },
    { "type": "wokwi-buzzer", "id": "bz1", "top": 249.6, "left": 268.2, "attrs": {} }
  ],
  "connections": [
    [ "led1:A", "r1:1", "green", [ "v0" ] ],
    [ "r1:2", "uno:2", "green", [ "v0" ] ],
    [ "led1:C", "uno:GND.1", "black", [ "v0" ] ],
    [ "led2:A", "r2:1", "green", [ "v0" ] ],
    [ "r2:2", "uno:3", "green", [ "v0" ] ],
    [ "led2:C", "uno:GND.1", "black", [ "v0" ] ],
    [ "led3:A", "r3:1", "green", [ "v0" ] ],
    [ "r3:2", "uno:4", "green", [ "v0" ] ],
    [ "led3:C", "uno:GND.1", "black", [ "v0" ] ],
    [ "led4:A", "r4:1", "green", [ "v0" ] ],
    [ "r4:2", "uno:5", "green", [ "v0" ] ],
    [ "led4:C", "uno:GND.1", "black", [ "v0" ] ],
    [ "btn1:1.l", "uno:6", "blue", [ "v0" ] ],
    [ "btn1:2.l", "uno:GND.2", "black", [ "v0" ] ],
    [ "btn2:1.l", "uno:7", "blue", [ "v0" ] ],
    [ "btn2:2.l", "uno:GND.2", "black", [ "v0" ] ],
    [ "btn3:1.l", "uno:8", "blue", [ "v0" ] ],
    [ "btn3:2.l", "uno:GND.2", "black", [ "v0" ] ],
    [ "btn4:1.l", "uno:9", "blue", [ "v0" ] ],
    [ "btn4:2.l", "uno:GND.2", "black", [ "v0" ] ],
    [ "bz1:1", "uno:10", "green", [ "v0" ] ],
    [ "bz1:2", "uno:GND.3", "black", [ "v0" ] ]
  ],
  "dependencies": {}
}

Comments