IntermediateArduinoArduino UnoGameLED

Simon Says Memory Game with Arduino Uno

Build the classic Simon Says memory game with Arduino Uno, four coloured LEDs, four push buttons, and a passive buzzer. Covers random seed with ADC noise, tone frequencies, game-over logic, and EEPROM high-score storage.

Circuit Hub24 min read2 views

How Simon Works

The game generates a random sequence of colour flashes, one longer each round. After each display the player must reproduce the exact sequence by pressing the matching buttons. One wrong press ends the game — the board shows your score and compares it to the stored high score in EEPROM.

The classic difficulty curve:

  • Level 1–4: 600 ms flash, 100 ms gap
  • Level 5–9: 400 ms flash, 80 ms gap
  • Level 10+: 250 ms flash, 60 ms gap

Components required

Arduino Uno R3
×1Buy
Red LED (5 mm)
×1
Green LED (5 mm)
×1
Blue LED (5 mm)
×1
Yellow LED (5 mm)
×1
Tactile Push Button (6 mm)
×4
220 Ω Resistors (for LEDs)
×4
10 kΩ Resistors (pull-down for buttons)
×4
5V Passive Buzzer
×1
Breadboard + Jumper Wires
×1

Pin Mapping

| Colour | LED Pin | Button Pin | Tone (Hz) | |--------|---------|------------|-----------| | Red | D5 | D9 | 262 (C4) | | Green | D6 | D10 | 330 (E4) | | Blue | D7 | D11 | 392 (G4) | | Yellow | D8 | D12 | 523 (C5) |

Passive buzzer positive → D4.

C++
// ── Simon Says — Arduino Uno ──────────────────────────────────────────────────
#include <EEPROM.h>

// ── Pin tables ────────────────────────────────────────────────────────────────
const int LED_PINS[]    = {5, 6, 7, 8};
const int BTN_PINS[]    = {9, 10, 11, 12};
const int TONES[]       = {262, 330, 392, 523};
const int BUZZER        = 4;
const int NUM_COLOURS   = 4;

// ── Game state ────────────────────────────────────────────────────────────────
int  sequence[100];
int  level = 0;
const int EEPROM_ADDR = 0;  // High score stored here

// ── Helpers ───────────────────────────────────────────────────────────────────
void lightUp(int colour, int ms) {
  digitalWrite(LED_PINS[colour], HIGH);
  tone(BUZZER, TONES[colour], ms);
  delay(ms);
  digitalWrite(LED_PINS[colour], LOW);
  noTone(BUZZER);
}

void gameOverEffect() {
  for (int i = 0; i < 3; i++) {
    for (int c = 0; c < NUM_COLOURS; c++) digitalWrite(LED_PINS[c], HIGH);
    tone(BUZZER, 150, 200);
    delay(200);
    for (int c = 0; c < NUM_COLOURS; c++) digitalWrite(LED_PINS[c], LOW);
    delay(200);
  }
}

int  waitForButton(unsigned long timeoutMs) {
  unsigned long start = millis();
  while (millis() - start < timeoutMs) {
    for (int i = 0; i < NUM_COLOURS; i++) {
      if (digitalRead(BTN_PINS[i]) == HIGH) {
        while (digitalRead(BTN_PINS[i]) == HIGH); // wait release
        return i;
      }
    }
  }
  return -1;  // timeout
}

void setup() {
  // Seed from floating ADC pin for true randomness
  randomSeed(analogRead(A0) * analogRead(A1));

  for (int i = 0; i < NUM_COLOURS; i++) {
    pinMode(LED_PINS[i], OUTPUT);
    pinMode(BTN_PINS[i], INPUT);
  }
  pinMode(BUZZER, OUTPUT);
  Serial.begin(9600);

  // Startup animation
  for (int i = 0; i < NUM_COLOURS; i++) { lightUp(i, 150); delay(50); }
}

void loop() {
  level = 0;

  // ── Build and play the sequence ───────────────────────────────────────────
  while (true) {
    sequence[level] = random(NUM_COLOURS);
    level++;

    // Speed curve
    int flashMs = (level <= 4) ? 600 : (level <= 9) ? 400 : 250;
    int gapMs   = (level <= 4) ? 100 : (level <= 9) ?  80 :  60;

    delay(600);
    for (int i = 0; i < level; i++) {
      lightUp(sequence[i], flashMs);
      delay(gapMs);
    }

    // ── Player input ──────────────────────────────────────────────────────
    for (int i = 0; i < level; i++) {
      int pressed = waitForButton(4000);
      if (pressed == -1 || pressed != sequence[i]) {
        // Wrong or timeout → game over
        Serial.print("Game over at level: ");
        Serial.println(level);
        gameOverEffect();

        int hiScore = EEPROM.read(EEPROM_ADDR);
        if (level > hiScore) {
          EEPROM.write(EEPROM_ADDR, level);
          Serial.println("New high score!");
          // Celebrate
          for (int c = 0; c < NUM_COLOURS; c++) { lightUp(c, 200); }
        }
        return;  // Restart
      }
      lightUp(pressed, 200);
      delay(80);
    }
    Serial.print("Level cleared: ");
    Serial.println(level);
  }
}

Live simulation

Related projects