Mini Simon Game

Another fun little project to practice my soldering skills and become more familiar with the Arduino.

Parts list:

  • Arduino Uno (SparkFun)
  • 4 push buttons (SparkFun)
  • Red/Green/Blue/Yellow LEDs (SparkFun or RadioShack)
  • PC Board Piezo Buzzer (SparkFun or RadioShack)
  • 4x 330 ohm resistors
  • 4x 10k ohm resistors
  • wire
  • PC board (I really like these)¬†or breadboard

Schematic

The buttons are wired to pins 5-8 with one node connected to +5V and the other to ground via a 10k ohm pull-down resistor. The LEDs to pins 10-13, with 330 ohm current limiting resistor. The piezo buzzer is connected directly to pin 9 and ground. For the wires going to the Arduino pins, I just wired one end to the board and left the other end hanging, so it is not permanently attached to the Arduino.

Code

For more information about working with the piezo buzzer and an Arduino, check out CIRC06 at ardx.org

// Whether we're in "listen" or "playback" mode
boolean listen;

// Change this value to increase or decrease the number of rounds
// played before winning the game
const int num_rounds = 9;

const int speakerPin = 9;
// "A" note frequency
const int a = 1136;
// how long to play a note
const int timestep = 500;

char buttons[] =   { 'y', 'b', 'r', 'g' };
int button_pins[] = { 5,   6,   7,   8 };
int led_pins[] =    { 10,  11,  12,  13 };
// The frequency of all other notes is based off the "A" note
// See: http://en.wikipedia.org/wiki/Simon_(game)#Gameplay
int notes[] = { a * 1.25 * 1.25,
a * 1.25,
a,
a * 0.75
};
// The note we play for failure
const int fail_note = a * 4;

// an array of the buttons for this game
int play_buttons[num_rounds];

// which round are we currently playing?
int currentRound;
// what button are we on for the current round
int current_button;

// Set up the LEDs and buzzer as output,
// and the buttons as input
void setup() {
pinMode(speakerPin, OUTPUT);
for (int i=0; i<4; i++) {
pinMode(button_pins[i], INPUT);
pinMode(led_pins[i], OUTPUT);
}

initialize();
}

void loop() {
if (listen) {
int buttonPress = readButtons();

// Check whether a button was pressed
if (buttonPress != -1) {

// make the button sound and light up the LED, to provide feedback
playButton(buttonPress, timestep/2);

// They hit the appropriate button
if (buttonPress == play_buttons[current_button]) {
delay(timestep);

// They just played the final button for the final round
if (current_button == num_rounds) {
win();
return;
}

// They just played the final button for this round
// Reset the round and switch to "playback" mode
if (current_button == currentRound) {
current_button = 0;
currentRound++;
listen = false;
return;
}

// They're still in the middle of this round
// Increment the current button and wait for next input
current_button++;
} else {  // they didn't hit the correct button!
fail();
return;
}
} // end listen
} else { // play all buttons for the round
if (currentRound == num_rounds) {
win();
return;
} else {
// playback all the buttons for this round
for (int i=0; i<=currentRound; i++) {
playButton(play_buttons[i]);
delay(timestep/2);
}
// switch to "listen" mode
listen = true;
}
}
}

// During initialization, randomly choose arrays of buttons
// for each round, then play a button pattern to let the user know
// that the game has been loaded
void initialize() {
delay(timestep*2);

randomSeed(analogRead(0));
for (int i=0; i<num_rounds; i++) {
play_buttons[i] = (int)random(0, 4);
}
listen = false;
currentRound = 0;
current_button = 0;

spin_colors();
spin_colors();

delay(timestep*2);
}

// Play the "failure" tone and restart the game
void fail() {
playTone(fail_note, timestep * 4);
delay(timestep*2);
initialize();
}

// Play the "win" button pattern and restart the game
void win() {
for (int i=0; i<4; i++) {
spin_colors();
}
delay(timestep*2);
initialize();
}

void spin_colors() {
for (int i=0; i<4; i++) {
playButton(i, timestep/4);
delay(timestep/4);
}
}

void playButton(int color) {
playButton(color, timestep);
}

// Turn on the LED and play the button's tone
void playButton(int color, int duration) {
digitalWrite(led_pins[color], HIGH);
playTone(notes[color], duration);
digitalWrite(led_pins[color], LOW);
}

// Play the buzzer at the tone's frequency
void playTone(int tone, int duration) {
for (long i = 0; i < duration * 1000L; i += tone * 2) {
digitalWrite(speakerPin, HIGH);
delayMicroseconds(tone);
digitalWrite(speakerPin, LOW);
delayMicroseconds(tone);
}
}

// Iterate over all the buttons and check if one was pressed
int readButtons() {
for (int i=0; i<4; i++) {
if (digitalRead(button_pins[i]) == HIGH) {
return i;
}
}
return -1;
}

Video

2 thoughts on “Mini Simon Game”

Leave a Reply

Your email address will not be published. Required fields are marked *