Last active
May 23, 2022 17:30
-
-
Save wkoch/1c23fd09d9a0974eb2c17297798b5b25 to your computer and use it in GitHub Desktop.
Jogo da Memória
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #define entrada(x) pinMode(x, INPUT_PULLUP) | |
| #define saida(x) pinMode(x, OUTPUT) | |
| #define aguarde(x) delay(x) | |
| #define DESLIGA 0 // Usado para controlar LEDs | |
| #define NADA_ESCOLHIDO 0 // Usado para verificar botões | |
| #define VERMELHO (1 << 0) | |
| #define VERDE (1 << 1) | |
| #define AZUL (1 << 2) | |
| #define AMARELO (1 << 3) | |
| #define LED_VERMELHO 10 | |
| #define LED_VERDE 3 | |
| #define LED_AZUL 13 | |
| #define LED_AMARELO 5 | |
| // Definições dos pinos de botão | |
| #define BOTAO_VERMELHO 9 | |
| #define BOTAO_VERDE 2 | |
| #define BOTAO_AZUL 12 | |
| #define BOTAO_AMARELO 6 | |
| // Definições dos pinos do Buzzer | |
| #define PIEZO1 4 | |
| #define PIEZO2 7 | |
| // Parâmetros do jogo | |
| #define RODADAS_ATE_SER_CAMPEAO 10 // Número de rodadas para vencer o Jogo. | |
| #define TEMPO_DE_RESPOSTA_JOGADOR 3000 // Tempo para pressionar um botão antes que o jogo acabe. 3 segundos | |
| // Variáveis de estado do jogo | |
| byte tabuleiro[32]; //Salva a combinação de botões à medida que avançamos | |
| byte rodadas = 0; //Conta o número de rodadas de sucesso que o jogador fez | |
| void setup() | |
| { | |
| // Configuração dos pinos de entradas e saídas | |
| entrada(BOTAO_VERMELHO); | |
| entrada(BOTAO_VERDE); | |
| entrada(BOTAO_AZUL); | |
| entrada(BOTAO_AMARELO); | |
| saida(LED_VERMELHO); | |
| saida(LED_VERDE); | |
| saida(LED_AZUL); | |
| saida(LED_AMARELO); | |
| saida(PIEZO1); | |
| saida(PIEZO2); | |
| toqueInicial(); // Ao ligar toque a música vencedor | |
| if (checaBotao() == AMARELO) tocarMusica(); | |
| } | |
| void loop() | |
| { | |
| modoAtracao(); // Pisca luzes enquanto aguarda o usuário apertar um botão | |
| // Indique o início do jogo | |
| controlaLEDs(VERMELHO | VERDE | AZUL | AMARELO); // Ativar todos os LEDs | |
| aguarde(1000); | |
| controlaLEDs(DESLIGA); // Desligue os LEDs | |
| aguarde(250); | |
| // Roda o jogo de memória e recebe resultado | |
| if (jogoDaMemoria() == true) | |
| toqueVencedor(); // Ganhou, toca som de vitória | |
| else | |
| toquePerdedor(); // Perdeu, toca som de derrota | |
| } | |
| //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= | |
| //As seguintes funções estão relacionadas apenas ao jogo | |
| // Jogue o jogo regular da memória | |
| // Retorna false se o jogador perde ou true se o jogador ganhar | |
| boolean jogoDaMemoria(void) | |
| { | |
| randomSeed(millis()); // Semeia o gerador aleatório | |
| rodadas = 0; // Redefinir o jogo para o começo | |
| while (rodadas < RODADAS_ATE_SER_CAMPEAO) | |
| { | |
| adicionaJogada(); // Adicione um botão aos movimentos atuais e reproduza-os | |
| apresentaJogadas(); // Jogue de volta o tabuleiro do jogo atual | |
| // Em seguida, solicite ao jogador que repita a sequência. | |
| for (byte atual = 0 ; atual < rodadas ; atual++) | |
| { | |
| byte opcao = aguardarBotao(); // Veja o botão que o usuário pressiona | |
| if (opcao == 0) return false; // Se a espera expirar, o jogador perde | |
| if (opcao != tabuleiro[atual]) return false; // Se a escolha estiver incorreta, o jogador perde | |
| } | |
| aguarde(1000); // O jogador estava correto, espera antes de jogar | |
| } | |
| return true; // O jogador cumpriu todas as rodadas para ganhar! | |
| } | |
| // Reproduz o conteúdo atual dos movimentos do jogo | |
| void apresentaJogadas(void) | |
| { | |
| for (byte atual = 0 ; atual < rodadas ; atual++) | |
| { | |
| emitirTom(tabuleiro[atual], 150); | |
| // Aguarde algum tempo entre a reprodução do botão | |
| // Encurtar isso para tornar o jogo mais difícil | |
| aguarde(150); // 150 funciona bem. 75 fica rápido. | |
| } | |
| } | |
| // Adiciona um novo botão aleatório à sequência do jogo | |
| void adicionaJogada(void) | |
| { | |
| byte novoBotao = random(0, 4); //min (incluido), max (excluido) | |
| // Temos que converter esse número, 0 até 3, para cor | |
| if(novoBotao == 0) novoBotao = VERMELHO; | |
| else if(novoBotao == 1) novoBotao = VERDE; | |
| else if(novoBotao == 2) novoBotao = AZUL; | |
| else if(novoBotao == 3) novoBotao = AMARELO; | |
| tabuleiro[rodadas++] = novoBotao; // Adicionar este novo botão ao array do jogo | |
| } | |
| //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= | |
| // As seguintes funções controlam o hardware | |
| // ilumina um determinado LEDs | |
| // Passar em um byte composto de VERMELHO, AMARELO, etc | |
| void controlaLEDs(byte leds) | |
| { | |
| if ((leds & VERMELHO) != 0) | |
| digitalWrite(LED_VERMELHO, HIGH); | |
| else | |
| digitalWrite(LED_VERMELHO, LOW); | |
| if ((leds & VERDE) != 0) | |
| digitalWrite(LED_VERDE, HIGH); | |
| else | |
| digitalWrite(LED_VERDE, LOW); | |
| if ((leds & AZUL) != 0) | |
| digitalWrite(LED_AZUL, HIGH); | |
| else | |
| digitalWrite(LED_AZUL, LOW); | |
| if ((leds & AMARELO) != 0) | |
| digitalWrite(LED_AMARELO, HIGH); | |
| else | |
| digitalWrite(LED_AMARELO, LOW); | |
| } | |
| // Aguarde até que um botão seja pressionado. | |
| // Retorna uma das cores do LED (LED_VERMELHO, etc.) se for bem-sucedida, 0 se expirar | |
| byte aguardarBotao(void) | |
| { | |
| long inicio = millis(); // Lembre-se da hora em que começamos o loop | |
| // Enquanto tempo decorrido desde a definição da variável início for menor que limite do jogo: | |
| while ( (millis() - inicio) < TEMPO_DE_RESPOSTA_JOGADOR) // Faz um loop até que passe o tempo limite | |
| { | |
| byte botao = checaBotao(); | |
| if (botao != NADA_ESCOLHIDO) | |
| { | |
| emitirTom(botao, 150); // Reproduzir o botão que o usuário acabou de pressionar | |
| while(checaBotao() != NADA_ESCOLHIDO) ; // Agora vamos esperar que o usuário libere o botão | |
| aguarde(10); // Isso ajuda com toques duplos acidentais | |
| return botao; | |
| } | |
| } | |
| return NADA_ESCOLHIDO; // Se chegarmos aqui, expiramos! | |
| } | |
| // Retorna um bit '1' na posição correspondente a VERMELHO, VERDE, etc. | |
| byte checaBotao(void) | |
| { | |
| if (digitalRead(BOTAO_VERMELHO) == 0) return(VERMELHO); | |
| else if (digitalRead(BOTAO_VERDE) == 0) return(VERDE); | |
| else if (digitalRead(BOTAO_AZUL) == 0) return(AZUL); | |
| else if (digitalRead(BOTAO_AMARELO) == 0) return(AMARELO); | |
| return(NADA_ESCOLHIDO); // Se nenhum botão for pressionado, não retorne nenhum | |
| } | |
| // Acenda um LED e toque o tom | |
| // Vermelho, superior esquerdo: 440Hz - 2.272ms - 1.136ms de pulso | |
| // Verde, superior direito: 880Hz - 1.136ms - pulso de 0.568ms | |
| // Azul, inferior esquerdo: pulso de 587.33Hz - 1.702ms - 0.851ms | |
| // Amarelo, inferior direito: 784Hz - 1,276ms - pulso de 0,638ms | |
| void emitirTom(byte qual, int duracao_milisegundos) | |
| { | |
| controlaLEDs(qual); // Ligue um dado LED | |
| // Reproduz o som associado ao LED fornecido | |
| switch(qual) | |
| { | |
| case VERMELHO: | |
| emitirSom(duracao_milisegundos, 1136); | |
| break; | |
| case VERDE: | |
| emitirSom(duracao_milisegundos, 568); | |
| break; | |
| case AZUL: | |
| emitirSom(duracao_milisegundos, 851); | |
| break; | |
| case AMARELO: | |
| emitirSom(duracao_milisegundos, 638); | |
| break; | |
| } | |
| controlaLEDs(DESLIGA); // Desligue todos os LEDs | |
| } | |
| // Alterna o buzzer a cada pausa_microsegundos, por uma duração de duracao_milisegundos. | |
| void emitirSom(int duracao_milisegundos, int pausa_microsegundos) | |
| { | |
| // Converter tempo total de reprodução de milissegundos para microssegundos | |
| long comprimento_microsegundos = duracao_milisegundos * (long)1000; | |
| // Faz um loop até que o tempo restante de reprodução seja menor que uma única pausa_microsegundos | |
| while (comprimento_microsegundos > (pausa_microsegundos * 2)) | |
| { | |
| comprimento_microsegundos -= pausa_microsegundos * 2; // Diminui o tempo de jogo restante | |
| // Alterna a campainha em várias velocidades | |
| digitalWrite(PIEZO1, LOW); | |
| digitalWrite(PIEZO2, HIGH); | |
| delayMicroseconds(pausa_microsegundos); | |
| digitalWrite(PIEZO1, HIGH); | |
| digitalWrite(PIEZO2, LOW); | |
| delayMicroseconds(pausa_microsegundos); | |
| } | |
| } | |
| // Reproduzir o som e as luzes do vencedor | |
| void toqueInicial(void) | |
| { | |
| controlaLEDs(VERDE | AZUL); | |
| somVencedor(); | |
| controlaLEDs(VERMELHO | AMARELO); | |
| somVencedor(); | |
| controlaLEDs(VERDE | AZUL); | |
| somVencedor(); | |
| controlaLEDs(VERMELHO | AMARELO); | |
| somVencedor(); | |
| } | |
| void toqueVencedor(void) | |
| { | |
| toqueInicial(); | |
| tocarMusica(); | |
| } | |
| // Som vencedor | |
| // Este é apenas um som (chato) único que criamos, não há mágica nisso | |
| void somVencedor(void) | |
| { | |
| // Alterna a campainha em várias velocidades | |
| for (byte x = 250 ; x > 70 ; x--) | |
| { | |
| for (byte y = 0 ; y < 3 ; y++) | |
| { | |
| digitalWrite(PIEZO2, HIGH); | |
| digitalWrite(PIEZO1, LOW); | |
| delayMicroseconds(x); | |
| digitalWrite(PIEZO2, LOW); | |
| digitalWrite(PIEZO1, HIGH); | |
| delayMicroseconds(x); | |
| } | |
| } | |
| } | |
| // Toque o som perdedor / luzes | |
| void toquePerdedor(void) | |
| { | |
| controlaLEDs(VERMELHO | VERDE); | |
| emitirSom(255, 1500); | |
| controlaLEDs(AZUL | AMARELO); | |
| emitirSom(255, 1500); | |
| controlaLEDs(VERMELHO | VERDE); | |
| emitirSom(255, 1500); | |
| controlaLEDs(AZUL | AMARELO); | |
| emitirSom(255, 1500); | |
| } | |
| // Mostra uma tela de "modo de atração" enquanto aguarda o usuário pressionar o botão. | |
| void modoAtracao(void) | |
| { | |
| while(true) | |
| { | |
| controlaLEDs(VERMELHO); | |
| aguarde(100); | |
| if (checaBotao() != NADA_ESCOLHIDO) return; | |
| controlaLEDs(AZUL); | |
| aguarde(100); | |
| if (checaBotao() != NADA_ESCOLHIDO) return; | |
| controlaLEDs(VERDE); | |
| aguarde(100); | |
| if (checaBotao() != NADA_ESCOLHIDO) return; | |
| controlaLEDs(AMARELO); | |
| aguarde(100); | |
| if (checaBotao() != NADA_ESCOLHIDO) return; | |
| } | |
| } | |
| //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= | |
| // As seguintes funções estão relacionadas apenas ao Easter Egg Musical | |
| int numeroDoLed = 0; // Mantém o controle de qual LED estamos ligando durante o ciclo musical | |
| // Não faça nada além de tocar a música | |
| // Esta função é ativada quando o usuário segura o botão inferior direito (amarelo) | |
| void tocarMusica(void) | |
| { | |
| // Notas (frequências) da música. | |
| int notas[] = { | |
| 2637, 2637, 0, 2637, 0, 2093, 2637, 0, 3136, 0, 0, 0, 1568, 0, 0, 0, | |
| 2093, 0, 0, 1568, 0, 0, 1319, 0, 0, 1760, 0, 1976, 0, 1865, 1760, 0, | |
| 1568, 2637, 3136, 3520, 0, 2794, 3136, 0, 2637, 0, 2093, 2349, 1976, 0, 0, 2093, | |
| 0, 0, 1568, 0, 0, 1319, 0, 0, 1760, 0, 1976, 0, 1865, 1760, 0, 1568, | |
| 2637, 3136, 3520, 0, 2794, 3136, 0, 2637, 0, 2093, 2349, 1976, 0, 0, 262, 523, | |
| 220, 440, 233, 466, 0, 0, 262, 523, 220, 440, 233, 466, 0, 0, 175, 349, | |
| 147, 294, 156, 311, 0, 0, 175, 349, 147, 294, 156, 311, 0, 0, 311, 277, | |
| 294, 277, 311, 311, 208, 196, 277, 262, 370, 349, 165, 466, 440, 415, 311, 247, | |
| 233, 220, 208, 0, 0, 0}; | |
| // Duração das notas da música | |
| int tempos[] = { | |
| 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, | |
| 12, 12, 12, 12, 12, 12, 12, 12, 9, 9, 9, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, | |
| 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 9, 9, 9, 12, 12, 12, 12, 12, 12, | |
| 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 6, 3, 12, 12, 12, 12, 12, 12, 6, 3, 12, 12, | |
| 12, 12, 12, 12, 6, 3, 12, 12, 12, 12, 12, 12, 6, 6, 18, 18, 18, 6, 6, 6, 6, 6, 6, 18, | |
| 18, 18, 18, 18, 18, 10, 10, 10, 10, 10, 10, 3, 3, 3}; | |
| // Ligue o LED inferior direito (amarelo) | |
| controlaLEDs(AMARELO); | |
| emitirTom(AMARELO, 150); | |
| controlaLEDs(VERMELHO | VERDE | AZUL); // Ligue os outros LEDs até você soltar o botão | |
| while(checaBotao() != NADA_ESCOLHIDO) ; // Aguarde até que o usuário pare de pressionar o botão | |
| controlaLEDs(NADA_ESCOLHIDO); // Desligue os LEDs | |
| aguarde(1000); // Espere um segundo antes de tocar música | |
| digitalWrite(PIEZO2, LOW); // configure o lado "PIEZO1" da campainha para ficar baixo, enquanto tocamos o tom no outro pino. | |
| while(checaBotao() == NADA_ESCOLHIDO) // Reproduzir música até você pressionar um botão | |
| { | |
| int limite = sizeof notas / sizeof *notas; // Descobre o tamanho do array | |
| // iterar sobre as notas da melodia: | |
| for (int i = 0; i < limite; i++) { | |
| mudaLED(); | |
| int duracao = 1000 / tempos[i]; // Velocidade da música | |
| tone(PIEZO1, notas[i], duracao); | |
| aguarde(duracao * 1.3); // Pausa entre notas | |
| noTone(PIEZO1); | |
| if(checaBotao() != NADA_ESCOLHIDO) | |
| break; | |
| } | |
| } | |
| } | |
| // Cada vez que esta função é chamada, a placa se move para o próximo LED | |
| void mudaLED(void) | |
| { | |
| controlaLEDs(1 << numeroDoLed); // Mude o LED | |
| numeroDoLed++; // Ir para o próximo LED | |
| if(numeroDoLed > 3) numeroDoLed = 0; // Enrole o balcão, se necessário | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment