/* Referências
https://wokwi.com/projects/372433455461300225
https://wokwi.com/projects/344891334169985618
https://wokwi.com/projects/379597238939188225
https://wokwi.com/projects/375949126570206209
https://wokwi.com/projects/377890232076729345
https://docs.wokwi.com/pt-BR/parts/wokwi-buzzer
https://docs.wokwi.com/pt-BR/parts/wokwi-arduino-uno
https://docs.wokwi.com/pt-BR/parts/wokwi-74hc595
https://www.arduino.cc/reference/pt/language/functions/advanced-io/notone/
https://www.arduino.cc/reference/pt/language/functions/advanced-io/shiftout/
https://wokwi.com/projects/379961744312747009
https://wokwi.com/projects/285525640477671948
*/
#include "pitches.h"
const byte pinosLED[] = {9, 10, 11, 12};
const byte pinosBotao[] = {2, 3, 4, 5};
const byte sonsJogo[] = { NOTE_D4, NOTE_E4, NOTE_G2, NOTE_G5 };
const int pinoRegistroDeslocamento = A1;
const int pinoDados = A0;
const int pinoClock = A2;
const int pinoAltoFalante = 8;
const int pontuacaoMax = 100;
byte seqJogo[pontuacaoMax];
byte pontuacaoJogo = 0;
const byte tabelaDigitos[] = {
0b11000000,
0b11111001,
0b10100100,
0b10110000,
0b10011001,
0b10010010,
0b10000010,
0b11111000,
0b10000000,
0b10010000,
};
void setup() {
Serial.begin(9600);
for (byte i = 0; i < 4; i++) {
pinMode(pinosLED[i], OUTPUT);
pinMode(pinosBotao[i], INPUT_PULLUP);
}
pinMode(pinoAltoFalante, OUTPUT);
pinMode(pinoRegistroDeslocamento, OUTPUT);
pinMode(pinoClock, OUTPUT);
pinMode(pinoDados, OUTPUT);
randomSeed(analogRead(A3));
}
void enviaPontuacao(byte alto, byte baixo) {
digitalWrite(pinoRegistroDeslocamento, LOW);
shiftOut(pinoDados, pinoClock, MSBFIRST, baixo);
shiftOut(pinoDados, pinoClock, MSBFIRST, alto);
digitalWrite(pinoRegistroDeslocamento, HIGH);
}
void exibePontuacao() {
int alto = pontuacaoJogo % 100 / 10;
int baixo = pontuacaoJogo % 10;
enviaPontuacao(alto ? tabelaDigitos[alto] : 0xff, tabelaDigitos[baixo]);
}
void acendeLedESom(byte indiceLED) {
digitalWrite(pinosLED[indiceLED], HIGH);
tone(pinoAltoFalante, sonsJogo[indiceLED]);
delay(500);
digitalWrite(pinosLED[indiceLED], LOW);
noTone(pinoAltoFalante);
}
void reproduzSeq() {
for (int i = 0; i < pontuacaoJogo; i++) {
byte LEDAtual = seqJogo[i];
acendeLedESom(LEDAtual);
delay(100);
}
}
byte lerBotoes() {
while (true) {
for (byte i = 0; i < 4; i++) {
byte pinoBotao = pinosBotao[i];
if (digitalRead(pinoBotao) == LOW) {
return i;
}
}
delay(0);
}
}
void fimDeJogo() {
Serial.print("Fim de jogo! Sua pontuação é: ");
Serial.println(pontuacaoJogo - 1);
pontuacaoJogo = 0;
delay(500);
int somFimDeJogo[] = {NOTE_DS5, NOTE_D5, NOTE_CS5};
for (int indiceSom = 0; indiceSom < 2; indiceSom++) {
tone(pinoAltoFalante, somFimDeJogo[indiceSom]);
delay(300);
}
for (byte i = 0; i < 5; i++) {
for (int Som = -5; Som <= 5; Som++) {
tone(pinoAltoFalante, NOTE_C5 + Som);
delay(10);
}
}
noTone(pinoAltoFalante);
delay(500);
}
bool verificaSeq() {
for (int i = 0; i < pontuacaoJogo; i++) {
byte botaoEsperado = seqJogo[i];
byte botaoAtual = lerBotoes();
acendeLedESom(botaoAtual);
if (botaoEsperado != botaoAtual) {
return false;
}
}
return true;
}
void tocaSomNivelUP() {
int somNivelUP[] = {NOTE_E4, NOTE_G4, NOTE_E5};
for (int indiceSom = 0; indiceSom < 6; indiceSom++) {
tone(pinoAltoFalante, somNivelUP[indiceSom]);
delay(200);
}
noTone(pinoAltoFalante);
}
void loop() {
exibePontuacao();
seqJogo[pontuacaoJogo] = random(0, 4);
pontuacaoJogo++;
if (pontuacaoJogo >= pontuacaoMax) {
pontuacaoJogo = pontuacaoMax - 1;
}
reproduzSeq();
if (!verificaSeq()) {
fimDeJogo();
}
delay(500);
if (pontuacaoJogo > 0) {
tocaSomNivelUP();
delay(400);
}
}