Simon Game

So I have FINALLY completely finalized the game. I went through the process of ordering a dual 7 segment display and a bunch of 74HC595 shift registers to get a turn/high score display programmed in. So here is the final prototyping stage of the project:

I'll post the code later after I get home from work. This is going to be a pain to hardwire/solder... I'm thinking about attempting some homemade, acid etched PCBs.... hmmm. :-/

Great job!

Please make sure you show us the result once you get the project hard wired and packaged.

Thanks again for sharing. I've learnt a lot from examining your code.

Sorry, totally forgot to post the code. As requested:

/*Simon Says game by Robert Spann*/
#include <EEPROM.h>

//Pin connected to ST_CP of 74HC595
int latchPin = 7;
//Pin connected to SH_CP of 74HC595
int clockPin = 8;
////Pin connected to DS of 74HC595
int dataPin = 6;

int switch1 = 5; //The four button input pins
int switch2 = 4;
int switch3 = 3;
int switch4 = 2;
int led1 = 9; //LED pins
int led2 = 10;
int led3 = 11;
int led4 = 12;
int turn = 0;
int speakerPin = 13;
int intro = -1;
int input1 = LOW;
int input2 = LOW;
int input3 = LOW;
int input4 = LOW;
int tenDisp;
int oneDisp;
int highTen;
int highOne;

byte dataOne; //Shift Register Stuff
byte dataTwo;
byte dataArrayOne[12];
byte dataArrayTwo[12];



int randomArray[100]; //Intentionally long to store up to 100 inputs (doubtful anyone will get this far)
int inputArray[100];


void setup() {

  Serial.begin(9600); 

  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(switch1, INPUT);
  pinMode(switch2, INPUT);
  pinMode(switch3, INPUT);
  pinMode(switch4, INPUT);
  pinMode(speakerPin, OUTPUT);
  randomSeed(analogRead(0)); //Added to generate "more randomness" with the randomArray for the output function
  pinMode(latchPin, OUTPUT); //Shift register output pin

  dataArrayOne[0] = B11111100; //7 segment number values for shift register 1
  dataArrayOne[1] = B01100000;
  dataArrayOne[2] = B11011010;
  dataArrayOne[3] = B11110010;
  dataArrayOne[4] = B01100110;
  dataArrayOne[5] = B10110110;
  dataArrayOne[6] = B10111110;
  dataArrayOne[7] = B11100000;
  dataArrayOne[8] = B11111110;
  dataArrayOne[9] = B11100110;
  dataArrayOne[10] = B01101110;
  dataArrayOne[11] = B11101110;

  dataArrayTwo[0] = B11111100; //7 segment number values for shift register 2
  dataArrayTwo[1] = B01100000;
  dataArrayTwo[2] = B11011010;
  dataArrayTwo[3] = B11110010;
  dataArrayTwo[4] = B01100110;
  dataArrayTwo[5] = B10110110;
  dataArrayTwo[6] = B10111110;
  dataArrayTwo[7] = B11100000;
  dataArrayTwo[8] = B11111110;
  dataArrayTwo[9] = B11100110;
  dataArrayTwo[10] = B01101110;
  dataArrayTwo[11] = B11101110;

  //EEPROM.write(1, 0);
  int value = EEPROM.read(1);
  highScore(value);
  warHymn();
  delay(1000);



  for (int y=0; y<=1000; y++){ //For statement to loop through the output and input functions

    output();
    input();
  }
}

