This is example code for a game I developed based loosely on Simon Says and similar electronic games. It uses an Arduino, four buttons, four LEDs, and a speaker, and is essentially a sequence memorization game. It will play a note and light an LED, after which the user presses the button associated with that note and LED in order to repeat the game’s sequence. The game adds another step so the sequence is two notes/LEDs long, and the user repeats that two step sequence. This continues, the game adding another step to the sequence, the user repeating the sequence, until either the user makes a mistake, or the user successfully plays the game to the point where the sequence is 30 steps long.
Simply cut and paste into your Arduino IDE to use.
/*
RepeatMe!
Author: Adam Davis
Contact: adavis@ubasics.com
Date: 2 June 2011
SETUP
This project requires one Arduino, four buttons, four LEDs, and one
speaker.
The LEDs are connected to pins 3, 9, 10, 11 and VCC (with a resistor)
The buttons are connected to pins 5, 6, 7, 8 and ground
The speaker is connected to pin 4 and ground
PLAY
When started, the game blinks and sings randomly. Any button press will
enter game mode.
In game mode the game simultaneously lights an LED and plays a note.
The player presses the button that is associated with that light and
note, then the game plays the note and lights the LED again, and then
another light and note in a two note/light sequence. The player then
copies the sequence by pressing the two buttons associated with the
lights and notes, and then the game adds another light/note to the
sequence which the player must again copy.
Game play continues with the game adding new steps to the sequence until
either the sequence is 30 steps long, or the player makes a mistake in
copying the sequence.
If the player succeeds in completing the full 30 step sequence, all LEDs
are lit briefly, then the game resets.
If the player makes a mistake, the game plays a low note, then resets.
When connected to the computer with a terminal at 9600bps game information
is displayed as the game is played.
IMPROVEMENTS
- Make a winning song for the game to play on winning
- Make losing more interesting - perhaps it gives you a second and third chance
- Make it explicitly four player - each player gets one button, they
have to play them in proper sequence, and when one person gets it
wrong they are out, however the game plays their part so the others
can continue play to find the winner - the last one remaining
- Add more game modes
- Make the sequence playback variable speed - as the sequence gets longer,
each step is played for a shorter time
- Remove the 30 sequence limit and see how high people can get. Keep a
maximum score to encourage people to beat the highest successful sequence
- Add some achievements or badges (Use serial port and computer software, or
LCD support to view and post about achievements on social networks)
- The LEDs are on PWM capable pins - use PWM to pulse them in a more pleasing
manner than the existing hard on and off
- The attraction mode the game starts up in could play more interesting
melodies and show more interesting LED patterns
- Could be used as a 4 key piano, or even record and play back the user's song
- Complex audio generation using a wavetable or sinewaves could produce
fun synthesizer or more interesting sounds. Add a microphone and play
the game with a recorded sound
LICENSE
This code is copyright 2011 Adam Davis, and is provided to the public as
a public domain work. You may use it in any way or for any purpose you
desire. If it makes things easier for you, feel free to consider this
work licensed under the BSD, Apache, MIT, or GNU license of your choice.
See http://opensource.org/licenses/category for more information on these
licenses.
This code is provided AS IS without warranties or conditions of any kind.
You are solely responsible for determining the appropriateness of use or
redistribution of this code or any derivative, and assume any risks.
*/
// Pin definitions
const static int led[4] = {3, 9, 10, 11};
const static int button[4] = {5, 6, 7, 8};
const static int spk = 4;
const static int pentatonic[5] = {262, 294, 330, 392, 440}; // C, D, E, A, G
int buttonpress;
// Game states
enum GameStates{START, ADD, REPEAT, QUIZ, WIN, LOSE};
int state;
int memory[31];
int count;
// Button and LED macros
#define btn(x) (!(digitalRead((button[(x)]))))
//#define ledpwm(x,y) (analogWrite((led[(x)]),(255-(y))))
#define led(x,y) (digitalWrite((led[(x)]),(!(y))))
int debounce(void);
int leds(int ledvalue);
void setup() {
// initialize the digital pin as an output.
// Pin 13 has an LED connected on most Arduino boards:
Serial.begin(9600);
pinMode(13, OUTPUT);
for(int index=0; index<4; index++)
{
pinMode(led[index], OUTPUT);
digitalWrite(led[index], HIGH);
pinMode(button[index], INPUT);
digitalWrite(button[index], HIGH); // Turn on the pull up resistors
}
pinMode(spk, OUTPUT);
randomSeed(analogRead(0));
state = START;
Serial.print("hi");
}
void loop() {
switch(state)
{
case START: // Attract mode
leds(random(16));
tone(spk, pentatonic[random(5)]);
delay(100);
if(debounce() > -1)
{
noTone(spk);
leds(0);
Serial.print(" Waiting for you to let go of button\n");
while(debounce() >= 0);
delay(500);
count = 0;
state = ADD;
}
break;
case ADD: // Add a new step to the existing sequence
Serial.print("Add\n");
memory[count] = random(4);
count++;
state = REPEAT;
break;
case REPEAT: // Play the current sequence
Serial.print("Repeat\n");
for(int index=0; index < count; index++)
{
tone(spk, pentatonic[memory[index]], 400);
leds(1<<memory[index]);
delay(400);
leds(0);
delay(100);
}
state = QUIZ;
break;
case QUIZ: // Quiz the user on the current sequence
Serial.print("Start quiz\n");
int answer;
state = ADD; // Default go to ADD
for(int index=0; index < count; index++)
{
Serial.print(" Wait for button\n");
while((answer = debounce()) < 0); // Wait for a button press
// Light the LED
led(answer, 1);
Serial.print(" Got button\n");
// If it's the right button play the tone, if not go to lose
if(answer == memory[index])
{
// Correct
Serial.print(" Correct\n");
tone(spk, pentatonic[answer]);
if(count >=31)
{
state = WIN;
}
}
else
{
// Incorrect
Serial.print(" Incorrect\n");
state = LOSE;
tone(spk, 60);
leds(15);
Serial.print(" Waiting for you to let go of button\n");
while(debounce() >= 0);
break; // Stop the for loop before it finishes
}
// wait for button to stop, then go to next tone
Serial.print(" Waiting for you to let go of button.\n");
while(debounce() >= 0);
leds(0);
noTone(spk);
}
delay(500);
break;
case WIN: // User won
Serial.print("Win\n");
leds(15);
delay(250);
leds(0);
delay(250);
break;
case LOSE: // User lost
Serial.print("Lose\n");
Serial.print(" Waiting for a new button press\n");
if(debounce() >= 0)
{
state = START;
}
break;
default: // Uh oh, something bad happened, reset game
Serial.print("Default\n");
state = START;
break;
}
}
// Check all four buttons. If a button is pressed, wait 30 mS then check again.
// If it's still pressed, return that button number as a successful button press.
int debounce(void)
{
int index;
for(index=0; index<4; index++)
{
if(btn(index))
{
delay(30);
if(btn(index))
{
return index;
}
}
}
return -1;
}
// Light the LEDs according to the first four bits in ledvalue.
int leds(int ledvalue)
{
led(0, ledvalue & 1);
led(1, ledvalue & 2);
led(2, ledvalue & 4);
led(3, ledvalue & 8);
}






Recent Comments