/************************************************ * Projeto: Jogo da Tabuada * * Desenvolvedor: Vanderlei Alves * * Data: 04/02/2025 * *************************************************/ //Mapeamento de hardware------------------------- //Pinos do display LCD #define RS 12 #define EN 11 #define D7 2 #define D6 3 #define D5 4 #define D4 5 //Pino de saída de toques sonoros #define PTONE 10 //Pinos dos botões #define UP 6 #define DN 7 #define NX 8 #define OK 9 //Pino de saída dos LEDs de aviso #define LED 13 //Ponos dos LEDs de indicação de algarismo #define P1 A0 //LED de posição do primeiro dígito #define P2 A1 //LED de posição do segundo dígito #define P3 A2 //LED de posição do terceiro dígito #define P4 A3 //LED de posição do quarto dígito //Inclusão da biblioteca do display LCD #include //Declaração de variáveis globais int resultado, dg = 0, dg1 = 0, dg2 = 0, dg3 = 0, dg4 = 0, opc, res, x, y, z, score = 0, apagar = 0, pts = 10, nivel = 1, rx = 9, rz = 10, oper = 2, over = 0, fr = 660, t = 30; //Variáveis de leitura dos botões bool btUp = true, btDn = true, btNx = true, btOk = true; //------Caractere especial para LCD----------- byte coin[8]={ 0b00100, 0b01010, 0b10001, 0b10111, 0b11101, 0b10001, 0b01010, 0b00100 }; //Objeto do display LCD LiquidCrystal lcd(RS, EN, D4, D5, D6, D7); void setup() { lcd.clear(); //Elimina qualquer resíduo gráfico da tela lcd.createChar(1, coin); //Criação do caractere especial lcd.begin(16, 2); //Inicialização do display LCD 16 linhas e 2 colunas //Pinos definidos como entradas digitais pinMode(UP, INPUT); pinMode(DN, INPUT); pinMode(NX, INPUT); pinMode(OK, INPUT); //Pinos definidos como saídas digitais pinMode(LED, OUTPUT); pinMode(P1, OUTPUT); pinMode(P2, OUTPUT); pinMode(P3, OUTPUT); pinMode(P4, OUTPUT); //Inicialização do LED de aviso digitalWrite(LED, LOW); //Inicialização dos LEDs de posições dos dígitos digitalWrite(P1, HIGH); digitalWrite(P2, LOW); digitalWrite(P3, LOW); digitalWrite(P4, LOW); randomSeed(analogRead(4)); //Ruído da porta analógica para gerar números aleatórios } void loop() { //Inicialização do jogo (Aparece apenas ao ligar ou reiniciar a placa) lcd.setCursor(0,0); //Faz com que os caracteres comecem a serem apresentados na coluna 0 e linha 0 lcd.print("_=JOGO TABUADA=_"); //Escreve o nome do jogo no display lcd.setCursor(0,1); //Faz com que os caracteres comecem a serem apresentados na coluna 0 e linha 1 lcd.print("Iniciando"); //Tempo ao iniciar com animação de pontinhos na tela for(int i = 9; i < 14; i++) { digitalWrite(LED, LOW); //Acende led de stop informando para aguardar lcd.setCursor(i,1); lcd.print("."); delay(500); } digitalWrite(LED, HIGH); //Acende led de start informando que o jogo pode ser iniciado tone(PTONE, 870, 30); //Tom sonoro de 870Hz e 30 milisegundos de duração que sairá pelo pino 10 lcd.clear(); //Limpa as informções do display LCD //Lógica e Design da tela LCD while(score < pts && over < 5) { //Gerar números aleatórios x = random(1, rx); //x pega um valor aleatório diferente de zero z = random(0, rz); //z pegar qualquer valor aleatório opc = random(1, oper); //Define a operação //Dependendo da opção sorteada e armazenada na variável 'opc' //teremos uma operação matemática para ser resolvida switch(opc) { case 1: y = x+z; //Operação de soma break; case 2: y = x*z; //Operação de multiplicação break; } //Design da tela do jogo //Informações na primeira linha dp display LCD lcd.setCursor(0, 0); //Nível do jogo lcd.print("N"); lcd.print(nivel); //Erros cometidos lcd.print(" E: "); lcd.print(over); //Pontuação conquistada lcd.print(" S: "); lcd.print(score); //Máxima pontuação para mudar de nível lcd.print("/"); lcd.print(pts); //Gera um tom sonoro de 870Hz de frequência e com duração de 30 milisegundos tone(PTONE, 870, 30); //Informações na segunda linha do display LCD lcd.setCursor(0, 1); lcd.print("R: "); lcd.print(x); //Primeiro valor da operação //Dependendo da operação sorteada, o display apresentará o caractere adequado. if(opc == 1) lcd.print("+"); else lcd.print("X"); lcd.print(z); //Segundo valor da operação //Apresentação dos dígitos de tentativa de resposta lcd.print("="); lcd.setCursor(12, 1); lcd.print(dg4); lcd.setCursor(13, 1); lcd.print(dg3); lcd.setCursor(14, 1); lcd.print(dg2); lcd.setCursor(15, 1); lcd.print(dg1); //Laço de repetição aguardando resposta while(res == 0) { //Leitura dos botões btUp = digitalRead(UP); btDn = digitalRead(DN); btNx = digitalRead(NX); btOk = digitalRead(OK); delay(50); //Tempo como anti-bouncing //Cada vez que o botão de próximo digito for pressionado, os botões btUp e //btDn irão atuar sobre a unidade, dezena, centena ou milhar, dependendo do //valor da variável 'dg' if(!btNx) { dg++; if(dg > 3) dg = 0; //Acente o LED que indica qual dígito será alterado switch (dg) { case 0: //A unidade será alterada digitalWrite(P1, HIGH); digitalWrite(P2, LOW); digitalWrite(P3, LOW); digitalWrite(P4, LOW); break; case 1: //A dezena será alterada digitalWrite(P1, LOW); digitalWrite(P2, HIGH); digitalWrite(P3, LOW); digitalWrite(P4, LOW); break; case 2: //A centena será alterada digitalWrite(P1, LOW); digitalWrite(P2, LOW); digitalWrite(P3, HIGH); digitalWrite(P4, LOW); break; case 3: //A milhar será alterada digitalWrite(P1, LOW); digitalWrite(P2, LOW); digitalWrite(P3, LOW); digitalWrite(P4, HIGH); break; } //Anti-bouncing, evita efeito de trepidação do botão ao ser pressionado while(!btNx) btNx = digitalRead(8); } //Alteração do valor de cada dígito switch(dg) { case 0: //Alteração da unidade if(!btUp) { dg1++; //Incrementa o valor if(dg1 > 9) dg1 = 0; //Se o valor for maior que 9, muda para zero while(!btUp) btUp = digitalRead(6); //Anti-bouncing } else if(!btDn) { dg1--; //Decrementa o valor if(dg1 < 0) dg1 = 9; //Se o valor for menor que zero, muda para 9 while(!btDn) btDn = digitalRead(7); //Anti-bouncing } break; case 1: //Alteração da dezena if(!btUp) { dg2++; if(dg2 > 9) dg2 = 0; while(!btUp) btUp = digitalRead(6); } else if(!btDn) { dg2--; if(dg2 < 0) dg2 = 9; while(!btDn) btDn = digitalRead(7); } break; case 2: //Alteração da centena if(!btUp) { dg3++; if(dg3 > 9) dg3 = 0; while(!btUp) btUp = digitalRead(6); } else if(!btDn) { dg3--; if(dg3 < 0) dg3 = 9; while(!btDn) btDn = digitalRead(7); } break; case 3: //Alteração da milhar if(!btUp) { dg4++; if(dg4 > 9) dg4 = 0; while(!btUp) btUp = digitalRead(6); } else if(!btDn) { dg4--; if(dg4 < 0) dg4 = 9; while(!btDn) btDn = digitalRead(7); } break; } //Apresentação dos algarismos digitados como opção de resposta lcd.setCursor(12, 1); lcd.print(dg4); lcd.setCursor(13, 1); lcd.print(dg3); lcd.setCursor(14, 1); lcd.print(dg2); lcd.setCursor(15, 1); lcd.print(dg1); if(!btOk) { //Juntando unidade, dezena, centena e milhar para a formação do //valor de resposta res = 1000*dg4 + 100*dg3 + 10*dg2 + dg1; //Zera as variáveis de cada algarismo dg1 = dg2 = dg3 = dg4 = 0; while(!btOk) btOk = digitalRead(9); lcd.clear(); } } //Quando a resposta é correta if(res == y) { score++; tone(PTONE, 560, 10); tone(PTONE, 550, 8); lcd.setCursor(0, 0); lcd.print("PARABENS!!! "); lcd.write((byte)1); //Desenha a moeda (caractere criado no setup()) lcd.setCursor(0, 1); lcd.print("R: "); lcd.print(y); //Mostra a resposta esperada lcd.print(" Pts: "); lcd.print(score); //Mostra a pontuação conquistada delay(3000); lcd.clear(); res = dg = 0; //Zera as variáveis //Zera a posição dos dígitos para o algarismo da unidade digitalWrite(P1, HIGH); digitalWrite(P2, LOW); digitalWrite(P3, LOW); digitalWrite(P4, LOW); } else { //Quando a resposta está errada tone(PTONE, 440, 100); //Tom de 440Hz por 100 milisegundos over++; //Incrementa valor para Game Over lcd.setCursor(0, 0); lcd.print("Ops! errou"); lcd.setCursor(0, 1); lcd.print("Resposta: "); lcd.print(y); //Mostra qual seria a resposta correta res = dg = 0; digitalWrite(LED, LOW); delay(3000); digitalWrite(LED, HIGH); lcd.clear(); //Zera a posição dos dígitos digitalWrite(P1, HIGH); digitalWrite(P2, LOW); digitalWrite(P3, LOW); digitalWrite(P4, LOW); } } lcd.clear(); //Pontuação Máxima para mudar de nível if(score == pts) { for(int i = 0; i < 4; i++) { tone(PTONE, 550, 8); lcd.setCursor(0,0); lcd.print("PARABENS! "); lcd.write((byte)1); lcd.write((byte)1); lcd.write((byte)1); lcd.setCursor(0,1); lcd.print("_=VOCE PASSOU!=_"); lcd.blink(); //Comemoração. Alterna entre os LEDs vermelho e verde e //Reproduz sons com frequência e tempos diferentes digitalWrite(LED, LOW); tone(PTONE, 560, 10); delay(500); digitalWrite(LED, HIGH); tone(PTONE, 550, 8); delay(500); digitalWrite(LED, LOW); tone(PTONE, 560, 20); delay(500); digitalWrite(LED, HIGH); tone(PTONE, 550, 8); delay(500); score = 0; over = 0; } lcd.noBlink(); pts += 10; //Eleva a meta de pontuação para mais 10 pontos nivel++; //Muda de nível rx += 5; //Aumenta os valores para cálculos x rz += 10; //Aumenta os valores para cálculos y oper++; //Aumenta a quantidade de operações if(oper > 3) oper = 3; lcd.clear(); } //Game Over------------------------------------- else if(over >= 5) { tone(PTONE, 330, 100); lcd.setCursor(0, 0); lcd.print("_>GAME OVER!!!<_"); lcd.setCursor(0, 1); lcd.print("Pts: "); lcd.print(score); lcd.print(" N: "); lcd.print(nivel); //Reproduz um som de reprovação por 10 vezes for(int i = 0; i < 10; i++) { tone(PTONE, 330, 100); } //Alterna entre os LEDs digitalWrite(LED, HIGH); delay(6000); digitalWrite(LED, LOW); //Reinicia as variáveis do jogo pts = 10; nivel = 1; rx = 9; rz = 10; score = 0; over = 0; lcd.clear(); } }