void output() { //function for generating the array to be matched by the player

  scoreDisplay(turn);
  for (int y=turn; y <= turn; y++){ //Limited by the turn variable
    //Some serial output to follow along
    Serial.print("Turn: ");
    Serial.print(y + 1);
    Serial.println("");
    randomArray[y] = random(1, 5); //Assigning a random number (1-4) to the randomArray[y], y being the turn count
    for (int x=0; x <= turn; x++){ 

      Serial.print(randomArray[x]);

      if (randomArray[x] == 1) {  //if statements to display the stored values in the array
        digitalWrite(led1, HIGH);
        playTone(1915, 200); //Passes tone value and duration of the tone to the playTone function
        delay(200);
        digitalWrite(led1, LOW);
        delay(100);
      }

      if (randomArray[x] == 2) {
        digitalWrite(led2, HIGH);
        playTone(1519, 200);//Passes tone value and duration of the tone to the playTone function
        delay(200);
        digitalWrite(led2, LOW);
        delay(100);
      }

      if (randomArray[x] == 3) {
        digitalWrite(led3, HIGH);
        playTone(1275, 200);//Passes tone value and duration of the tone to the playTone function
        delay(200);
        digitalWrite(led3, LOW);
        delay(100);
      }

      if (randomArray[x] == 4) {
        digitalWrite(led4, HIGH);
        playTone(956, 200);//Passes tone value and duration of the tone to the playTone function
        delay(200);
        digitalWrite(led4, LOW);
        delay(100);
      }
    }
  }
}



void input() { //Function for allowing user input and checking input against the generated array

  for (int x=0; x <= turn;){ //Statement controlled by turn count
    input1 = digitalRead(switch1);
    input2 = digitalRead(switch2);
    input3 = digitalRead(switch3);
    input4 = digitalRead(switch4);

    if (input1 == HIGH){ //Checking for button push
      digitalWrite(led1, HIGH);
      playTone(1915, 200);//Passes tone value and duration of the tone to the playTone function
      delay(200);
      digitalWrite(led1, LOW);
      inputArray[x] = 1;
      delay(50);
      Serial.print(" ");
      Serial.print(1);
      if (inputArray[x] != randomArray[x]) {
        turn = -1;                                      //Checks value input by user and checks it against
        fail();                              //the value in the same spot on the generated array
      }                                      //The fail function is called if it does not match
      x++;
    }

    if (input2 == HIGH){
      digitalWrite(led2, HIGH);
      playTone(1519, 200);//Passes tone value and duration of the tone to the playTone function
      delay(200);
      digitalWrite(led2, LOW);
      inputArray[x] = 2;
      delay(50);
      Serial.print(" ");
      Serial.print(2);
      if (inputArray[x] != randomArray[x]) {
        turn = -1;
        fail();
      }
      x++;

    }

    if (input3 == HIGH){
      digitalWrite(led3, HIGH);
      playTone(1275, 200);//Passes tone value and duration of the tone to the playTone function
      delay(200);
      digitalWrite(led3, LOW);
      inputArray[x] = 3;
      delay(50);
      Serial.print(" ");
      Serial.print(3);
      if (inputArray[x] != randomArray[x]) {
        turn = -1;
        fail();
      }
      x++;

    }

    if (input4 == HIGH){

      digitalWrite(led4, HIGH);
      playTone(956, 200);//Passes tone value and duration of the tone to the playTone function
      delay(200);
      digitalWrite(led4, LOW);
      inputArray[x] = 4;
      delay(50);
      Serial.print(" ");
      Serial.print(4);
      if (inputArray[x] != randomArray[x]) {
        turn = -1;
        fail();
      }
      
      int value = EEPROM.read(1);
    
   
    if (turn > value) {
      EEPROM.write(1, turn);
    } 
    Serial.println();
    Serial.print("High Score: ");
    Serial.print(value);
    Serial.println();
      
      x++;

    }
  }
  delay(200);
  turn++; //Increments the turn count, also the last action before starting the output function over again
}

void fail() { //Function used if the player fails to match the sequence

  numberOne(10);
  numberTwo(11);
  playTone(1432, 200);
  playTone(1, 5);
  playTone(1432, 200);
  playTone(1700, 200);
  playTone(1275, 200);
  playTone(1432, 200);
  playTone(1, 5);
  playTone(1432, 200);
  playTone(1700, 400);
  for (int y=0; y<=5; y++){ //Flashes lights for failure
    digitalWrite(led1, HIGH);
    digitalWrite(led2, HIGH);
    digitalWrite(led3, HIGH);
    digitalWrite(led4, HIGH);
    delay(200);
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
    digitalWrite(led4, LOW);
    delay(200);
    
  }

  turn = -1; //Resets turn value so the game starts over without need for a reset button
}

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);
  }
}

void highScore(int turnVal) {

  int tenDisp = turnVal / 10;
  int oneDisp = turnVal - (tenDisp * 10);
  Serial.print(turnVal);

  if (turnVal == 9) {
    numberOne(1);
    numberTwo(0);
  }

  if (turnVal == 19) {
    numberOne(2);
    numberTwo(0);
  }

  if (turnVal == 29) {
    numberOne(3);
    numberTwo(0);
  }

  if (turnVal == 39) {
    numberOne(4);
    numberTwo(0);
  }

  if (turnVal == 49) {
    numberOne(5);
    numberTwo(0);
  }


  if (turnVal < 9) {
    numberOne(tenDisp);
    numberTwo(oneDisp + 1);
  }

  if (turnVal > 9 && turnVal < 19) {
    numberOne(tenDisp);
    numberTwo(oneDisp + 1);
  }

  if (turnVal > 19 && turnVal < 29) {
    numberOne(tenDisp);
    numberTwo(oneDisp + 1);
  }

  if (turnVal > 29 && turnVal < 39) {
    numberOne(tenDisp);
    numberTwo(oneDisp + 1);
  }

  if (turnVal > 39 && turnVal < 49) {
    numberOne(tenDisp);
    numberTwo(oneDisp + 1);
  }

}

void warHymn() {  //can be changed to any tune you can figure out. This is the Texas A&M "War Hymn".
  playTone(1915, 200);
  playTone(1, 5);
  playTone(1915, 100);
  playTone(1, 5);
  playTone(1915, 100);
  playTone(1, 5);
  playTone(1915, 200);
  playTone(1, 5);
  playTone(1915, 200);
  playTone(1519, 400);
  playTone(1915, 200);
  playTone(1519, 200);
  playTone(1275, 200);
  playTone(1, 5);
  playTone(1275, 100);
  playTone(1, 5);
  playTone(1275, 100);
  playTone(1, 5);
  playTone(1275, 200);
  playTone(1519, 200);
  playTone(1275, 200);
  playTone(1519, 200);
  playTone(1915, 600);

}

