const int led1Pin = 5;   // Pino para o LED 1
const int led2Pin = 4;   // Pino para o LED 2
const int led3Pin = 3;   // Pino para o LED 3
const int led4Pin = 2;   // Pino para o LED 4

const int triggerPin1 = 13;
const int echoPin1 = 12;
const int triggerPin2 = 11;
const int echoPin2 = 10;
const int triggerPin3 = 9;
const int echoPin3 = 8;
const int triggerPin4 = 7;
const int echoPin4 = 6;

const int buzzerPin = A0; // Pino para o buzzer

int sequencia[50];        // Array para armazenar a sequência
int tamanhoSequencia = 0; // Tamanho atual da sequência
int rodada = 1;           // Número da rodada atual

// Sequência de tons para o som de derrota
int somDerrota[] = {196, 175, 156, 139, 131, 117, 104, 93};

// Sequência de tons para o som de vitória
int somVitoria[] = {262, 330, 392, 523, 1047};

float distance1, distance2, distance3, distance4;

unsigned long tempoInicial;
const unsigned long tempoMaximoSemDeteccao = 5000; // 5 segundos em milissegundos
bool aguardandoDetecao = false;

void setup() {
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  pinMode(led3Pin, OUTPUT);
  pinMode(led4Pin, OUTPUT);
  
  
  pinMode(triggerPin1, OUTPUT);
  pinMode(echoPin1, INPUT);
  
  pinMode(triggerPin2, OUTPUT);
  pinMode(echoPin2, INPUT);
  
  pinMode(triggerPin3, OUTPUT);
  pinMode(echoPin3, INPUT);
  
  pinMode(triggerPin4, OUTPUT);
  pinMode(echoPin4, INPUT);
  
  pinMode(buzzerPin, OUTPUT);  // Configura o pino do buzzer como saída
  
  randomSeed(analogRead(0));  // Inicializa a semente para números aleatórios

  tempoInicial = millis(); // Inicializa o tempo no início do programa
  
  Serial.begin(9600);         // Inicializa a comunicação serial para depuração
}

void loop() {
  medirDistancia();

  // Verifica se todos os sensores estão acima de 100 cm na primeira rodada
  bool todosSensoresAcimaDe100 = (distance1 > 100 && distance2 > 100 && distance3 > 100 && distance4 > 100);

  // Verifica se a primeira rodada ou se os sensores estão acima de 100 cm
  if (todosSensoresAcimaDe100 && rodada == 1) {
    Serial.println("Todos os sensores acima de 100 na primeira rodada. Pisca o led1Pin...");
    piscarLED(led1Pin, 500, 200);  // Exemplo de piscar o LED1
  } else {
    Serial.println("Sensores abaixo de 100 ou rodada não é a primeira. Executando jogarRodada()...");
    jogarRodada();

    // Verifica se os sensores estão abaixo de 100 cm e inicia a contagem de tempo
    if (distance1 <= 100 || distance2 <= 100 || distance3 <= 100 || distance4 <= 100) {
      aguardandoDetecao = true;
      tempoInicial = millis(); // Atualiza o tempo de início da contagem
    }

    // Verifica se o tempo máximo sem detecção foi atingido
    if (aguardandoDetecao && millis() - tempoInicial >= tempoMaximoSemDeteccao) {
      gameOver(); // Executa o Game Over
      aguardandoDetecao = false; // Reinicia a condição de espera
    }
  }
}

