Tente acertar a sequência de cores

Criando um Game Genius com Arduino.

#arduino, #iot - 20 de agosto de 2017

Lançado em 1980 pela Estrela, o Genius era a versão brasileira do brinquedo americano Simon produzido pela Hasbro. E é considerado o primeiro jogo eletrônico comercializado no Brasil. O game busca estimular a memorização através de sequências de cores e sons. Cabendo ao jogador tentar reproduzir essas sequências na mesma ordem em que lhe é apresentada.

Em minha pesquisa no Programa de Iniciação Científica da faculdade, me propus a realizar alguns experimentos com Arduino. Criar um game Genius foi um deles (em breve postarei os outros), já que queria que algum deles fosse um jogo. Para voltarmos no tempo e reproduzirmos esse saudoso game, precisaremos dos seguintes componentes:

  • Arduino Uno R3 com cabo USB
  • Protoboard
  • 4 Resistores de 220 Ohm
  • 4 LEDs 4mm, sendo:
    • 1 LED vermelho
    • 1 LED azul
    • 1 LED verde
    • 1 LED amarelo
  • 4 botões de 2 ou 4 pinos
  • Jumpers
  • Speaker

Eis o esquema do projeto:

Há uma infinidade de formas de se programar e colocar tudo isso para funcionar. No meu caso utilizei a IDE Arduino e código logo abaixo. Mas, você pode utilizar outra IDE e adaptar o código da maneira que achar mais conveniente.

Código:

// Definindo os componentes de acordo com as portas:
#define LED_VERDE 2
#define LED_VERMELHO 3
#define LED_AMARELO 4
#define LED_AZUL 5
#define BOTAO_VERDE 8
#define BOTAO_VERMELHO 9
#define BOTAO_AMARELO 10
#define BOTAO_AZUL 11
#define BUZZER 13

//Definindo variáveis 
#define INDEFINIDO -1
#define UM_SEGUNDO 1000
#define MEIO_SEGUNDO 500
#define UM_QUARTO_DE_SEGUNDO 250

//Aqui definimos a quantidade de sequências(rodadas) que o jogo terá
#define TAMANHO_SEQUENCIA 5

//Enumerando os estados do jogo
enum Estados {
  PRONTO_PARA_PROXIMA_RODADA,
  USUARIO_RESPONDENDO,
  JOGO_FINALIZADO_SUCESSO,
  JOGO_FINALIZADO_FALHA
};

//Iniciando váriaveis e Portas
int sequenciaLuzes[TAMANHO_SEQUENCIA];
int rodada = 0;
int ledsRespondidos = 0;

void setup() {
  Serial.begin(9600);
  iniciaPortas();
  iniciaJogo();
}

void iniciaPortas() {
  pinMode(LED_VERDE, OUTPUT);
  pinMode(LED_AMARELO, OUTPUT);
  pinMode(LED_VERMELHO, OUTPUT);
  pinMode(LED_AZUL, OUTPUT);

  pinMode(BOTAO_VERDE, INPUT_PULLUP);
  pinMode(BOTAO_AMARELO, INPUT_PULLUP);
  pinMode(BOTAO_VERMELHO, INPUT_PULLUP);
  pinMode(BOTAO_AZUL, INPUT_PULLUP);

  pinMode(BUZZER, OUTPUT);
}

//Pisca led
int piscaLed(int portaLed) {
  verificaSomDoLed(portaLed);
  digitalWrite(portaLed,HIGH);
  delay(UM_SEGUNDO);
  digitalWrite(portaLed,LOW);
  delay(UM_QUARTO_DE_SEGUNDO);
  return portaLed;
}

//Toca Som
void tocaSom(int frequencia) {
  tone(BUZZER,frequencia, 100);
}

//Associando som aos leds
void verificaSomDoLed(int portaLed) {
  switch (portaLed) {
    case LED_VERDE:
      tocaSom(2000);
      break;
    case LED_AMARELO:
      tocaSom(2200);
      break;
    case LED_VERMELHO:
      tocaSom(2400);
      break;
    case LED_AZUL:
      tocaSom(2500);
      break;
  }
}

//  --- O JOGO ---
//Função para iniciar o jogo
void iniciaJogo() {
  
  int jogo = analogRead(0);
  randomSeed(jogo);

  for (int i = 0; i < TAMANHO_SEQUENCIA; i++) {
    sequenciaLuzes[i] = sorteiaCor();
  }
}

