Arduino Playground is read-only starting December 31st, 2018. For more info please look at this Forum Post

Simple Simon Says Game

Creator: Andrew Mascolo(HazardsMind)

Buttons are to be wired normally HIGH (LOW when pressed)
Pay attention to how the LED pins follow directly after the Button pins.
----

/*
  This code is set for buttons to be normally LOW by default.
  To change from normally LOW to HIGH, use "if (buttonState[count] == LOW && buttonState[count] != lastButtonState[count]) "
*/

#define Num_of_Pins 4 // number of buttons and/or LEDs  used
#define SequenceLenght 50 // max lenght of the pattern
#define TonePin 12 // pin for the Piezo 

const byte LEDpin[Num_of_Pins] = {6, 7, 8, 9}; // LED pins used
const byte ButtonPin[Num_of_Pins] = {2, 3, 4, 5}; //Buttons pins used
const int Note[Num_of_Pins] = {165, 330, 659, 1319}; // tone per LED

byte ledList[SequenceLenght]; // starting pattern
byte buttonState[Num_of_Pins] = {0, 0, 0, 0}; // button state holder
byte lastButtonState[Num_of_Pins] = {0, 0, 0, 0}; // store old button state for compare

byte Pat_count = 0; // number of LEDs in starting pattern
int Btemp = 0; // temporary button pin holder

unsigned int Speed = 300; // pattern display speed
byte count = 0; // cycle through button pins

unsigned long lastDebounceTime[Num_of_Pins]; // record last time button was pressed
unsigned long time; // record initial time for pattern blinks

bool PatternStatus = false; // toggle whether player has won or not
//===========================================================================================


void setup()
{
  randomSeed(analogRead(A4) / analogRead(A5)); // set a seed value upon start up
  Serial.begin(115200);
  for (int cnt = 0; cnt < Num_of_Pins; cnt++) // initialize LED pins and buttons
  {
    pinMode(LEDpin[cnt], OUTPUT);
    pinMode(ButtonPin[cnt], INPUT_PULLUP);
    ledList[cnt] = random(6, 9);
    Pat_count++;
  }
}

void loop() 
{
  showPattern(); // display the LED pattern
  VerifyButtons(); // wait for button presses and check to see button presses match LEDs that were lit
}

void showPattern()
{
  for (byte pattern = 0; pattern < Pat_count; pattern++) // cycle through LED pattern and blink them
  {
    time = millis();
    while (millis() - time < Speed)
    {
      digitalWrite(ledList[ pattern ], HIGH);
      tone(TonePin, Note[ledList[pattern] - 6]);
    }

    time = millis();
    while (millis() - time < Speed)
    {
      noTone(TonePin);
      digitalWrite(ledList[ pattern ], LOW);
    }
  }
}

void VerifyButtons()
{
  static byte i;
  i = 0;

  while (i < Pat_count)
  {
    Btemp = Getbutton(); // get a value from Getbutton function
    if (Btemp != -1) // filter out no button press "0"
    {
      tone(TonePin, Note[Btemp - 2]); 

      //Serial.println(Btemp); // debug purpose
      if (ledList[i] == (Btemp + Num_of_Pins)) // compare button pressed to LED lit
      {
        i++; // each correct button press, increments ledList to check the next LED
        PatternStatus = true;
      }
      else // If at any time a button was incorrect, set PatternStatus to false to show losing message then get out of while loop
      {
        PatternStatus = false;
        break;
      }
    }
    else
    {
      noTone(TonePin);
      Serial.println(F("Times Up"));
      PatternStatus = false;
      break;
    }
  }
  if (PatternStatus == true) // button pattern matched all shown LEDs
  {
    Speed -= 9; // increase pattern speed, by lowering Speed value
    Serial.println(F("Pattern was Good"));
    updatePattern();
  }
  else Serial.println(F("Player Lost"));
}

void updatePattern() // if player has entered buttons correctly add a new LED to ledList
{
  if (Pat_count > 32)
    Serial.println(F("Player has won the game"));
  else
    Pat_count++;
  ledList[Pat_count - 1] = random(5, 7);
}

int Getbutton()
{
  static unsigned long timeOut = 2000, countDown;
  countDown = millis();

  while (millis() - countDown <= timeOut)
  {
    for (count = 0; count < Num_of_Pins; count++) // loop through all the buttons
    {
      buttonState[count] = digitalRead(ButtonPin[count]); // read button states

      if (buttonState[count] != lastButtonState[count]) // check to see if the state has changed from last press
      {
        if (buttonState[count] == LOW)
        {
          lastDebounceTime[count] = millis();// record the time of the last press
          lastButtonState[count] = buttonState[count]; // update old button state for next checking
        }
      }
      if ((millis() - lastDebounceTime[count]) > 50UL)
      {
        if (buttonState[count] == LOW)
        {
          return ButtonPin[count];
        }
      }
    }
  }
  return -1; // return button pin pressed
}