void scoreDisplay(int x) {

  int tenDisp = turn / 10;
  int oneDisp = turn - (tenDisp * 10);
  Serial.print(turn);

  if (turn == 9) {
    numberOne(1);
    numberTwo(0);
  }

  if (turn == 19) {
    numberOne(2);
    numberTwo(0);
  }

  if (turn == 29) {
    numberOne(3);
    numberTwo(0);
  }

  if (turn == 39) {
    numberOne(4);
    numberTwo(0);
  }

  if (turn == 49) {
    numberOne(5);
    numberTwo(0);
  }


  if (turn < 9) {
    numberOne(tenDisp);
    numberTwo(oneDisp + 1);
  }

  if (turn > 9 && turn < 19) {
    numberOne(tenDisp);
    numberTwo(oneDisp + 1);

*** NOTE: I changed the pins from previous versions because of the inclusion of the shift registers. Be sure to change your pins if you try this setup. Also, if you're wiring up a 7-segment display, the code is made to where the Q7 output for the register should be hooked up to the 'A' segment on the display (Q6 - B, Q5 - C, etc.).

Thanks very much.

Looking forward to trying it out.

Hi, i wanted to make this game, but decided to use my lcd too, i was wondering if you could help me because at the tenth turn it resets to 0 without going into the fail sequence (i think).

#include <LiquidCrystal.h>
#include <EEPROM.h>

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);// set up lcd input pins

//lcd pin     ard pin
//   1          GND
//   2          +5
//   3          GND
//   4          7
//   5          GND
//   6          6
//   11         5
//   12         4
//   13         3
//   14         2
//   15         +5
//   16         GND

int switch1 = 11; //The four button input pins
int switch2 = 16;
int switch3 = 9;
int switch4 = 18;
int led1 = 12; //LED pins
int led2 = 15;
int led3 = 10;
int led4 = 17;
int turn = 0;
int speakerPin = 8;
int input1 = HIGH;
int input2 = HIGH;
int input3 = HIGH;
int input4 = HIGH;
int hscore;

int randomArray[100]; //Intentionally long to store up to 100 inputs (doubtful anyone will get this far)
int inputArray[100];


void setup() {
  lcd.begin(16, 2);
 

  Serial.begin(9600);

  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(switch1, INPUT);
  pinMode(switch2, INPUT);
  pinMode(switch3, INPUT);
  pinMode(switch4, INPUT);
  pinMode(speakerPin, OUTPUT);
  digitalWrite(switch1,HIGH);
  digitalWrite(switch2,HIGH);
  digitalWrite(switch3,HIGH);
  digitalWrite(switch4,HIGH);
  
  randomSeed(analogRead(0)); //Added to generate "more randomness" with the randomArray for the output function

hsc();








 for (int y=0; y<=1000; y++){ //For statement to loop through the output and input functions
   output();
   input();
 }

   }
  
void output() { //function for generating the array to be matched by the player
    
   for (int y=turn; y <= turn; y++){ //Limited by the turn variable
   
    lcd.setCursor(0, 1);
    lcd.print("Turn:");
    lcd.setCursor(6, 1);
    lcd.print(y);
    randomArray[y] = random(1, 5); //Assigning a random number (1-4) to the randomArray[y], y being the turn count
    for (int x=0; x <= turn; x++){

   

      if (randomArray[x] == 1) {  //if statements to display the stored values in the array
        digitalWrite(led1, HIGH);
        playTone(1915, 200); //Passes tone value and duration of the tone to the playTone function
        delay(200);
        digitalWrite(led1, LOW);
        delay(100);
      }

      if (randomArray[x] == 2) {
        digitalWrite(led2, HIGH);
        playTone(1519, 200);//Passes tone value and duration of the tone to the playTone function
        delay(200);
        digitalWrite(led2, LOW);
        delay(100);
      }

      if (randomArray[x] == 3) {
        digitalWrite(led3, HIGH);
        playTone(1275, 200);//Passes tone value and duration of the tone to the playTone function
        delay(200);
        digitalWrite(led3, LOW);
        delay(100);
      }

      if (randomArray[x] == 4) {
        digitalWrite(led4, HIGH);
        playTone(956, 200);//Passes tone value and duration of the tone to the playTone function
        delay(200);
        digitalWrite(led4, LOW);
        delay(100);
      }
     }
    }
   }
  
  
  
void input() { //Function for allowing user input and checking input against the generated array

  for (int x=0; x <= turn;){ //Statement controlled by turn count
    input1 = digitalRead(switch1);
    input2 = digitalRead(switch2);
    input3 = digitalRead(switch3);
    input4 = digitalRead(switch4);

    if (input1 == LOW){ //Checking for button push
      digitalWrite(led1, HIGH);
      playTone(1915, 200);//Passes tone value and duration of the tone to the playTone function
      delay(200);
      digitalWrite(led1, LOW);
      inputArray[x] = 1;
      delay(50);
      if (inputArray[x] != randomArray[x]) { //Checks value input by user and checks it against
        fail();                              //the value in the same spot on the generated array
      }                                      //The fail function is called if it does not match
      x++;
    }

    if (input2 == LOW){
      digitalWrite(led2, HIGH);
      playTone(1519, 200);//Passes tone value and duration of the tone to the playTone function
      delay(200);
      digitalWrite(led2, LOW);
      inputArray[x] = 2;
      delay(50);
      if (inputArray[x] != randomArray[x]) {
        fail();
      }
      x++;

    }

    if (input3 == LOW){
      digitalWrite(led3, HIGH);
      playTone(1275, 200);//Passes tone value and duration of the tone to the playTone function
      delay(200);
      digitalWrite(led3, LOW);
      inputArray[x] = 3;
      delay(50);
      if (inputArray[x] != randomArray[x]) {
        fail();
      }
      x++;

    }

    if (input4 == LOW){

      digitalWrite(led4, HIGH);
      playTone(956, 200);//Passes tone value and duration of the tone to the playTone function
      delay(200);
      digitalWrite(led4, LOW);
      inputArray[x] = 4;
      delay(50);
      if (inputArray[x] != randomArray[x]) {
        fail();
      }
      x++;

    }
   }
  delay(500);
  turn++; //Increments the turn count, also the last action before starting the output function over again
}

void fail() { //Function used if the player fails to match the sequence
lcd.clear();
lcd.print("FAIL  FAIL  FAIL");
  playTone(1432, 200); //Tune playing when fail, there is a more elegant way to do this, but this works for short tunes
  playTone(1, 5);
  playTone(1432, 200);
  playTone(1700, 200);
  playTone(1275, 200);
  playTone(1432, 200);
  playTone(1, 5);
  playTone(1432, 200);
  playTone(1700, 400);
  for (int y=0; y<=5; y++){ //Flashes lights for failure
   digitalWrite(led1, HIGH);
   digitalWrite(led2, HIGH);
   digitalWrite(led3, HIGH);
   digitalWrite(led4, HIGH);
   delay(200);
   digitalWrite(led1, LOW);
   digitalWrite(led2, LOW);
   digitalWrite(led3, LOW);
   digitalWrite(led4, LOW);
   delay(200);
   
  }
 if((turn-1) > (EEPROM.read(1)))  {
   EEPROM.write(1, (turn - 1));
  }
  lcd.clear();

  
  EEPROM.write(0, (turn - 1));
  
hsc();

  delay(5000);
  turn = -1; //Resets turn value so the game starts over without need for a reset button
}

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);
  }
}

