Voltar ao Catálogo
Matemática

Jogo da tabuada

Responda a perguntas matemáticas e veja os resultados em um display.

Código Fonte Arduino (.INO)

Código Arduino Jogo da Tabuada (.INO)
Baixar .INO

Código C++ principal para o Jogo da Tabuada em tela LCD/display.

/************************************************
* 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<LiquidCrystal.h>

//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();
  }
} 

Materiais Didáticos & Documentos

Tutorial Didático - Jogo da Tabuada (PDF)
Tutorial Didático Guia passo a passo de montagem, circuito e roteiro pedagógico.
Baixar Arquivo
Quer este projeto em sua escola?

A WETECH disponibiliza kits de hardware prontos, roteiros de aulas alinhados à BNCC e formação continuada de educadores.

Solicitar Orçamento Escolar