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).


Diagrama elétrico do CEREBRUS | Clique na imagem para ampliar |

 

 

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.

 

Diagrama elétrico do CEREBRUS
Diagrama elétrico do CEREBRUS | Clique na imagem para ampliar |

 

 

 

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.

 

 

NO YOUTUBE


NOSSO PODCAST