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!


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*--------------------------------------------------------
  Programa : GENIUS (SIMON GAME)
  Autor    : Fellipe Couto [ http://www.efeitonerd.com.br ]
  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;
    }
  }
} 

6 comentários:

  1. A melhor lógica de simon que já vi. Parabéns!

    ResponderExcluir
  2. cara,esse programa roda mesmo?

    ResponderExcluir
  3. o que essa linha faz? long previousMillis = 0;

    ResponderExcluir
    Respostas
    1. É a declaração da variável para controle do temporizador. Iniciando com valor 0.

      Excluir