Skip to content

Instantly share code, notes, and snippets.

@Elbow-Room
Created May 17, 2013 00:31
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Elbow-Room/5596179 to your computer and use it in GitHub Desktop.
Save Elbow-Room/5596179 to your computer and use it in GitHub Desktop.
A simple Simon Says game to run on Arduino
/* Author: Elbow-Room
* Purpose: To run the classic game "Simon" on arduino using random sequences and a maximum of 100 turns
*
* HARDWARE SETUP:
* Connect lights to digital ports 10 through 13
* Connect buttons to digital ports 2 through 5
* Connect Piezo to digital port 7 and switch to digital port 9
*/
/* Game related constants */
#define BUTTON_0 2
#define BUTTON_1 3
#define BUTTON_2 4
#define BUTTON_3 5
#define GREEN_LED 10
#define RED_LED 11
#define YELLOW_LED 12
#define BLUE_LED 13
#define PIEZO 7
#define PIEZO_SWITCH 9
static int pitches [] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 262, 294, 330, 349};
/* General constants */
#define TRUE 1
#define FALSE 0
#define CORRECT 1
#define INCORRECT 0
/* Time constants */
#define ONE_SEC 1000
#define HALF_SEC 500
#define QUART_SEC 250
/* Generates a random number then flashes the 4 lights in an order dictated by the array of random numbers
* Parameter - sequence: The array which stores the sequence of lights to be flashed
* Parameter - roundnum: The round number which is also the number of lights to read from the array
*/
void flash_lights (int sequence [], int roundnum);
/* Reads the order of buttons pressed and stores them in an array
* Parameter - input: the array which stores the order of the buttons pressed
* Parameter - roundnum: The round number which is also the number of buttons to read and store in the array
*/
void get_input (int input [], int roundnum);
/* Compares the light sequence with the buttons pressed and returns the state of "Correct" or "Incorrect"
* Parameter - sequence: The sequence of lights
* Parameter - input: The sequence of button presses
* Parameter - roundnum: The round number which is also the number of entries to be compared in each array
* Return: Whether the user entered a correct or incorrect sequence of button pushes
*/
int check_input (int sequence [], int input [], int roundnum);
/* Determines what to do in the next round based on the Correct or Incorrect state of the user's input. Whether to add a light to the
* sequence, award a win and restart, or give a lose signal and restart
* Parameter - status: The "Correct" or "Incorrect" status of the user's entered button sequence
* Parameter - roundnum: The current round number
* Return: The new round number
*/
int next_round (int status, int roundnum);
void setup ()
{
pinMode (2, INPUT);
pinMode (3, INPUT);
pinMode (4, INPUT);
pinMode (5, INPUT);
pinMode (7, OUTPUT);
pinMode (9, INPUT);
pinMode (10, OUTPUT);
pinMode (11, OUTPUT);
pinMode (12, OUTPUT);
pinMode (13, OUTPUT);
randomSeed (analogRead(0));
}
int roundnum = 1; /* The current round number, number of lights to flash, number of buttons to read */
int sequence [100]; /* The sequence of lights to flash in each round */
int input [100]; /* The sequence of buttons that the user presses */
int state; /* Whether the user's button entries are correct or incorrect */
/* Run one round of outputs and inputs then determine how many outputs and inputs to use in the next round */
void loop()
{
flash_lights(sequence, roundnum);
get_input(input, roundnum);
state = check_input(sequence, input, roundnum);
roundnum = next_round(state, roundnum);
}
/* End of main program, start of functions */
void flash_lights (int sequence [], int roundnum)
{
int count;
/* Generates a random number and assigns it to the round's position in the sequence array */
sequence [roundnum-1] = random(10, 14);
/* Flashes the lights as dictated by the array and the round number */
for (count = 0; count < roundnum; count++)
{
delay (QUART_SEC);
digitalWrite (sequence [count], HIGH);
tone (PIEZO, pitches [sequence [count]], QUART_SEC);
delay (QUART_SEC);
digitalWrite (sequence [count], LOW);
}
}
void get_input (int input [], int roundnum)
{
int count;
int i0;
int i1;
int i2;
int i3;
/* Loops until the number of buttons pressed matches the round number */
for (count = 0; count < roundnum; count++)
{
/* Read from buttons and stores their statuses in variables until a button is pressed */
do
{
i0 = digitalRead (BUTTON_0);
i1 = digitalRead (BUTTON_1);
i2 = digitalRead (BUTTON_2);
i3 = digitalRead (BUTTON_3);
}while (i0 == LOW && i1 == LOW && i2 == LOW && i3 == LOW);
/* Assigns the value of the button pressed to the round number's psoition in the input array */
if (i0 == HIGH)
input [count] = 10;
else if (i1 == HIGH)
input [count] = 11;
else if (i2 == HIGH)
input [count] = 12;
else if (i3 == HIGH)
input [count] = 13;
/* Turns on the light corresponding to the button being pressed */
digitalWrite (input[count], HIGH);
if (digitalRead (PIEZO_SWITCH) == HIGH)
tone (PIEZO, pitches [input [count]]);
/* delay to avoid multiple reads from button bouncing */
delay (200);
/* Ensures that the pressed button is released before carrying on (avoids reading multiple times if the button is held) */
do
{
i0 = digitalRead (BUTTON_0);
i1 = digitalRead (BUTTON_1);
i2 = digitalRead (BUTTON_2);
i3 = digitalRead (BUTTON_3);
}while (i0 == HIGH || i1 == HIGH || i2 == HIGH || i3 == HIGH);
/* Turns off the light of the button that was just released */
digitalWrite (input[count], LOW);
noTone(PIEZO);
}
}
int check_input (int sequence [], int input [], int roundnum)
{
int count = 0;
int test = CORRECT;
/* Compares the individual entries in the sequence and input arrays and assigns the value of INCORRECT to the test variable if the values
* in the arrays do not match
* Loop breaks when all values relevant to the round have been read or when the entries in the arrays do not match
*/
while (count < roundnum && test == CORRECT)
{
if (sequence[count] != input[count])
test = INCORRECT;
count++;
}
/* Returns whether or not the input array matches the output array up the round numbe's position */
return test;
}
int next_round (int state, int roundnum)
{
int newround;
int i;
/* If user has entered correct buttons but has not yet completed the entire game, adds one output/input to the next round of play */
if (state == CORRECT && roundnum < 100)
{
newround = roundnum + 1;
tone (PIEZO, 440);
delay (QUART_SEC);
tone (PIEZO, 880, 250);
delay (QUART_SEC);
}
/* If user has successfully responded up to the maximum number of rounds, flashes the green light three times and assigns
* a value to newround in order to start a new game
*/
else if (state == CORRECT && roundnum == 100)
{
delay (HALF_SEC);
for (i = 0; i < 3; i++)
{
digitalWrite (GREEN_LED, HIGH);
delay (HALF_SEC);
digitalWrite(GREEN_LED, LOW);
delay (QUART_SEC);
}
newround = 1;
}
/* If input buttons are wrong, flashes red light three times and assigns a value to newround in order to restart the game */
else if (state == INCORRECT)
{
delay (HALF_SEC);
for (i = 0; i < 3; i++)
{
digitalWrite (RED_LED, HIGH);
tone (PIEZO, 200);
delay (HALF_SEC);
digitalWrite (RED_LED, LOW);
noTone(PIEZO);
delay (HALF_SEC);
}
newround = 1;
}
/* Pauses momentarily and returns the number of inputs/outputs to use in the next round of play */
delay (HALF_SEC);
return newround;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment