Simon Game Help

I'm trying to recreate the game Simon in Arduino without using any push buttons, and I'm having issues with my readSequence() function. Although the showSequence() function works the way I want it to.

The showSequence() function will randomly light up some LEDs and create a string of letters that will match the order that the LEDs light up in.

After showSequence(), I'm trying to determine if the user correctly repeats the sequence. The user will enter letters to create a string called userSequence to compare to the gameSequence string.

When largestIndex is equal to zero, and I run the code, the LEDs light up more than once (only one LED should light up), it doesn't wait for the user to enter anything in the serial port and then goes through the if else statement and ends the void loop(). When I try printing showSequence(), it works the way I want it to. For some reason, readSequence() lights up more LEDs that I want to and ends the program early.

How can I fix my code so that the code will continue until the user fails to enter the sequence correctly?

#define A3  220 //Red tone
#define G4  392 //Yellow tone
#define C4  262 //Green tone

int sequence[100];
int largestIndex = 0;
int score = 0;
boolean gameOver = false;

void setup() {
  // put your setup code here, to run once:
  pinMode(16, OUTPUT);  //Red LED
  pinMode(14, OUTPUT);  //Yellow LED
  pinMode(13, OUTPUT);  //Green LED
  pinMode(12, OUTPUT);  //Speaker
  Serial.begin(115200);
}

String showSequence()
{
  String gameSequence = "";
  sequence[largestIndex] = random(0, 3);
  largestIndex++;

  for (int index = 0; index < largestIndex; index++)
  {
    if (sequence[index] == 0)
    {
      delay(300);
      digitalWrite(16, HIGH);
      delay(650);
      tone(12, A3);
      delay(50);
      noTone(12);
      digitalWrite(16, LOW);
      gameSequence += "r";
    }

    if (sequence[index] == 1)
    {
      delay(300);
      digitalWrite(14, HIGH);
      delay(650);
      tone(12, G4);
      delay(50);
      noTone(12);
      digitalWrite(14, LOW);
      gameSequence += "y";
    }

    if (sequence[index] == 2)
    {
      delay(300);
      digitalWrite(13, HIGH);
      delay(650);
      tone(12, C4);
      delay(50);
      noTone(12);
      digitalWrite(13, LOW);
      gameSequence += "g";
    }
  }
  return gameSequence;
}