void jogarRodada() {
  // Gere a próxima cor na sequência
  int proximaCor = random(4); // 0 para LED1, 1 para LED2, 2 para LED3 e 3 para LED4
  sequencia[tamanhoSequencia] = proximaCor;
  tamanhoSequencia++;

  // Exiba a sequência para o jogador
  for (int i = 0; i < tamanhoSequencia; i++) {
    int cor = sequencia[i];
    int pinoLED;
    int frequenciaSom;

    switch (cor) {
      case 0:
        pinoLED = led1Pin;
        frequenciaSom = 200;
        break;
      case 1:
        pinoLED = led2Pin;
        frequenciaSom = 500;
        break;
      case 2:
        pinoLED = led3Pin;
        frequenciaSom = 900;
        break;
       case 3:
        pinoLED = led4Pin;
        frequenciaSom = 1100;
        break;
      default:
        // Lida com cores não reconhecidas (se necessário)
        break;
    }

    piscarLED(pinoLED, 500, frequenciaSom);
    delay(300); // Espere um pouco entre as cores
  }

  // Aguarde as respostas do jogador
  for (int i = 0; i < tamanhoSequencia; i++) {
    int corEsperada = sequencia[i];
    int pinoLED;
    int frequenciaSom;

    switch (corEsperada) {
      case 0:
        pinoLED = led1Pin;
        frequenciaSom = 200;
        break;
      case 1:
        pinoLED = led2Pin;
        frequenciaSom = 500;
        break;
      case 2:
        pinoLED = led3Pin;
        frequenciaSom = 900;
        break;
      case 3:
        pinoLED = led4Pin;
        frequenciaSom = 1100;
        break;
      default:
        // Lida com cores não reconhecidas (se necessário)
        break;
    }

    int botaoPressionado = esperarBotaoPressionado();

    if (botaoPressionado == corEsperada) {
      piscarLED(pinoLED, 500, frequenciaSom);
    } else {
      // O jogador errou a sequência
      gameOver();
      return;
  reiniciarJogo();
    }
    delay(300); // Espere um pouco entre as cores piscadas pelo jogador
  }

  // O jogador acertou a sequência, aumente a dificuldade
  rodada++;
  Serial.print("Nova Rodada ");
  Serial.println(rodada);

  tocarSomVitoria();

  delay(1000); // Espere um pouco antes da próxima rodada
}

void medirDistancia()
{
  // Gere um pulso no pino de trigger do sensor ultrassônico 1 para medir a distância
    digitalWrite(triggerPin1, LOW);
    delayMicroseconds(2);
    digitalWrite(triggerPin1, HIGH);
    delayMicroseconds(10);
    digitalWrite(triggerPin1, LOW);

    // Meça o tempo de resposta no pino de echo e converta-o em distância
    long duration1 = pulseIn(echoPin1, HIGH);
     distance1 = duration1 * 0.034 / 2;

    // Gere um pulso no pino de trigger do sensor ultrassônico 2 para medir a distância
    digitalWrite(triggerPin2, LOW);
    delayMicroseconds(2);
    digitalWrite(triggerPin2, HIGH);
    delayMicroseconds(10);
    digitalWrite(triggerPin2, LOW);

    // Meça o tempo de resposta no pino de echo do segundo sensor e converta-o em distância
    long duration2 = pulseIn(echoPin2, HIGH);
     distance2 = duration2 * 0.034 / 2;
    
    // Gere um pulso no pino de trigger do sensor ultrassônico 3 para medir a distância
    digitalWrite(triggerPin3, LOW);
    delayMicroseconds(2);
    digitalWrite(triggerPin3, HIGH);
    delayMicroseconds(10);
    digitalWrite(triggerPin3, LOW);

    // Meça o tempo de resposta no pino de echo do terceiro sensor e converta-o em distância
    long duration3 = pulseIn(echoPin3, HIGH);
     distance3 = duration3 * 0.034 / 2;
    
    // Gere um pulso no pino de trigger do sensor ultrassônico 4 para medir a distância
    digitalWrite(triggerPin4, LOW);
    delayMicroseconds(2);
    digitalWrite(triggerPin4, HIGH);
    delayMicroseconds(10);
    digitalWrite(triggerPin4, LOW);

    // Meça o tempo de resposta no pino de echo do terceiro sensor e converta-o em distância
    long duration4 = pulseIn(echoPin4, HIGH);
     distance4 = duration4 * 0.034 / 2;
    
    
    Serial.print("| Distancia 1: |");
    Serial.print(distance1);
    Serial.print(" cm");
    
    
    
    Serial.print("| Distancia 2: |");
    Serial.print(distance2);
    Serial.print(" cm");
    
    
    
    Serial.print("| Distancia 3: |");
    Serial.print(distance3);
    Serial.print(" cm");
    
    
    
    Serial.print("| Distancia 4: |");
    Serial.print(distance4);
    Serial.println(" cm");
}

