11 de abril de 2014

Genius (Simon Game)


Quem não lembra desse clássico jogo da memória? O jogador precisa repetir a sequência exibida, e a cada acerto vai ficando mais difícil. Um bom passatempo e um ótimo exercício pra cabeça!

O jogo memoriza a pontuação máxima. Assim você pode verificar qual foi o seu recorde. Para isso, basta ligar o jogo com o botão do led verde pressionado. Isso fará com que o led pisque o número de vezes da pontuação recorde. Se quiser resetar a memória, mantenha o botão pressionado até o led parar de piscar. E quando um recorde de pontuação for batido, ao final do jogo o led verde piscará.
Então o objetivo é ver o led verde piscar! É recorde de pontuação batido!

Fiz o circuito utilizando a plataforma Arduino, e montei numa placa de fenolite de 8x7 cm.



Segue o esquema elétrico do circuito e o código fonte do microcontrolador.

Abraços!


/*-----------------------------
 Programa : GENIUS (SIMON GAME)
 Autor    : Fellipe Couto
 Data     : 04/04/2014
 -----------------------------*/

#include <EEPROM.h> //Biblioteca da memória EEPROM

long previousMillis = 0;
long interval = 1000; //Tempo do intervalo dentro do loop. 1000 milisegundos (1 segundo)
int timeControl = 0; //Controla o tempo de ociosidade
int led[4] = {12, 11, 10, 9}; //Pinos dos Leds
int but[4] = {5, 6, 7, 8}; //Pinos dos botões
int sequence[100]; //Array com a sequencia do jogo
int countGame = 0;
int countInput = 0;
int maxScore = EEPROM.read(0); //Retorna o valor do score armazenado na EEPROM
boolean play = true;

/*----- SETUP -----*/
void setup() {
  for (int i = 0; i < 4; i++) {
    pinMode(led[i], OUTPUT); //Configura os pinos como saída
    pinMode(but[i], INPUT); //Configura os pinos como entrada
  }
  randomSeed(analogRead(0)); //Para o random não repetir a sequencia
  score(); //Função para verificar e exibir a pontuação
  start(); //Inicia o jogo
}

/*----- LOOP PRINCIPAL -----*/
void loop() {
  unsigned long currentMillis = millis();

  //Intervalo de 1 segundo
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    timeControl++; //Incrementa a variável de controle de tempo
    if (timeControl >= 10) { //Ficando 10 segundos sem pressionar, inicia o jogo novamente
      start();
    }
  }

  if (play == true) {
    game();
  }
  else {
    player();
  }
}

/*----- SORTEIO DO JOGO -----*/
void game() {
  countGame++;
  sequence[countGame] = random(4); //de 0 a 3
  for (int i = 1; i <= countGame; i++) {
    digitalWrite(led[sequence[i]], HIGH);
    delay(400);
    digitalWrite(led[sequence[i]], LOW);
    delay(150);
  }
  play = false;
}

/*----- JOGADOR -----*/
void player() {
  int input = 4;
  int t = 300;

  //Leitura dos botões
  for (int b = 0; b < 4; b++) {
    if (digitalRead(but[b]) == 1) {
      digitalWrite(led[b], HIGH);
      delay(t);
      input = b;
    }
  }

  //Apaga todos os leds
  for (int i = 0; i < 4; i++) {
    digitalWrite(led[i], LOW);
  }

  if (input != 4) { //Se algum botão foi pressionado
    timeControl = 0;
    countInput++;
    if (sequence[countInput] != input) { //Errou a sequencia
      delay(t);
      blinkLeds(8, 150); //Pisca os leds indicando o erro
      score(); //Verifica a pontuação
      delay(3000);
      start(); //Inicia o jogo novamente
    }
    else if (countInput == countGame) { //Acertou a sequencia
      countInput = 0;
      play = true;
      delay(t);
      blinkLeds(1, 1000);
    }
  }
}

/*----- SEQUENCIA INICIAL DE PISCAR DOS LEDS -----*/
void start() {
  countGame = 0;
  countInput = 0;
  timeControl = 0;
  play = true;

  //Pisca os leds randomicamente
  for (int i = 0; i < 15; i++) {
    int x = random(4);
    digitalWrite(led[x], HIGH);
    delay(20);
    digitalWrite(led[x], LOW);
    delay(100);
  }

  //Apaga e acende os leds em sequencia
  for (int y = 0; y < 3; y++) {
    for (int i = 0; i < 4; i++) {
      digitalWrite(led[i], LOW);
      delay(80);
    }
    for (int i = 0; i < 4; i++) {
      digitalWrite(led[i], HIGH);
      delay(80);
    }
  }
  delay(1000);

  //Apaga todos os leds
  for (int i = 0; i < 4; i++) {
    digitalWrite(led[i], LOW);
  }
  delay(1000);
}

/*----- PISCA OS LEDS -----*/
void blinkLeds(int qtd, int t) {
  //qtd = quantidade de piscadas / t = tempo
  for (int y = 0; y < qtd; y++) {
    //Acende todos os leds
    for (int i = 0; i < 4; i++) {
      digitalWrite(led[i], HIGH);
    }
    delay(t);
    //Apaga todos os leds
    for (int i = 0; i < 4; i++) {
      digitalWrite(led[i], LOW);
    }
    delay(t);
  }
}

/*----- VERIFICA, EXIBE E GRAVA A PONTUAÇÃO -----*/
void score() {
  //Zera a EEPROM caso esteja acima de 100.
  if (maxScore > 100) {
    EEPROM.write(0, 0);
    maxScore = 0;
  }
  //Verifica a pontuação
  if (countGame - 1 > maxScore) {
    EEPROM.write(0, countGame - 1);
    maxScore = countGame - 1;
    for (int i = 0; i < 100; i++) {
      digitalWrite(led[0], HIGH);
      delay(50);
      digitalWrite(led[0], LOW);
      delay(50);
    }
  }
  else if (digitalRead(but[0]) == 1) {
    //Se o verde estiver pressionado, exibe a pontuação piscando o led verde
    for (int i = 0; i < maxScore; i++) {
      digitalWrite(led[0], HIGH);
      delay(500);
      digitalWrite(led[0], LOW);
      delay(500);
    }
    delay(1000);
    if (digitalRead(but[0]) == 1) {
      //Após exibir a pontuação, efetua o reset dos pontos caso o botão verde estiver pressionado
      EEPROM.write(0, 0);
      maxScore = 0;
    }
  }
} 

4 comentários: