Jogo Genius com Arduíno UNO

Olá, como estão? Hoje iremos desenvolver um jogo chamado Genius com um Arduíno UNO, para isso irá ser usado o KIT iniciante com Arduíno UNO da WJ Componentes.

Arduíno UNO
LED Difuso

Componentes Utilizados


OU

Funcionamento do Projeto Jogo Genius


A principio iremos desenvolver no Arduíno UNO, um jogo chamado Genius, caso não conheça clique aqui para ver um vídeo.

Montagem do Projeto Jogo Genius


Logo após compra dos componentes na WJ Componentes, vamos à montagem! Em seguida conectamos os LEDs na protoboard com os resistores que ligamos nos catodos dos LEDs. Portanto para finalizar ligamos o anodo dos LEDs nos pinos 2 , 3, 8 e 9 do Arduíno UNO. Do mesmo modo conectamos os botões na protoboard e ligamos o GND de um lado e do outro ligamos nos pinos 4, 5, 6 e 7 do Arduíno UNO. Sendo assim para finalizar ligamos o GND do Arduíno UNO na protoboard.

Obs.: Cuidado ao conectar os botões, dependendo a forma que conecte eles podem não funcionar corretamente.

Dessa forma segue abaixo uma imagem que demonstrando a montagem do circuito.

Montagem do Circuito Eletrônico na Protoboard do Jogo Genius

Diagrama Esquemático do Projeto Jogo Genius


Diagrama do Circuito Eletrico do Jogo Genius

Código-fonte do Projeto Jogo Genius


Em seguida segue abaixo o código completo do projeto Genius.

//Definições de Pinos --------------------------------------------------------------------------------
byte led[4] = {9, 8, 2, 3};                                  // Define os pinos dos LED
byte btn[4] = {7, 6, 4, 5};                                  // Define os pinos dos Botões
	 
//Variáveis Globais ----------------------------------------------------------------------------------
byte score;                                                   // Armazena a pontuação
byte sequencia[100] = {};                                     // Armazena a sequência
byte rodadaAtual = 0;                                         // Armazena a rodadaAtual
byte passoSequencia = 0;                                      // Armazena o próximo passo da sequência
byte botaoPressionado = 0;                                    // Armazena o botão pressionado
bool startGame = false;                                       // Armazena se o jogo iniciou ou não
	 
//Funções Auxiliares ---------------------------------------------------------------------------------
void gameStart();                                             // Responsável pelo Star do jogo
void proximaRodada();                                         // Responsável pelo LED seguinte
void aguardarJogador();                                       // Responsável por esperar o jogador
void aguardarJogada();                                        // Responsável por espera a jogada
void verificarJogada();                                       // Responsável por verificar errou
void reproduzirSequencia();                                   // Responsável por reproduzir sequencia
void piscaLed();                                              // Responsável por piscar os LEDs
	 
//Setup ----------------------------------------------------------------------------------------------
void setup() {
    //Configuração dos LEDs
    for (byte i = 0; i < 4; i++) {                            // Cria um loop para cada LED
        pinMode(led[i], OUTPUT);                              // Configura os LED como OUTPUT
    }
    //Configuração dos Botões
    for (byte i = 0; i < 4; i++) {                            // Cria um loop para cada botão
        pinMode(btn[i], INPUT_PULLUP);                        // Configura os botões como INPUT_PULLUP
    }
}
 
//Loop -----------------------------------------------------------------------------------------------
void loop() {
    for (byte i = 0; i < 4; i++) {                            // Cria loop verificando cada botão
        if (!digitalRead(btn[i]) && !startGame) {             // Se os botões e se startGame = false
            gameStart();                                      // Chama função gameStart()
        }
    }
    if (startGame) {                                          // Verifica se startGame = true
        score++;                                              // Incrementa score +1
        proximaRodada();                                      // Chama função proximaRodada()
        reproduzirSequencia();                                // Chama função reproduzirSequencia()
        aguardarJogador();                                    // Chama função aguardarJogador()
        delay(1000);                                          // Espera 1s
    }
    delay(10);                                                // Espera 0,01s
}

//Game Start -----------------------------------------------------------------------------------------
void gameStart() {
    piscaLed();                                               // Chama função piscaLed()
    byte sequencia[100] = {};                                 // Limpa variável sequencia
    rodadaAtual = 0;                                          // Limpa variável rodadaAtual
    passoSequencia = 0;                                       // Limpa variável passoSequencia
    startGame = true;                                         // Atribui a startGame true
    score = -1;                                               // Atribui a score -1
}

//Próxima Rodada -------------------------------------------------------------------------------------
void proximaRodada() {
    byte num = random(0, 4);                                  // Atribui a num valor de 0 a 4
    sequencia[rodadaAtual++] = num;                           // Atribui a sequência num
}

//Reproduz Sequencia ---------------------------------------------------------------------------------
void reproduzirSequencia() {
    for (byte i = 0; i < rodadaAtual; i++) {                  // Cria um loop com a rodadaAtual
        digitalWrite(led[sequencia[i]], HIGH);                // Liga o LED da sequência atual
        delay(500);                                           // Espera 0,5s
        digitalWrite(led[sequencia[i]], LOW);                 // Desliga o LED da sequência atual
        delay(100);                                           // Espera 0,1s
    }
}

//Aguarda Jogador ------------------------------------------------------------------------------------
void aguardarJogador() {
    for (byte i = 0; i < rodadaAtual; i++) {                  // Cria um loop com a rodada Atual
        aguardarJogada();                                     // Chama função aguardarJogada()
        verificarJogada();                                    // Chama função verificarJogada()
        if (!startGame) {                                     // Verifica se startGame = false
            break;                                            // Se for sai do loop
        }
        passoSequencia++;                                     // Se não atribui +1 a passoSequencia
    }
    passoSequencia = 0;                                       // Redefine a variável para 0.
}

//Aguarda Jogada -------------------------------------------------------------------------------------
void aguardarJogada() {
    bool jogadaEfetuada = false;                              // Declara uma variável e atribui false
    while (!jogadaEfetuada) {                                 // Loop até que a jogadaEfetuada = true
        for (byte i = 0; i < 4; i++) {                        // Cria um loop para cada botão
            if (!digitalRead(btn[i])) {                       // Dizendo qual foi o botão pressionado
                botaoPressionado = i;                         // Atribui o valor de i
                digitalWrite(led[i], HIGH);                   // Liga o LED
                delay(300);                                   // Espera 0,3s
                digitalWrite(led[i], LOW);                    // Desliga o LED
                jogadaEfetuada = true;                        // Atribui a jogadaEfetuada true
            }
	    }
	    delay(10);                                              // Espera 0,01s
    }
}
	 
//Verifica Jogada ------------------------------------------------------------------------------------
void verificarJogada() {
    if (sequencia[passoSequencia] != botaoPressionado) {      // Se o botão clicado foi errado
        piscaLed();                                           // Chama função piscaLed()
        delay(1000);                                          // Espera 1s
        for(byte i = 0; i<score; i++){                     // Cria um loop da quantidade de pontos
            digitalWrite(led[0], HIGH);                       // Liga o LED
            delay(500);                                       // Espera 0,5s
            digitalWrite(led[0], LOW);                        // Desliga o LED
            delay(500);                                       // Espera 0,5s
        }
        piscaLed();                                           // Chama função piscaLed()
        startGame = false;                                    // Atribui starGame
    }
}
 
//Pisca LED ------------------------------------------------------------------------------------------
void piscaLed() {
    for (byte i = 0; i <= 11; i++) {                        // Cria um loop de 11 vezes
        for (byte j = 0; j < 4; j++) {                      // Cria um loop para cada LED
            digitalWrite(led[j], !digitalRead(led[j]));     // Inverte sinal dos LED
        }
	      delay(250);                                         // Espera 0,25s
    }
}

Vamos dar uma olhada mais de perto no código:

Definições de Pinos

Em primeiro lugar temos que definir os pinos que iremos usar em nosso projeto.

//Definições de Pinos --------------------------------------------------------------------------------
byte led[4] = {9, 8, 2, 3};                                 // Define os pinos dos LED
byte btn[4] = {7, 6, 4, 5};                                 // Define os pinos dos Botões

Variáveis Globais

Em seguida declaramos 6 variáveis globais. Sendo elas score que armazenará a pontuação, sequencia responsável pelos LEDs, rodadaAtual que armazenará a rodada atual, passoSequencia responsável pela próximo sequência, botaoPressionado responsável pelo botão. Por fim temos a variável startGame que é responsável por armazenar a informação do início do jogo.

//Variáveis Globais ----------------------------------------------------------------------------------
byte score;                                                 // Armazena a pontuação
byte sequencia[100] = {};                                   // Armazena a sequência
byte rodadaAtual = 0;                                       // Armazena a rodadaAtual
byte passoSequencia = 0;                                    // Armazena o próximo passo da sequência
byte botaoPressionado = 0;                                  // Armazena o botão pressionado
bool startGame = false;                                     // Armazena se o jogo iniciou ou não

Funções Auxiliares

Agora declaramos as 7 funções auxiliares, para assim dividir o código, para que assim ele fique mais organizado. A primeira delas é a gameStart, responsável por limpar as variáveis, para que assim possamos inicializar o jogo. Em seguida declaramos a função proximaRodada, responsável por escolher aleatoriamente o próximo LED que irá acender. Da mesma forma declaramos as funções aguardarJogador, aguardarJogada e verificaJogada, responsável por esperar o jogador realizar a jogada e realizar a verificação da jogada. Por fim temos duas funções sendo elas reproduzirSequencia, responsável por acender os LEDs na sequência e a função piscaLed, responsável por piscar os LEDs.

//Funções Auxiliares ---------------------------------------------------------------------------------
void gameStart();                                           // Responsável pelo Star do jogo
void proximaRodada();                                       // Responsável pelo LED seguinte
void aguardarJogador();                                     // Responsável por esperar o jogador
void aguardarJogada();                                      // Responsável por espera a jogada
void verificarJogada();                                     // Responsável por verificar errou
void reproduzirSequencia();                                 // Responsável por reproduzir sequencia
void piscaLed();                                            // Responsável por piscar os LEDs

Funções Setup

Além disso na função setup, será onde iremos configurar os pinos dos LEDs como OUTPUT a partir de um loop. Também configuramos os pinos dos botões como INPUT_PULLUP, para que assim não seja necessário utilizar mais um jumper, por este motivo o sinal do botão é invertido.

//Setup ----------------------------------------------------------------------------------------------
void setup() {
    //Configuração dos LEDs
    for (byte i = 0; i < 4; i++) {                          // Cria um loop para cada LED
        pinMode(led[i], OUTPUT);                            // Configura os LED como OUTPUT
    }
    //Configuração dos Botões
    for (byte i = 0; i < 4; i++) {                          // Cria um loop para cada botão
        pinMode(btn[i], INPUT_PULLUP);                      // Configura os botões como INPUT_PULLUP
    }
}

Funções Loop

Agora na função loop, criamos um loop para verificar se algum dos botões foi clicado e se startGame é igual a falso, caso seja chamamos a função gameStart, para que assim possamos limpar todas as variáveis, ou seja, iremos se preparar para inicializar o jogo.

//Loop -----------------------------------------------------------------------------------------------
void loop() {
    for (byte i = 0; i < 4; i++) {                          // Cria loop verificando cada botão
        if (!digitalRead(btn[i]) && !startGame) {           // Se os botões e se startGame = false
            gameStart();                                    // Chama função gameStart()
        }
    }

Logo depois, realizamos outra verificação se startGame é igual a true, caso seja quer dizer que o jogo foi inicializado com sucesso. Por isso chamamos as funções proximaRodada, reproduzirSequencia, aguardarJogada e esperamos 1 segundo.

    if (startGame) {                                        // Verifica se startGame = true
        score++;                                            // Incrementa score +1
        proximaRodada();                                    // Chama função proximaRodada()
        reproduzirSequencia();                              // Chama função reproduzirSequencia()
        aguardarJogador();                                  // Chama função aguardarJogador()
        delay(1000);                                        // Espera 1s
    }
    delay(10);                                              // Espera 0,01s
}

Funções gameStart

Em seguida vamos para a função gameStart, ela é responsável por limpar todas as variáveis para o início do jogo, para demonstrar que o jogo irá começar, após iremos chamar a função piscaLed, e então vamos limpar as variáveis.

//Game Start -----------------------------------------------------------------------------------------
void gameStart() {
    piscaLed();                                             // Chama função piscaLed()
    byte sequencia[100] = {};                               // Limpa variável sequencia
    rodadaAtual = 0;                                        // Limpa variável rodadaAtual
    passoSequencia = 0;                                     // Limpa variável passoSequencia
    startGame = true;                                       // Atribui a startGame true
    score = -1;                                             // Atribui a score -1
}

Funções proximaRodada

Em seguida vamos para a função proximaRodada, ela é responsável por escolher um LED aleatoriamente que irá acender na próxima rodada. Sendo assim iremos declarar uma nova variável do tipo byte chamada num e atribuímos um número aleatório entre 0 a 4, em seguida atribuímos a sequência[rodadaAtual++] o valor de num.

//Próxima Rodada -------------------------------------------------------------------------------------
void proximaRodada() {
    byte num = random(0, 4);                                // Atribui a num valor de 0 a 4
    sequencia[rodadaAtual++] = num;                         // Atribui a sequência num
}

Funções reproduzirSequencia

Agora vamos para a função reproduzirSequencia, ela é responsável por reproduzir toda a sequência ligando os LEDs, para isso criamos um loop com o número de vezes igual ao número da rodadaAtual e ligamos o LED correspondente, após isso esperamos 0,5 segundos, em seguida desligamos os LEDs e esperamos mais 0,1 segundo.

//Reproduz Sequencia ---------------------------------------------------------------------------------
void reproduzirSequencia() {
    for (byte i = 0; i < rodadaAtual; i++) {             // Cria um loop com a rodadaAtual
        digitalWrite(led[sequencia[i]], HIGH);             // Liga o LED da sequência atual
        delay(500);                                        // Espera 0,5s
        digitalWrite(led[sequencia[i]], LOW);              // Desliga o LED da sequência atual
        delay(100);                                        // Espera 0,1s
    }
}

Funções aguardarJogador

Do mesmo modo vamos para a função aguardaJogardor, ela é responsável por aguardar a jogador, assim criamos um for com número de vezes igual a rodadaAtual, após isso chamamos as funções aguardarJogada e verificarJogada, e iremos verificar se startGame é igual a false, se sim saímos do for e atribuímos 0 a passoSequencia, se não for incrementamos +1 na variável passoSequencia.

//Aguarda Jogador ---------------------------------------------------------------------------------
void aguardarJogador() {
    for (byte i = 0; i < rodadaAtual; i++) {                // Cria um loop com a rodada Atual
        aguardarJogada();                                   // Chama função aguardarJogada()
        verificarJogada();                                  // Chama função verificarJogada()
        if (!startGame) {                                   // Verifica se startGame = false
            break;                                          // Se for sai do loop
        }
        passoSequencia++;                                   // Se não atribui +1 a passoSequencia
    }
    passoSequencia = 0;                                     // Redefine a variável para 0.
}

Funções aguardarJogada

Agora na função aguardaJogada, ela é responsável por esperar a jogada do jogador, para isso é declarada uma variável chamada jogadaEfetuada e é atribuída falsa a ela, em seguida criamos um loop até que jogadaEfetuada seja igual a true em seguida fazemos outro loop onde será verificado todos os botões e atribuímos i a variável botaoPressionado, após isso é ligado o LED, espera 0,3 segundos, desligar o LED e para finalizar iremos atribuir a jogadaEfetuada true.

//Aguarda Jogada ----------------------------------------------------------------------------------
void aguardarJogada() {
    bool jogadaEfetuada = false;                            // Declara uma variável e atribui false
    while (!jogadaEfetuada) {                               // Loop até que a jogadaEfetuada = true
        for (byte i = 0; i < 4; i++) {                      // Cria um loop para cada botão
            if (!digitalRead(btn[i])) {                     // Dizendo qual foi o botão pressionado
                botaoPressionado = i;                       // Atribui o valor de i
                digitalWrite(led[i], HIGH);                 // Liga o LED
                delay(300);                                 // Espera 0,3s
                digitalWrite(led[i], LOW);                  // Desliga o LED
                jogadaEfetuada = true;                      // Atribui a jogadaEfetuada true
            }
	    }
	    delay(10);                                            // Espera 0,01s
    }
}

Funções verificarJogada

Então agora na função verificaJogada, ela é responsável por verificar se o usuário apertou o botão correto, para isso temos que verificar se o botão pressionado é errado, se sim é fim de jogo, portanto esperamos 1 segundo, criamos um for e piscamos um LED a quantidade de vezes igual à quantidade de score, para que assim o usuário saiba quantos acertos teve, em seguida será chamado a função piscarLed e atribuímos false a startGame.

//Verifica Jogada -------------------------------------------------------------------------------
void verificarJogada() {
    if (sequencia[passoSequencia] != botaoPressionado) {    // Se o botão clicado foi errado
        piscaLed();                                         // Chama função piscaLed()
        delay(1000);                                        // Espera 1s
        for(byte i = 0; i < score; i++){                    // Cria um loop da quantidade de pontos
            digitalWrite(led[0], HIGH);                     // Liga o LED
            delay(500);                                     // Espera 0,5s
            digitalWrite(led[0], LOW);                      // Desliga o LED
            delay(500);                                     // Espera 0,5s
        }
        piscaLed();                                         // Chama função piscaLed()
        startGame = false;                                  // Atribui starGame
    }
}

Funções piscaLed

Por fim vamos para a função piscaLed, ela é responsável por piscar os LEDs, para isso criamos um loop de 11 vezes, dentro dele criamos outro loop de 4 vezes, para assim piscar todos os LEDs, dentro do loop invertemos o sinal de todos os LEDs e esperar 0,25 segundos.

//Pisca LED -------------------------------------------------------------------------------------
void piscaLed() {
    for (byte i = 0; i <= 11; i++) {                        // Cria um loop de 11 vezes
        for (byte j = 0; j < 4; j++) {                      // Cria um loop para cada LED
            digitalWrite(led[j], !digitalRead(led[j]));     // Inverte sinal dos LED
        }
	    delay(250);                                           // Espera 0,25s
    }
}

Assim finalizamos o código-fonte com a explicação sobre o projeto Genius com Arduíno UNO.

Resultado do Projeto Jogo Genius


Por fim esse foi o resultado obtido com nosso projeto do Jogo Genius.

Agradecemos sua presença


Por fim, espero que tenham gostado e aprendido. Então compartilhem com seus colegas e deixe um comentário de qual projeto deveria ser o próximo aqui no Blog da WJ Componentes!
Enfim estarei deixando o arquivo Arduíno e Fritzing, link dos posts anteriores referentes ao projeto, software e sites utilizados.
Fique à vontade para tirar suas dúvidas nos comentários.

Software e Sites Utilizados

Post Relacionados

Posts mais Recentes

Julio Cesar Bonow Manoel

Julio Cesar Bonow Manoel

Cursando Engenharia da Computação pelo Centro Universitário Facens e atua no desenvolvimento de projetos na WJ Componentes. Participante da equipe de robótica Omegabotz.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *