Apresentamos neste artigo um interessante projeto baseado numa versão antiga dos anos 80 de um jogo eletrônico que fez muito sucesso no nosso país. O jogo foi totalmente modernizado pelo autor para fazer uso do moderno Arduino, tornando-se assim novamente uma grande atração para os que gostam de microcontroladores.
Um pouco de saudosismo
Lá pelos anos 80 chegou ao Brasil um brinquedo batizado pela Estrela de GENIUS , conhecido nos Estados Unidos como SIMON; um jogo tendo por objetivo desafiar a memória!

Em sua versão original apresentava quatro teclas coloridas diferentes iluminadas; essencialmente, ao ele acender aleatoriamente uma dessas luzes, o usuário tinha de repeti-la; em seguida era acrescida mais uma luz e a consequente necessidade de repetição de toda a sequência por parte do jogador e assim seguidamente até atingir a capacidade de memória do aparelho. O vencedor, é claro, era quem conseguia o maior número de repetições sem erro.
Mal SIMON acabara de ser lançado nos “estates” nosso compadre e amigo Eduardo chega à terra do Tio Sam; na sua bagagem de volta ao Brasil ele traz a essência da ideia do jogo e ma apresenta. Confesso ter ficado estupefato! Naquele princípio da década de 80 não era para menos! Novidades desse tipo eram disputadas a tapa!
Tão obstupefato fiquei que resolvi criar a minha própria versão do jogo. Em clara falta de criatividade recebeu ela o nome de CEREBRUS cujo circuito utilizava um fim de componentes entre eles, é claro, o inigualável e imbatível CI 555 (**), além disso, contava com um par de mostradores (display) que, ao final do jogo, apresentavam a quantidade de lances corretamente feitos pelo vencedor! A complexidade do circuito era tamanha que nenhuma das quatro revistas nacionais em que eu escrevia sobre eletrônica e a fins se atreveu a publicar tal projeto! O fato é que o pessoal lá de casa durante muito bom tempo brincou com tal aparelhinho, isso antes da versão GENIUS ser oficialmente lançada no Brasil.
A verdade é que umas duas décadas depois ‘pendurei as chuteiras’! Afastei-me da eletrônica como em, exatamente, 1985 me havia afastado do vício tabagismo! Do tabagismo consegui afastar-me de forma definitiva, mas da eletrônica nunca me afastei plenamente! Volta e meia uma coisinha aqui, uma coisinha lá... Mas publicar não! Inda que não tenha parado de escrever...
A prova cabal que de que é impossível abandonar de vez a eletrônica está aqui, neste artigo! Um texto cuja ideia é dar vida ao ‘meu’ CEREBRUS de mais de 30 anos e trazer de volta a ideia do GENIUS.
Tal como principia a canção de Oswaldo Nunes:
“Voltei,
Aqui é meu lugar,
Minha emoção é grande,
A saudade era maior,
E voltei pra ficar…”
O Arduino
O ARDUINO, em linhas gerais, é uma plataforma de desenvolvimento microprocessada extremamente interessante, fácil de usar pois aceita a linguagem de programação C/C++ e, de sobra, cabe na palma da mão (figura 2).
Essencialmente a placa é constituída por um microcontrolador (Atmel AVR – 8 bits), disponibilizando diversas linhas de entrada e saída (E/S ou I/O) tanto digitais como analógicas, conta ainda com uma interface serial USB capaz de comunicar-se também com um PC para efeito de programação e interação em tempo real e, o mais importante de tudo, de custo relativamente baixo, muito baixo (eu adquiri a minha, inda que não original, por menos de R$ 30,00 – maio de 2017). Ah! Se nos velhos tempos existisse...
O mais interessante é o fato de tratar-se de uma plataforma de prototipagem eletrônica capaz de ser utilizada por pessoas não profundamente familiarizadas com desenvolvimento de software (programação) além de não exigir profundos conhecimentos em eletrônica e afins, apenas um pouco de habilidade e ‘querer fazer’ – um sem fim de aplicações (programas - skechs) estão livremente disponíveis na Internet.
Informes adicionais sobre os modelos de placas também estão disponíveis na internet bem como várias interfaces prontas de baixo custo para utilizar em conjunto com as diversas opções de ARDUINO como, por exemplo, sensor de proximidade e temperatura, drivers para motor de passo entre outros.
O circuito do CEREBRUS
Ainda que aparelho seja único, foram implementados quatro jogos distintos na nova versão do CEREBRUS; em verdade um circuito simples utilizando um mínimo de componentes, todos passivos fora a placa ARDUINO, de custo relativamente baixo; a saber:
R1 a R5 Resistores 330 Ω, 1/8 W
J1 Piezo Speaker ou mesmo um pequeno alto faltante (8 Ω)
LED 1 a LED4 LED cor azul, mas nada impede que sejam utilizados LEDs de cores diferentes
S1 a S5 Pushbutton de contato momentâneo NA (preferencialmente um de aspecto diferente dos demais)
Fonte Fonte de alimentação externa, 9VCC@100 mA – como alternativa é possível utilizar um carregador USB de celular, tablet etc.
Cx Caixa de dimensões suficientes para alojar a placa do ARDUINO, no caso a versão UNO – em meu caso utilizei uma caixa MDF (Medium Density Fiberboard – placa de fibra de média densidade) de dimensões 13cm x 13 cm x 5 cm, respectivamente comprimento, largura e altura.
A simplicidade do circuito do CEREBRUS é evidente como bem o mostra o esquemático da figura 3; observe que apenas foram usadas cinco linhas de E/S do ARDUINO: quatro para os LEDs (entrada/saída) e uma para o alto falante, além da linha de reciclagem (reset) – interruptor S1.
A montagem
Na tampa da caixa fiz nove furos de diversos diâmetros para comportar os cinco interruptores de contato momentâneo e os quatro LEDs; na parte lateral da caixa de MDF fiz um furo de modo a passar o cabo de alimentação do circuito conforme mostra a figura 4, no canto superior esquerdo – a tecla central é o reset do sistema.

A interligação dos resistores, LEDs e resistores foi feita diretamente entre os componentes, ou seja, foram utilizados os próprios lides dos componentes, dispensando dessa forma o uso de placas de circuito impresso (figura 5), note que o ‘terra’ (GND) do reset do interruptor central foi usando como ponte para os quatro resistores; o quinto resistor, R1, foi devidamente protegido para evitar eventuais curto-circuitos (canto superior esquerdo da mesma figura 5). Esses componentes foram interligados aos respectivos pinos da placa ARDUINO, em um total de sete conexões.
Para que o programa funcione de forma harmoniosa é necessário interligar cada conjunto LED-resistor à placa de forma sequencial, isto é, de forma ordenada; no meu caso em particular iniciei a associação seguindo o movimento dos ponteiros do relógio , iniciei pela tecla vermelha localizada no canto superior direito da tampa da caixa, associando a essa disposição geométrica o par S2-LED1, interligando-a ao pino 3 do ARDUINO; o par S3-LED2 correspondeu ao conjunto inferior imediatamente à direita (tecla verde – conjunto aqui identificado por ‘LED 2’); já o duo S4-LED3, ligado ao pino 5 da placa, foi associado ao interruptor vermelho inferior, ‘LED 3’, finalmente, a segunda e última tecla verde foi associada ao conjunto S5-LED4 o qual foi ligada ao terminal 6 da placa, conjunto identificado no esquema por ‘LED 4’.

Não me esqueci de ligar os bornes do alto falante respectivamente ao pino 7 da placa e ao comum (GND) – sendo um piezoelétrico obedecer a polaridade: fio preto ao terra ou comum.
Para fonte de alimentação utilizei-me de uma fonte chaveada da sucata: de 9 VCC @0,5 A com larguíssima sobra de potência. Fiz experimentos com bateria de 9 VCC e com dois carregadores universais para móvel (smartphone) e tablete; em todos os casos com bons resultados.
O programa - descrição
O ‘coração’ do CEREBRUS é o programa adiante reproduzido que comando o hardware ARDUINO, por isso merecendo uma análise mais detalhada visando facilitar a tarefa daqueles que o quiserem adaptar à suas necessidades e/ou preferências.
Inicialmente são definidas as variáveis (inteiras) de uso geral e duas específicas: contjog responsável por armazenar o número de jogadas realizadas e del6 que estabelece em 90 ms a unidade básica de temporização.
Passo seguinte são definidas as variáveis booleanas (apenas armazenam 1 ou 0), a saber:
• boolean jogador - indica qual jogador a fazer seu lance no JOGO 2;
• boolean memo [99][4] - Matriz lógica de 100 linhas e 4 colunas; cada linha corresponde a uma jogada realizada (vetor) e cada coluna o valor lógico da tecla (única) acionada em determinada jogada (linha) - 100 é valor máximo de jogadas possíveis de serem armazenadas;
• boolean pinos [4] e boolean check [4] - dois vetores de 4 dimensões para armazenamento temporário do estado lógico de cada tecla;
• boolean matriz [][4] = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}, {0, 0, 0, 0}, {1, 1, 1, 1}}; memória pré-fixada: os quatro primeiros vetores correspondem às quatro teclas e os dois últimos servem para, respectivamente, ‘apagar’ e ‘acender’ os quatro leds.
No setup configurei a transmissão serial para efeito de depuração e a geração da semente para a função random pelo produto de dois valores aleatórios (ruído).
A rotina principal inicia alertando o usuário para selecionar a modalidade de jogo dentre as quatro disponíveis, a seleção é feita durante o momento em que o led estiver ativo de modo que o LED 1, leva ao JOGO0, LED 2 ao JOGO1 e assim por diante – note que o desvio somente é feito após o usuário liberar o teclado (linhas 12-37).
Durante a execução do programa são chamadas várias sub-rotinas a saber:
ATIVA_LEDS () [linhas 266-273] - Ativa/desativa os leds pelo número de vezes passado pela variável k com a emissão de som característico.
ESCREVE_PINOS () [linhas 241-256] - Recebe pelo vetor pinos o valor a ser escrito nos leds e por t a duração da apresentação, gerando o devido tom associado a cada led.
GERA_TOM () [linhas 258-264] - Calcula a frequência do tom e o ativa pelo pino 7 da placa.
DEBOUNCE () [linhas 214-239] - Aguarda o pressionar de uma única tecla pelo usuário, elimina ruído (repique) inerente a seu acionamento, salva valor no vetor pinos, só retornando após a liberação do teclado (nenhuma tecla pressionada).
TRATA_ERRO () [linhas 177-212] - Pelo piscar de todos os leds informa encerramento do jogo, mostra alternadamente a jogada errada feita, a jogada certa que deveria ter sido feita e, através de sucessivos piscar do LED 2, apresenta o valor das dezenas e depois unidades do número das jogadas certas realizadas. O processo é repetido indefinidamente.
JOGADOR () [linhas 149-165] - Lê o valor da tecla pressionada, escreve valor acionando o respectivo tom, se for o caso verifica a igualdade entre a tecla pressionada e o valor da tecla armazenado em memória quando pertinente, salva valor da nova tecla pressionada na memória (matriz memo) – rotina tipicamente atrelada ao jogador.
ESCREVE_MEMO () [linhas 130-147] - Escreve todos os valores (vetores) anteriormente armazenados na memória ativando o respectivo tom - cada apresentação com duração temporal múltipla do valor t passado à sub-rotina ‑ rotina orientada para a máquina.
JOGA_MAQUINA () [linhas 121-128] - Apresenta todas as jogadas feitas até o momento assim como a nova jogada realizada pela máquina através da função random.
JOGA_VERDE_VERMELHO () [linhas 100-119] - Lê teclado, retira o ruído (repiques) e analisa a tecla pressionada do JOGADOR identificado pela variável lógica jogador; se em 1 apenas as teclas de cor verde disponíveis, se em 0 apenas as duas teclas de cor vermelha serão interpretadas.
A rotina de cada um dos quatro jogos estão assim estabelecidas.
JOGO0 [linhas 39-45]: JOGADOR versus CEREBRUS - JOGADOR realiza seu primeiro lance, CEREBRUS repete o lance dele e acrescenta mais um passando a vez para o JOGADOR; a partir deste momento cada competidor repete TODAS as jogadas anteriormente realizadas acrescentando mais uma – limite: 100 jogadas ao total (imposição da linha 3).
Através de duas piscadas em todos os leds máquina dá as boas-vindas ao jogador, ou seja, foi aceito o comando e aguarda o lance do jogador chamando o sub-rotina JOGADOR (); após uma espera (‘máquina pensando’) o programa chama a sub-rotina JOGA_MAQUINA dando a vez para o CEREBRUS, findo este, todo o processo se repete.
JOGO1 [linhas 47-66]: JOGADOR versus CEREBRUS - Nesta modalidade apenas o CEREBRUS realiza novas jogadas (uma de cada vez) cabendo ao JOGADOR unicamente repetir sequencialmente as jogadas feitas pela máquina sem fazer qualquer acréscimo; convém notar que a máquina não apresenta, como no caso anterior, as jogadas anteriormente realizadas, dificultando o jogo.
Fazendo piscar por duas vezes todos os leds (linha 48), o circuito informa que irá fazer sua primeira jogada a ser armazenada em matriz, passo seguinte é chamada a sub-rotina DEBOUNCE que aguarda e analisa o pressionar de o lance do JOGADOR; havendo conformidade, o CEREBRUS apenas realiza nova jogada repetindo-se o processo continuamente.
JOGO2 [linhas 68-73]: JOGADOR1, VERDE versus JOGADOR2, VERMELHO - Inicialmente um dos jogadores escolhe uma cor, verde (LED2/LED4) ou vermelha (LED1/LED3), sendo essa a cor com a qual poderá inserir suas novas jogadas – cabe ao jogador das teclas verdes iniciar a disputa mental. O jogo inicia com o mesmo welcome da máquina visto anteriormente, cabendo ao ‘jogador verde’ realizar sua jogada a ser repetida pelo ‘jogador vermelho’ o qual acrescenta nova jogada, e assim por diante, alternadamente; nesta modalidade a máquina apenas funciona como uma espécie de juiz.
O programa deste jogo se utiliza das mesmas sub-rotinas utilizadas nas situações anteriores de jogo e em situações particularmente semelhantes.
JOGO3 [linhas 75-98]: JOGADOR1 versus JOGADOR2 - Nesta modalidade não há interferência da máquina onde cada repete todas as jogadas anteriores e acresce mais duas de sua livre escolha, cabendo ao oponente repetir o processo acrescendo, é claro, mais duas; há de notar que não há repetição automática das jogadas mas, para facilitar, chegando a vez do outro jogador, a máquina dá um rápido alerta no piscar dos leds. Em caso de erro o programa interrompe o jogo mostrando, como nos casos anteriores, o lance errado e o lance errado, logo depois a quantidade de jogadas feitas certas.
Tal como nos casos acima, as boas-vindas são dadas aos jogadores pelo duplo piscar dos leds ficando o circuito à espera do lance duplo do primeiro jogador; em se tratando da primeira jogada dupla é pulada a seção de verificação e tratamento de eventual erro (linhas 79-85).
O programa
1. int i,j,d,u,c,soma,contjog=0,del6=90;//CONTADORES GENÉRICOS E TEMPO DE ATRASO
2. boolean jogador=1;//1 --> JOGADOR VERDE; 0 --> JOGADOR VERMELHO
3. boolean memo [99][4];//MATRIZ DE ARMAZENAMENTO DAS JOGADAS REALIZADAS (MÁX. 100)
4. boolean pinos [4]; boolean check [4];//ARMAZENAMENTO TEMPORÁRIO DO ESTADO DAS QUATRO ENTRADAS/SAÍDAS
5. boolean matriz [][4]={{1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {0,0,0,1}, {0,0,0,0}, {1,1,1,1}};
6. void setup() {
7. Serial.begin (9600); // INICIALIZA A TRANSMISSÃO SERIAL PARA EVENTUAL DEPURAÇÃO
8. randomSeed (analogRead(0)*analogRead (1)); // GERAÇÃO DA SEMENTE PARA A FUNÇÃO random
9. }
10. void loop() {
11. //===========================JOGO CEREBRUS * AQUILINO R. LEAL======================================
12. REPETE:
13. for (d = 0; d <= 3; d++) {//ATIVAÇÃO INDIVIDUAL DE CADA UM DOS 4 LEDs E RESPECTIVO TOM ASSOCIADO
14. for (i = 0; i <= 3; i++) {// COPIA EM pinos O LED A SER ATIVADO SEGUNDO O VETOR matriz
15. pinos [i] = matriz [d][i];
16. }
17. for (u = 0; u <= 2; u++) {//ATIVA POR ATÉ 3 VEZES O LED
18. ESCREVE_PINOS (1); // ESCREVE VALOR E TOM, COLOCA PINOS NO MODO DE ENTRADA, ‘DESLIGA’ OS LEDs
19. if ((digitalRead (d + 3)) == 1) goto SELECIONAJOGO;//DESVIA SE TECLA CORRESPONDENTE FOI ACIONADA
20. }
21. delay (del6 * 2); // TEMPORIZA PARA O PRÓXIMO LED
22. }
23. goto REPETE;//PERMANECE NO LOOP ATÉ ALGUMA AÇÃO VÁLIDA DO USUÁRIO
24. SELECIONAJOGO:
25. for (j = 0; j <= 600; j++) {//AGUARDA LIBERAÇÃO DO TECLADO VERIFICANDO 601 VEZES
26. for (i = 0; i <= 3; i++) {
27. if (digitalRead(i + 3) != matriz[4][i]) j = 0;//REINICIA PROCESSO SE HÁ ALGUMA TECLA PRESSIONADA
28. }//COMPARANDO COM matriz [4][i]={0,0,0,0}
29. }
30. delay (del6 * 10);//TEMPO ADICIONAL DE ESPERA APÓS A LIBERAÇÃO DAS TECLAS
31. switch (d) {// SELECIONA O JOGO DE ACORDO COM A TECLA PRESSIONADA PELO USUÁRIO
32. case 0: goto JOGO0;
33. case 1: goto JOGO1;
34. case 2: goto JOGO2;
35. case 3: goto JOGO3;
36. }
37. goto REPETE; // VOLTA AO INICIO EM CASO DE EVENTUAL FALHA
38. // ===============================
39. JOGO0:
40. ATIVA_LEDS (2); // INFORMA QUE MÁQUINA ESTÁ PRONTA INICIAR JOGO
41. JOGO00:
42. JOGADOR (); // JOGADOR FAZ SEU LANCE
43. delay (del6 * 10); //TEMPO PARA A MÁQUINA FAZER SUA JOGADA
44. JOGA_MAQUINA ();
45. goto JOGO00;
46. // ===============================
47. JOGO1:
48. ATIVA_LEDS(2); // MÁQUINA PRONTA PARA INICIAR JOGO FAZENDO PISCAR TODOS OS LEDs
49. JOGO10:
50. delay (del6 * 13); //TEMPO DE ESPERA
51. int joga;
52. joga = random (0, 4);//GERA NÚMERO PARA JOGADA DA MÁQUINA
53. for (i = 0; i <= 3; i++) {
54. memo [contjog][i] = matriz [joga][i]; // ARMAZENA JOGADA DA MÁQUINA
55. pinos [i] = matriz [joga][i]; // ARMAZENAMENTO TEMPORÁRIO DA JOGADA DA MÁQUINA
56. }
57. ESCREVE_PINOS(3); // EXTERNA JOGADA PASSANDO O TEMPO DE APRESENTAÇÃO
58. contjog += 1; // MAIS UMA JOGADA FEITA
59. for (j = 0; j <= contjog - 1; j++) {// VERIFICA JOGADAS DO USUÁRIO
60. DEBOUNCE ();//EM pinos [i] A TECLA PRESSIONADA PELO JOGADOR
61. ESCREVE_PINOS(3);//ATIVA SAÍDA PASSANDO PERÍODO DE APRESENTAÇÃO
62. for (i = 0; i <= 3; i++) {
63. if (memo[j][i] != pinos [i]) TRATA_ERRO ();//VERIFICA SE JOGADA DO USUÁRIO É A CORRETA
64. }
65. }
66. goto JOGO10;//CONTINUA NO MESMO JOGO
67. // ===============================
68. JOGO2:
69. ATIVA_LEDS(2);//OS LEDs PISCAM: MÁQUINA PRONTA PARA INICIAR JOGO
70. JOGO20:
71. JOGA_VERDE_VERMELHO ();
72. jogador = !jogador;//PASSA A VEZ PARA O OUTRA COR, OUTRO JOGADOR
73. goto JOGO20;
74. // ===============================
75. JOGO3:
76. ATIVA_LEDS(2); // TODOS OS LEDs ACENDEM, MÁQUINA ESTÁ PRONTA INICIAR JOGO
77. JOGO30:
78. if (contjog <= 1)goto PRIMEIRODUO; //PULA CHECAGEM SE É A PRIMEIRA VEZ
79. for (j = 0; j <= contjog - 1; j++) { //VERIFICAÇÃO DAS JOGADAS REALIZADAS
80. DEBOUNCE (); // EM pinos [i] A TECLA PRESSIONADA
81. ESCREVE_PINOS(3); //ATIVA SAÍDAS E PASSA TEMPO DE APRESENTAÇÃO
82. for (i = 0; i <= 3; i++) {
83. if (memo[j][i] != pinos [i]) TRATA_ERRO ();
84. }
85. }
86. PRIMEIRODUO:
87. for (c = 0; c <= 1; c++) {
88. DEBOUNCE(); // ELIMINA RUIDO E RETORNA EM pinos [i] O LANCE VÁLIDO
89. ESCREVE_PINOS (3); //ESCREVE LANCE E PASSA TEMPO DE APRESENTAÇÃO
90. for (i = 0; i <= 3; i++) {
91. memo[contjog][i] = pinos[i]; // ARMAZENA JOGADA
92. }
93. contjog += 1; // PRÓXIMA JOGADA
94. }
95. delay (del6 * 4); //TEMPO DE ESPERA PARA A JOGADA DUPLA DO ADVERSÁRIO
96. ATIVA_LEDS(1); // VEZ DO OUTRO JOGADOR
97. goto JOGO30;
98. }
99. // ================= JOGADA VERDE/VERMELHO ======================
100. void JOGA_VERDE_VERMELHO () {
101. if (contjog == 0) goto PRIMEIRAJOGADA_J2;//PRIMEIRO LANCE? JOGA TECLA VERDE
102. for (j = 0; j <= contjog - 1; j++) {
103. DEBOUNCE ();//EM pinos [i] A TECLA PRESSIONADA PARA VERIFICAÇÃO
104. ESCREVE_PINOS(3);//ESCREVE VALOR DE TECLA PRESSIONADA LEVANDO TEMPO DE APRESENTAÇÃO
105. for (i = 0; i <= 3; i++) {
106. if (memo[j][i] != pinos [i]) TRATA_ERRO_J2();
107. }
108. }
109. PRIMEIRAJOGADA_J2:
110. DEBOUNCE ();//TRAZ EM pinos O VALOR DOS ESTADO DAS TECLAS (APENAS UMA PRESSIONADA)
111. for (i = 0; i <= 3; i++) {
112. if (pinos [i] != matriz [jogador][i] && pinos[i] != matriz [jogador + 2][i]) goto PRIMEIRAJOGADA_J2;//APENAS
113. }//PERMITE A JOGADA DAS TECLAS DA COR DO JOGADOR (VERDE OU VERMELHA)
114. ESCREVE_PINOS(3);//ATIVA O LED E O SOM DE ACORDO COM pinos, INFORMA O TEMPO DE APRESENTAÇÃO
115. for (i = 0; i <= 3; i++) {
116. memo[contjog][i] = pinos[i];//ARMAZENA JOGADA FEITA
117. }
118. contjog += 1;//INCREMENTA NÚMERO DE JOGADAS
119. }
120. // ================= JOGADA MÁQUINA ======================
121. void JOGA_MAQUINA() {
122. int joga = random (0, 4);//GERA A JOGADA A SER FEITA PELA MÁQUINA
123. for (i = 0; i <= 3; i++) {
124. memo [contjog][i] = matriz [joga][i];//ARMAZENA JOGADA DA MÁQUINA
125. }
126. ESCREVE_MEMO(3); // PASSA O TEMPO DE DURAÇÃO DE CADA LANCE
127. contjog += 1;//PREPARA PARA PRÓXIMA JOGADA
128. }
129. // ================= ESCREVE MEMÓRIA ======================
130. void ESCREVE_MEMO(int t) {// RECEBE DURAÇÃO DE APRESENTAÇÃO
131. int j;
132. for (j = 0; j <= contjog; j++) {
133. delay (del6 * 2);//TEMPO DE ESPERA
134. for (int i = 0; i <= 3; i++) {
135. pinMode (i + 3, OUTPUT);
136. digitalWrite(i + 3, memo[j][i]);
137. pinos [i] = memo[j][i];
138. }
139. GERA_TOM ();
140. delay (del6 * t); // TEMPO DE APRESENTAÇÃO
141. noTone (7);
142. for (i = 0; i <= 3; i++) {
143. pinMode (i + 3, INPUT); //APAGA MOSTRADOR
144. }
145. delay (del6 * 2); // AGUARDA PARA MOSTRAR PRÓXIMA JOGADA
146. }
147. }
148. // ================= JOGADA HUMANA ======================
149. void JOGADOR() {
150. if (contjog == 0) goto PRIMEIRAJOGADA; //NÃO VERIFICA LANCES ANTERIORES SE FOR A PRIMEIRA JOGADA
151. for (j = 0; j <= contjog - 1; j++) {//COMPARA A JOGADAS ATUAIS COM A JOGADAS ARMAZENADAS
152. DEBOUNCE (); // EM pinos [i] A TECLA PRESSIONADA
153. ESCREVE_PINOS(3); //ATIVA SAÍDAS E PASSA TEMPO DE APRESENTAÇÃO
154. for (i = 0; i <= 3; i++) {
155. if (memo[j][i] != pinos [i]) TRATA_ERRO ();
156. }
157. }
158. PRIMEIRAJOGADA:
159. DEBOUNCE(); // ELIMINA RUÍDO E RETORNA EM pinos [] O LANCE VÁLIDO FEITO
160. ESCREVE_PINOS (3); //ESCREVE LANCE E PASSA TEMPO DE APRESENTAÇÃO
161. for (i = 0; i <= 3; i++) {
162. memo[contjog][i] = pinos[i]; // ARMAZENA JOGADA
163. }
164. contjog += 1; // PRÓXIMA JOGADA
165. }
166. // ================= TRATAMENTO DE ERRO JOGO2 ======================
167. void TRATA_ERRO_J2() {
168. jogador = !jogador; // PARA APRESENTAR VITÓRIA DO OPONENTE
169. for (i = 0; i <= 3; i++) {
170. pinos [i] = (matriz [jogador][i] || matriz [jogador + 2][i]);
171. }
172. AQUI:
173. ESCREVE_PINOS (1);
174. goto AQUI;
175. }
176. // ================= TRATAMENTO DE ERRO ======================
177. void TRATA_ERRO () {
178. for (i = 0; i <= 3; i++) {
179. check[i] = pinos[i]; //ARMAZENA LANCE ERRADO EM check [i]
180. }
181. ATIVA_LEDS (4); // INFORMA ENCERRAMENTO DO JOGO PISCANDO OS LEDs 4 VEZES
182. d = j / 10;//SEPARA EM DEZENAS E UNIDADES DO NÚMERO DE JOGADAS CERTAS
183. u = j - d * 10;
184. delay (del6 * 2);//TEMPO DE ESPERA
185. LOOP_TRATAERRO:
186. for (int a = 0; a <= 3; a++) {
187. for (i = 0; i <= 3; i++) {
188. pinos [i] = memo[j][i]; // ESCREVE LANCE CERTO ('a' VEZES)
189. }
190. ESCREVE_PINOS (2);//ESCREVE LANCE CERTO COM SOM
191. for (i = 0; i <= 3; i++) {
192. pinos [i] = check[i]; // ESCREVE LANCE ERRADO ('a' VEZES)
193. }
194. ESCREVE_PINOS (2);//ESCREVE LANCE ERRADO COM SOM
195. }
196. delay (del6 * 12); //ESPERA PARA APRESENTAR NÚMERO DE LANCES FEITOS CERTOS
197. pinMode (4, OUTPUT);//SAÍDA DE DEZENAS
198. c = d;//PRIMEIRO APRESENTA DEZENAS
199. for (int soma = 0; soma <= 1; soma++) {//FAZ PRIMEIRO PARA DEZENAS E DEPOIS PARA UNIDADES
200. for (int a = 1; a <= c; a++) { // APRESENTA VALOR
201. digitalWrite (4, HIGH);
202. delay (del6 * 8);
203. digitalWrite (4, LOW);
204. delay (del6 * 6);
205. }
206. delay (del6 * 20); // ESPERA PARA APRESENTAR UNIDADES
207. c = u;//AGORA É A VEZ DAS UNIDADES
208. }
209. pinMode (4, INPUT);
210. delay (del6 * 5); // ESPERA PARA REPETIR INDEFINIDAMENTE O PROCESSO
211. goto LOOP_TRATAERRO;
212. }
213. // ================= DEBOUNCE ======================
214. void DEBOUNCE () {
215. //ATIVAÇÃO TECLAS
216. int i, j; //VARIÁVEIS LOCAIS
217. for (j = 0; j <= 600; j++) {//CONFIRMAÇÃO DA MESMA TECLA PRESSIONADA
218. for (i = 0; i <= 3; i++) {
219. check [i] = pinos[i];//SALVA VALOR DA ATUAL LEITURA PARA FUTURAS COMPARAÇÕES
220. };
221. soma = 0;//CONTADOR DE TECLAS PRESSIONADAS SIMULTANEAMENTE
222. for (i = 0; i <= 3; i++) {
223. pinos [i] = digitalRead(i + 3);
224. soma += pinos [i];
225. }
226. if (soma != 1) j = 0; // SOMENTE UMA TECLA ACIONADA! REINICIA PROCESSO
227. for (i = 0; i <= 3; i++) {
228. if (check [i] != pinos[i]) {
229. j = 0; //REINICIA PROCESSO SE TECLA AGORA PRESSIONA NÃO É A MESMA DAS VEZES ANTERIORES
230. }
231. }
232. }// REPETE POR 601 VEZES
233. //DESATIVAÇÃO TECLAS
234. for (j = 0; j <= 600; j++) {//NÚMERO DE VEZES DE CONFIRMAÇÃO DE NENHUMA TECLA PRESSIONADA
235. for (i = 0; i <= 3; i++) {
236. if (digitalRead(i + 3) != matriz[4][i]) j = 0;//TECLA PRESSIONADA? REINICIA PROCESSO
237. }
238. }//REPETE POR 601 VEZES
239. }
240. // ================= ESCREVE_PINOS ======================
241. void ESCREVE_PINOS(int t) {// RECEBE DADOS POR pinos[i] E A DURAÇÃO POR t
242. GERA_TOM ();//ATIVA O SOM DE ACORDO COM O LED ATIVO
243. int i;
244. for (i = 3; i <= 6; i++) {//OS PINOS DA PLACA SÃO 3, 4, 5, E 6
245. pinMode (i, OUTPUT);//PINOS NO MODO SAÍDA
246. }
247. for (i = 0; i <= 3; i++) {
248. digitalWrite (i + 3, pinos[i]);//ESCREVE NOS PINOS O VETOR pinos
249. }
250. delay (del6*t);//ESTABELECE O TEMPO DE APRESENTAÇÃO
251. for (i = 0; i <= 3; i++) {
252. pinMode (i + 3, INPUT);//DESATIVA PINOS COLOCANDO-OS NO MODO DE ENTRADA
253. }
254. noTone (7);//DESATIVA SOM SE ATIVO
255. delay (del6 * 2); // TEMPO DE DESATIVAÇÃO
256. }
257. // ================= GERA_TOM ======================
258. void GERA_TOM () {
259. int c = 250;//CONSTANTE INCIAL PARA ESTABELECER A FREQUÊNCIA DO SOM EMITIDO
260. for (i = 0; i <= 3; i++) {
261. c = c + 150 * i * pinos[i]; // SELEÇÃO DO TOM DE ACORDO COM O PINO ATIVO (EM HIGH OU 1)
262. }
263. tone (7, c);//FAZ EMITIR O SOM NO PINO 7
264. }
265. // ================= ATIVA OS LEDS ======================
266. void ATIVA_LEDS (int k) {//FAZ PISCAR OS LEDs PELO NÚMERO RECEBIDO
267. for (int p = 1; p <= k; p++) {
268. for (int i = 0; i <= 3; i++) {
269. pinos [i] = matriz [5][i]; //TODAS SAÍDAS EM ALTO (matriz [5][]={1,1,1,1})
270. }
271. ESCREVE_PINOS (1);//EXECUTA A ROTINA UMA ÚNICA VEZ
272. }
273. }
Nota de Newton C. Braga: com muita satisfação, podemos dizer que com este artigo temos a volta “a ativa” do nosso grande amigo e colaborador Aquilino. Este artigo é apenas uma amostra do que ele pode fazer. Além de estarmos “recuperando” muitos dos artigos que ele publicou e que certamente são ainda de grande interesse para nossos leitores, esperamos muito mais.