#include "pitches.h"
#include <LiquidCrystal.h>
#include <Wire.h>

//Pins, Taster und Speaker Pins festgelegt 
LiquidCrystal   lcd( A0, A1, A2, A3, A4, A5);
const uint8_t ledPins[] ={22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37};
const uint8_t buttonPins[] = {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};
#define SPEAKER_PIN 38

int turn   = 0;  // turn counter
int buttonstate = 0;  // button state checker
int randomArray[50];   //long to store up to 50 inputs 
int inputArray[50];
int highscore = 0;
int   MyScore;

#define MAX_GAME_LENGTH 100

const int gameTones[] = { NOTE_G3, NOTE_C4, NOTE_E4, NOTE_G5};

/* Global variables - store the game state */
uint8_t gameSequence[MAX_GAME_LENGTH] = {0};
uint8_t gameIndex = 0;

/**
   Set up the Arduino board and initialize Serial communication
*/
void setup() {
  Serial.begin(9600);
  for (byte i = 0; i < 16; i++) {
    pinMode(ledPins[i], OUTPUT);
    pinMode(buttonPins[i], INPUT_PULLUP);
  }
  pinMode(SPEAKER_PIN, OUTPUT);
 
  lcd.begin(16,2);

lcd.setCursor(0,0);   // Abschnitt für LCD
lcd.print("Simon Says"); 
lcd.setCursor(0,1);
delay(3000);
lcd.clear();

 lcd.setCursor(0, 1);
 lcd.print("Your   Score: 0");
 lcd.setCursor(0, 0);
 lcd.print("High Score: 0");

for (int y=turn;   y <= turn; y++) 
   { 
     Serial.println(""); 
      Serial.print("Turn:   ");
      Serial.print(y);
     Serial.println("");
      lcd.clear();
   MyScore=y;
 lcd.setCursor(0, 1);  //(Column,Row)
 lcd.print("Your Score:   ");
 lcd.setCursor(12, 1); 
 lcd.print(MyScore);
 if(MyScore > highscore)   {
   highscore = y;
 }
 lcd.setCursor(0, 0);
 lcd.print("High Score:   " + (String)(highscore));
 Serial.print(y);
 Serial.println("");
delay(1000);
  // The following line primes the random number generator.
  // It assumes pin A3 is floating (disconnected):
  randomSeed(analogRead(A3));
}
}
/**
   Lights the given LED and plays a suitable tone
*/
void lightLedAndPlayTone(byte ledIndex) {
  digitalWrite(ledPins[ledIndex], HIGH);
  tone(SPEAKER_PIN, gameTones[ledIndex]);
  delay(300);
  digitalWrite(ledPins[ledIndex], LOW);
  noTone(SPEAKER_PIN);
}

/**
   Plays the current sequence of notes that the user has to repeat
*/
void playSequence() {
  for (int i = 0; i < gameIndex; i++) {
    byte currentLed = gameSequence[i];
    lightLedAndPlayTone(currentLed);
    delay(50);
  }
}

/**
    Waits until the user pressed one of the buttons,
    and returns the index of that button
*/
byte readButtons() {
  while (true) {
    for (byte i = 0; i < 16; i++) {
      byte buttonPin = buttonPins[i];
      if (digitalRead(buttonPin) == LOW) {
        return i;
      }
    }
    delay(1);
  }
}

/**
  Play the game over sequence, and report the game score
*/
void gameOver() {
  Serial.print("Game over! your score: ");
  Serial.println(gameIndex - 1);
  gameIndex = 0;
  delay(200);

  // Play a Wah-Wah-Wah-Wah sound
  tone(SPEAKER_PIN, NOTE_DS5);
  delay(300);
  tone(SPEAKER_PIN, NOTE_D5);
  delay(300);
  tone(SPEAKER_PIN, NOTE_CS5);
  delay(300);
  for (byte i = 0; i < 10; i++) {
    for (int pitch = -10; pitch <= 10; pitch++) {
      tone(SPEAKER_PIN, NOTE_C5 + pitch);
      delay(5);
    }
  }
  noTone(SPEAKER_PIN);
  delay(500);
}

/**
   Get the user's input and compare it with the expected sequence.
*/
bool checkUserSequence() {
  for (int i = 0; i < gameIndex; i++) {
    byte expectedButton = gameSequence[i];
    byte actualButton = readButtons();
    lightLedAndPlayTone(actualButton);
    if (expectedButton != actualButton) {
      return false;
    }
  }

  return true;
}

/**
   Plays a hooray sound whenever the user finishes a level
*/
void playLevelUpSound() {
  tone(SPEAKER_PIN, NOTE_E4);
  delay(150);
  tone(SPEAKER_PIN, NOTE_G4);
  delay(150);
  tone(SPEAKER_PIN, NOTE_E5);
  delay(150);
  tone(SPEAKER_PIN, NOTE_C5);
  delay(150);
  tone(SPEAKER_PIN, NOTE_D5);
  delay(150);
  tone(SPEAKER_PIN, NOTE_G5);
  delay(150);
  noTone(SPEAKER_PIN);
}

/**
   The main game loop
*/
void loop() {
  // Add a random color to the end of the sequence
  gameSequence[gameIndex] = random(0, 16);
  gameIndex++;
  if (gameIndex >= MAX_GAME_LENGTH) {
    gameIndex = MAX_GAME_LENGTH - 1;
  }
  playSequence();
  if (!checkUserSequence()) {
    gameOver();
  }

  delay(300);

  if (gameIndex > 0) {
    playLevelUpSound();
    delay(300);
  }
}