void readSequence()
{
  String userSequence = "";
  Serial.println("Repeat the sequence. Enter one char at a time (r for red, y for yellow, and g for green)");

  for (int index = 0; index < largestIndex; index++)
  {
    if (Serial.available() > 0) //check to see if something came in the serial port
    {
      char a = Serial.read(); //if so, read it
      Serial.println(a);
      switch (a)
      {
        case 'r' :
          userSequence += "r";
          break;

        case 'y' :
          userSequence += "y";
          break;

        case 'g' :
          userSequence += "g";
          break;
      }
    }
  }
  if (userSequence == showSequence())
  {
    Serial.println("Correct!");
    score++;
  }
  else
  {
    String totalScore = String(score);
    Serial.println("Incorrect!");
    Serial.println("Your score is " + totalScore);
    gameOver = true;
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  while (!gameOver)
  {
    showSequence();
    readSequence();
  }
}

  sequence[largestIndex] = random(0, 3);

You generate a random number from the set 0, 1, and 2. And you need an int array to hold those values? Are you sure you don't need a long array, or a long long array?

  for (int index = 0; index < largestIndex; index++)
  {
    if (Serial.available() > 0) //check to see if something came in the serial port
    {

Don't you think you should wait for user input? Perhaps, do nothing while(Serial.available() == 0).

Doesn't the switch statement seem silly? In each case, you simply add the entered letter to the String.

I used while(Serial.available() == 0) to do nothing and removed the switch statement. But I'm still having problems with the code.

It waits for the user input, and then checks to see if the userString and gameString are equal to each other.
Even when I enter the correct sequence, the game will end.

#define A3  220 //Red tone
#define G4  392 //Yellow tone
#define C4  262 //Green tone

int sequence[100];
int largestIndex = 0;
int score = 0;
boolean gameOver = false;

void setup() {
  // put your setup code here, to run once:
  pinMode(16, OUTPUT);  //Red LED
  pinMode(14, OUTPUT);  //Yellow LED
  pinMode(13, OUTPUT);  //Green LED
  pinMode(12, OUTPUT);  //Speaker
  Serial.begin(115200);
}

String showSequence()
{
  String gameSequence = "";
  sequence[largestIndex] = random(0, 3);
  largestIndex++;

  for (int index = 0; index < largestIndex; index++)
  {
    if (sequence[index] == 0)
    {
      delay(300);
      digitalWrite(16, HIGH);
      delay(650);
      tone(12, A3);
      delay(50);
      noTone(12);
      digitalWrite(16, LOW);
      gameSequence += "r";
    }

    if (sequence[index] == 1)
    {
      delay(300);
      digitalWrite(14, HIGH);
      delay(650);
      tone(12, G4);
      delay(50);
      noTone(12);
      digitalWrite(14, LOW);
      gameSequence += "y";
    }

    if (sequence[index] == 2)
    {
      delay(300);
      digitalWrite(13, HIGH);
      delay(650);
      tone(12, C4);
      delay(50);
      noTone(12);
      digitalWrite(13, LOW);
      gameSequence += "g";
    }
  }
  return gameSequence;
}

void readSequence()
{
  String userSequence = "";
  Serial.println("Repeat the sequence. Enter one char at a time (r for red, y for yellow, and g for green)");

  for (int index = 0; index < largestIndex; index++)
  {
    while (Serial.available() == 0) //check to see if something came in the serial port
    {

    }
    char a = Serial.read(); //if so, read it
    String led = String(a);
    Serial.println(a);
    userSequence += led;
  }

  if (userSequence.equals(showSequence()))
  {
    Serial.println("Correct!");
    score++;
  }
  else
  {
    String totalScore = String(score);
    Serial.println("Incorrect!");
    Serial.println("Your score is " + totalScore + "!");
    gameOver = true;
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  while (!gameOver)
  {
    showSequence();
    readSequence();
  }
}

What do you have the Serial Monitor's Line Ending set to? The code assumes nothing, Is that a valid assumption?

I figured out one of my problems with my code. I originally checked if the userSequence string is equal to the showSequence() function. The userSequence should have been checking if it was equal to gameSequence. That was why the LEDs lit up more than I wanted to.

I changed the if statement to:
if (userSequence.equals(gameSequence))

When I try running the code, it says that 'gameSequence' was not declared in this scope.
I set the Serial Monitor's Line Ending to "No line ending."

#define A3  220 //Red tone
#define G4  392 //Yellow tone
#define C4  262 //Green tone

int sequence[100];
int largestIndex = 0;
int score = 0;
boolean gameOver = false;

void setup() {
  // put your setup code here, to run once:
  pinMode(16, OUTPUT);  //Red LED
  pinMode(14, OUTPUT);  //Yellow LED
  pinMode(13, OUTPUT);  //Green LED
  pinMode(12, OUTPUT);  //Speaker
  Serial.begin(115200);
}

String showSequence()
{
  String gameSequence = "";
  sequence[largestIndex] = random(0, 3);
  largestIndex++;

  for (int index = 0; index < largestIndex; index++)
  {
    if (sequence[index] == 0)
    {
      delay(300);
      digitalWrite(16, HIGH);
      delay(650);
      tone(12, A3);
      delay(50);
      noTone(12);
      digitalWrite(16, LOW);
      gameSequence += "r";
    }

    if (sequence[index] == 1)
    {
      delay(300);
      digitalWrite(14, HIGH);
      delay(650);
      tone(12, G4);
      delay(50);
      noTone(12);
      digitalWrite(14, LOW);
      gameSequence += "y";
    }

    if (sequence[index] == 2)
    {
      delay(300);
      digitalWrite(13, HIGH);
      delay(650);
      tone(12, C4);
      delay(50);
      noTone(12);
      digitalWrite(13, LOW);
      gameSequence += "g";
    }
  }
  return gameSequence;
}

String readSequence()
{
  String userSequence = "";
  Serial.println("Repeat the sequence. Enter one char at a time (r for red, y for yellow, and g for green)");

  for (int index = 0; index < largestIndex; index++)
  {
    while (Serial.available() == 0) //check to see if something came in the serial port
    {

    }
    char a = Serial.read(); //if so, read it
    String led = String(a);
    Serial.println(a);
    userSequence += led;
  }

  if (userSequence.equals(gameSequence))
  {
    Serial.println("Correct!");
    score++;
    else
    }
  {
    String totalScore = String(score);
    Serial.println("Incorrect!");
    Serial.println("Your score is " + totalScore + "!");
    gameOver = true;
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  while (!gameOver)
  {
    showSequence();
    readSequence();
  }
}

Where is gameSequence declared ?
What is its scope ?

ShowSequence() returns a value. You ignore the value. Why?

I created a new function called playGame(), placing showSequence() and readSequence() in it. Everything works the way I want it to. Thanks for all the help!

#define A3  220 //Red tone
#define G4  392 //Yellow tone
#define C4  262 //Green tone

int sequence[100];
int largestIndex = 0;
int score = 0;
boolean gameOver = false;

void setup() {
  // put your setup code here, to run once:
  pinMode(16, OUTPUT);  //Red LED
  pinMode(14, OUTPUT);  //Yellow LED
  pinMode(13, OUTPUT);  //Green LED
  pinMode(12, OUTPUT);  //Speaker
  Serial.begin(115200);
}

void playGame()
{
  String gameSequence = "";
  sequence[largestIndex] = random(0, 3);
  largestIndex++;

  for (int index = 0; index < largestIndex; index++)
  {
    if (sequence[index] == 0)
    {
      delay(300);
      digitalWrite(16, HIGH);
      delay(650);
      tone(12, A3);
      delay(50);
      noTone(12);
      digitalWrite(16, LOW);
      gameSequence += "r";
    }

    if (sequence[index] == 1)
    {
      delay(300);
      digitalWrite(14, HIGH);
      delay(650);
      tone(12, G4);
      delay(50);
      noTone(12);
      digitalWrite(14, LOW);
      gameSequence += "y";
    }

    if (sequence[index] == 2)
    {
      delay(300);
      digitalWrite(13, HIGH);
      delay(650);
      tone(12, C4);
      delay(50);
      noTone(12);
      digitalWrite(13, LOW);
      gameSequence += "g";
    }
  }

  String userSequence = "";
  Serial.println("Repeat the sequence. Enter one char at a time (r for red, y for yellow, and g for green)");

  for (int index = 0; index < largestIndex; index++)
  {
    while (Serial.available() == 0) //check to see if something came in the serial port
    {

    }
    char a = Serial.read(); //if so, read it
    String led = String(a);
    Serial.println(a);
    userSequence += led;
  }

  if (userSequence.equals(gameSequence))
  {
    Serial.println("Correct!");
    score++;
  }
  else
  {
    String totalScore = String(score);
    Serial.println("Incorrect!");
    Serial.println("Your score is " + totalScore + "!");
    gameOver = true;
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  while (!gameOver)
  {
    playGame();
  }
}

I dont use the String class but after this line in your code

userSequence +=led ;

when the while loop is exited do you have to append a null character to end the string?

Also you can print out both the user string and the show string to see what it looks like .

when the while loop is exited do you have to append a null character to end the string?

No. The String class does that, after each character is appended.