int sorteiaCor() {
  return random(LED_VERDE, LED_AZUL + 1);
}

void loop() {
  switch (estadoAtual()) {
    case PRONTO_PARA_PROXIMA_RODADA:
      Serial.println("Pronto para a proxima rodada");
      preparaNovaRodada();
      break;
    case USUARIO_RESPONDENDO:
      Serial.println("Usuario respondendo");
      processaRespostaUsuario();
      break;
    case JOGO_FINALIZADO_SUCESSO:
      Serial.println("Jogo finalizado com sucesso");
      jogoFinalizadoSucesso();
      break;
    case JOGO_FINALIZADO_FALHA:
      Serial.println("Jogo finalizado com falha");
      jogoFinalizadoFalha();
      break;
  }
  delay(MEIO_SEGUNDO);
}

//Nova Rodada em caso de acerto
void preparaNovaRodada() {
  rodada++;
  ledsRespondidos = 0;
  if (rodada <= TAMANHO_SEQUENCIA) {
    tocaLedsRodada();
  }
}

void processaRespostaUsuario() {
  int resposta = checaRespostaJogador();
  if (resposta == INDEFINIDO) {
    return;
  }
  if (resposta == sequenciaLuzes[ledsRespondidos]) {
    ledsRespondidos++; 
  } else {
    Serial.println("Sequencia errada");
    rodada = TAMANHO_SEQUENCIA + 2;
  }
}

//Loop para iniciar uma nova rodada
int estadoAtual() {
  if (rodada <= TAMANHO_SEQUENCIA) {
    if (ledsRespondidos == rodada) {
      return PRONTO_PARA_PROXIMA_RODADA; 
    } else {
      return USUARIO_RESPONDENDO;
    }
  } else if (rodada == TAMANHO_SEQUENCIA + 1) {
    return JOGO_FINALIZADO_SUCESSO;
  } else {
    return JOGO_FINALIZADO_FALHA;
  }
}

void tocaLedsRodada() {
  for (int i = 0; i < rodada; i++) {
    piscaLed(sequenciaLuzes[i]);
  }
}

//Checagem de resposta
int checaRespostaJogador() {
  if (digitalRead(BOTAO_VERDE) == LOW) {
    return piscaLed(LED_VERDE);
  }
  if (digitalRead(BOTAO_AMARELO) == LOW) {
    return piscaLed(LED_AMARELO);
  }
  if (digitalRead(BOTAO_VERMELHO) == LOW) {
    return piscaLed(LED_VERMELHO);
  }
  if (digitalRead(BOTAO_AZUL) == LOW) {
    return piscaLed(LED_AZUL);
  }
  return INDEFINIDO;
}

//Fim de jogo - Vitória
void jogoFinalizadoSucesso() {
  delay(UM_QUARTO_DE_SEGUNDO);
  tocaSom(5000);
  piscaLed(LED_VERDE);
  tocaSom(5000);
  piscaLed(LED_VERMELHO);
  tocaSom(5000);
  piscaLed(LED_AMARELO);
  tocaSom(5000);
  piscaLed(LED_AZUL); 
}

//Fim de jogo - Derrota
void jogoFinalizadoFalha() {
  delay(MEIO_SEGUNDO);
  tocaSom(400);
  digitalWrite(LED_VERDE,HIGH);
  digitalWrite(LED_AMARELO,HIGH);
  digitalWrite(LED_VERMELHO,HIGH);
  digitalWrite(LED_AZUL,HIGH);
  delay(MEIO_SEGUNDO);
  digitalWrite(LED_VERDE,LOW);
  digitalWrite(LED_AMARELO,LOW);
  digitalWrite(LED_VERMELHO,LOW);
  digitalWrite(LED_AZUL,LOW);
  delay(MEIO_SEGUNDO);
}

Créditos da imagem do header: Instructables.


05-08-2018 | Update:

É possivel que se tenha alguns problemas (identação por exemplo) ao copiar e colar o código. Por isso, estou deixando o link para quem quiser baixar o projeto no Github. E também do simulador virtual Tinkercad.

11-12-2019 | Update:

Para quem quer aprender um pouco mais e se aventurar em novos projetos, sugiro dar uma conferida no Brain. Que é o blog da loja de componentes eletrônicos Eletrogate. Eles possuem um conteúdo bem rico sobre Arduino, além de tutoriais super bacanas.