void loop() { //Unused void loop(), though for some reason it doesn't compile without this 
}
  
 void hsc()  {
   lcd.print("High Score:");
lcd.setCursor(12,0);
int secd;
hscore = EEPROM.read(1);
//hscore = 22;  // test

if((hscore << 10))  {
  secd = hscore;
}

if((hscore >= 10) && (hscore < 20))  {
  lcd.print("1");
  secd = hscore - 10;
}


if((hscore >= 20) && (hscore < 30))  {
  lcd.print("2");
  secd = hscore - 20;
}


if((hscore >= 30) && (hscore < 40))  {
  lcd.print("3");
  secd = hscore - 30;
}


if((hscore >= 40) && (hscore < 50))  {
  lcd.print("4");
  secd = hscore - 40;
}


if((hscore >= 50) && (hscore < 60))  {
  lcd.print("5");
  secd = hscore - 50;
}


if((hscore >= 60) && (hscore < 70))  {
  lcd.print("6");
  secd = hscore - 60;
}


if((hscore >= 70) && (hscore < 80))  {
  lcd.print("7");
  secd = hscore - 70;
}


if((hscore >= 80) && (hscore < 90))  {
  lcd.print("8");
  secd = hscore - 80;
}


if((hscore >= 90) && (hscore < 100))  {
  lcd.print("9");
  secd = hscore - 90;
}

lcd.setCursor(13,0);

if(secd == 1)  {
  lcd.print("1");
}
if(secd == 2)  {
  lcd.print("2");
}
if(secd == 3)  {
  lcd.print("3");
}
if(secd == 4)  {
  lcd.print("4");
}
if(secd == 5)  {
  lcd.print("5");
}
if(secd == 6)  {
  lcd.print("6");
}
if(secd == 7)  {
  lcd.print("7");
}
if(secd == 8)  {
  lcd.print("8");
}
if(secd == 9)  {
  lcd.print("9");
}
 }

would really apreciate some help!!! :-/ :-/

Awesome project, well done :)`

Hi Jackal, would you happen to have a link or file of your schematic so I can see your project? Thanks.