int esperarBotaoPressionado() {
  while (true) {
    // Gere um pulso no pino de trigger do sensor ultrassônico 1 para medir a distância
    digitalWrite(triggerPin1, LOW);
    delayMicroseconds(2);
    digitalWrite(triggerPin1, HIGH);
    delayMicroseconds(10);
    digitalWrite(triggerPin1, LOW);

    // Meça o tempo de resposta no pino de echo e converta-o em distância
    long duration1 = pulseIn(echoPin1, HIGH);
     distance1 = duration1 * 0.034 / 2;

    // Gere um pulso no pino de trigger do sensor ultrassônico 2 para medir a distância
    digitalWrite(triggerPin2, LOW);
    delayMicroseconds(2);
    digitalWrite(triggerPin2, HIGH);
    delayMicroseconds(10);
    digitalWrite(triggerPin2, LOW);

    // Meça o tempo de resposta no pino de echo do segundo sensor e converta-o em distância
    long duration2 = pulseIn(echoPin2, HIGH);
     distance2 = duration2 * 0.034 / 2;
    
    // Gere um pulso no pino de trigger do sensor ultrassônico 3 para medir a distância
    digitalWrite(triggerPin3, LOW);
    delayMicroseconds(2);
    digitalWrite(triggerPin3, HIGH);
    delayMicroseconds(10);
    digitalWrite(triggerPin3, LOW);

    // Meça o tempo de resposta no pino de echo do terceiro sensor e converta-o em distância
    long duration3 = pulseIn(echoPin3, HIGH);
     distance3 = duration3 * 0.034 / 2;
    
    // Gere um pulso no pino de trigger do sensor ultrassônico 4 para medir a distância
    digitalWrite(triggerPin4, LOW);
    delayMicroseconds(2);
    digitalWrite(triggerPin4, HIGH);
    delayMicroseconds(10);
    digitalWrite(triggerPin4, LOW);

    // Meça o tempo de resposta no pino de echo do terceiro sensor e converta-o em distância
    long duration4 = pulseIn(echoPin4, HIGH);
     distance4 = duration4 * 0.034 / 2;
    
    
    Serial.print("| Distancia 1: |");
    Serial.print(distance1);
    Serial.print(" cm");
    
    
    
    Serial.print("| Distancia 2: |");
    Serial.print(distance2);
    Serial.print(" cm");
    
    
    
    Serial.print("| Distancia 3: |");
    Serial.print(distance3);
    Serial.print(" cm");
    
    
    
    Serial.print("| Distancia 4: |");
    Serial.print(distance4);
    Serial.println(" cm");
    
    


    if (distance1 <= 100) 
    {
      return 0; // Botão 1 pressionado, corresponde à cor 0 (LED1)
    } 
    else if (distance2 <= 100) 
    {
      return 1; // Botão 2 pressionado, corresponde à cor 1 (LED2)
    }
    else if (distance3 <= 100) 
    {
      return 2; // Botão 3 pressionado, corresponde à cor 2 (LED3)
    }
     else if (distance4 <= 100) 
    {
      return 3; // Botão 3 pressionado, corresponde à cor 3 (LED4)
    }
  }
}

void piscarLED(int pino, int tempo, int frequencia) {
  digitalWrite(pino, HIGH);
  tocarSom(frequencia, tempo); // Toca o som correspondente ao LED
  digitalWrite(pino, LOW);
  delay(tempo);
}

void tocarSom(int frequencia, int duracao) {
  tone(buzzerPin, frequencia, duracao);
  delay(duracao + 50); // Aguarda um pouco antes de parar o som
  noTone(buzzerPin);   // Para o som
}

void reiniciarJogo() {
  tamanhoSequencia = 0;
  rodada = 1;
  for (int i = 0; i < 50; i++) {
    sequencia[i] = -1; // Define todos os valores no array de sequência como inválidos
  }
  Serial.println("Jogo reiniciado");
}

void gameOver() {
  Serial.println("Game Over!");
  tocarSomDerrota(); // Toca o som de derrota
  delay(1000); // Aguarde um pouco para que o jogador ouça o som de derrota
  reiniciarJogo(); // Reinicie o jogo após o Game Over
}

void tocarSomDerrota() {
  for (int i = 0; i < 8; i++) {
    tone(buzzerPin, somDerrota[i]);
    delay(300);
  }
  noTone(buzzerPin);
}

void tocarSomVitoria() {
  for (int i = 0; i < 5; i++) {
    tone(buzzerPin, somVitoria[i]);
    delay(100);
    noTone(buzzerPin);
    delay(100);
  }
}
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module