.. note:: Ciao, benvenuto nella Community SunFounder per appassionati di Raspberry Pi, Arduino e ESP32 su Facebook! Approfondisci l'uso di Raspberry Pi, Arduino e ESP32 insieme ad altri entusiasti. **Perché Unirsi?** - **Supporto Esperto**: Risolvi problemi post-vendita e sfide tecniche con l'aiuto della nostra community e del nostro team. - **Impara e Condividi**: Scambia consigli e tutorial per migliorare le tue competenze. - **Anteprime Esclusive**: Ottieni accesso anticipato agli annunci di nuovi prodotti e anteprime. - **Sconti Speciali**: Approfitta di sconti esclusivi sui nostri prodotti più recenti. - **Promozioni Festive e Omaggi**: Partecipa a promozioni e omaggi durante le festività. 👉 Pronto per esplorare e creare con noi? Clicca [|link_sf_facebook|] e unisciti oggi stesso! 3.1.14 GIOCO – Not Not ======================= Introduzione -------------------- In questa lezione realizzeremo un dispositivo per un gioco interessante, che chiamiamo "Not Not". Durante il gioco, la matrice di punti genererà casualmente una freccia. Il tuo obiettivo è premere il pulsante nella direzione opposta alla freccia entro un tempo limitato. Se il tempo scade, o se premi il pulsante nella stessa direzione della freccia, perdi la partita. Questo gioco è un ottimo esercizio per allenare il pensiero inverso. Sei pronto a provare? Componenti --------------- .. image:: img/list_GAME_Not_Not.png :align: center Schema Circuitale ----------------------- ============ ======== ======== === T-Board Name physical wiringPi BCM GPIO17 Pin 11 0 17 GPIO18 Pin 12 1 18 GPIO27 Pin 13 2 27 GPIO20 Pin 38 28 20 GPIO26 Pin 37 25 26 ============ ======== ======== === .. image:: img/Schematic_three_one14.png :align: center Procedura Sperimentale ----------------------------- **Step 1:** Costruisci il circuito. .. image:: img/image280.png :width: 800 **Step 2:** Vai nella cartella del codice. .. raw:: html .. code-block:: cd ~/davinci-kit-for-raspberry-pi/c/3.1.14/ **Step 3**: Compila. .. raw:: html .. code-block:: gcc 3.1.14_GAME_NotNot.c -lwiringPi **Step 4**: Esegui. .. raw:: html .. code-block:: sudo ./a.out All'avvio del programma, una freccia a sinistra o a destra apparirà casualmente sulla matrice di punti. Devi premere il pulsante nella direzione opposta alla freccia entro il tempo stabilito. Se ci riesci, apparirà un \"**√**\" sulla matrice di punti. Se invece il tempo scade o premi il pulsante nella stessa direzione della freccia, perdi e sulla matrice di punti verrà visualizzato \"x\". Puoi aggiungere due nuovi pulsanti o sostituirli con i tasti del Joystick per le direzioni su, giù, sinistra e destra – aumentando così la difficoltà del gioco. .. note:: Se il programma non funziona dopo l'avvio o compare un messaggio di errore come \"wiringPi.h: File o directory inesistente\", consulta :ref:`Il codice C non funziona?`. **Spiegazione del Codice** Basandosi su **1.1.6 Matrice LED**, questa lezione aggiunge **2** pulsanti per creare un dispositivo di gioco divertente. Se non hai familiarità con la matrice a punti, consulta :ref:`1.1.6 Matrice di LED`. L’intero processo del programma è il seguente: 1. Seleziona casualmente la direzione di una freccia e genera il **timer 1**. 2. Visualizza l’immagine della freccia sulla matrice di punti. 3. Verifica l'input del pulsante. Se viene premuto un pulsante o **timer 1** segnala lo scadere del tempo, inizia la valutazione. 4. Visualizza l’immagine in base al risultato della valutazione; nel frattempo, genera **timer 2**. 5. Ripeti **passo 1** quando **timer 2** segnala lo scadere del tempo. .. code-block:: c struct GLYPH{     char *word;     unsigned char code[8]; }; struct GLYPH arrow[2]= {     {"right",{0xFF,0xEF,0xDF,0x81,0xDF,0xEF,0xFF,0xFF}},     // {"down",{0xFF,0xEF,0xC7,0xAB,0xEF,0xEF,0xEF,0xFF}},     // {"up",{0xFF,0xEF,0xEF,0xEF,0xAB,0xC7,0xEF,0xFF}},         {"left",{0xFF,0xF7,0xFB,0x81,0xFB,0xF7,0xFF,0xFF}} }; struct GLYPH check[2]= {     {"wrong",{0xFF,0xBB,0xD7,0xEF,0xD7,0xBB,0xFF,0xFF}},     {"right",{0xFF,0xFF,0xF7,0xEB,0xDF,0xBF,0xFF,0xFF}} }; La struttura **GLYPH** funziona come un dizionario: l’attributo **word** corrisponde alla **chiave** del dizionario, mentre l’attributo **code** corrisponde al **valore**. Qui, **code** viene utilizzato per memorizzare un array per la matrice LED al fine di visualizzare immagini (un array a 8 bit x 8 bit). L’array **arrow** può essere utilizzato per visualizzare le frecce in direzioni verso l’alto, il basso, sinistra e destra sulla matrice LED. Attualmente, le frecce per **down** e **up** sono commentate; rimuovi i commenti se necessario. L'array **check** viene utilizzato per visualizzare le seguenti immagini: \"**×**\" e \"**√**\". .. code-block:: c char *lookup(char *key,struct GLYPH *glyph,int length){     for (int i=0;i>i);         hc595_out();     } } Visualizza il pattern specificato sulla matrice di punti. .. code-block:: c void createGlyph(){     srand(time(NULL));     int i=rand()%(sizeof(arrow)/sizeof(arrow[0]));     waypoint=arrow[i].word;     stage="PLAY";     alarm(2); } La funzione **createGlyph()** viene utilizzata per selezionare casualmente una direzione (l'attributo "word" di un elemento nell'array **arrow[]:** \"**left**\", \"**right**\"...). Imposta lo stato su \"PLAY\" e avvia una funzione di allarme di 2 secondi. **srand(time(NULL)):** Inizializza i semi casuali derivanti dall'orologio di sistema. **(sizeof(arrow)/sizeof(arrow[0])):** Ottiene la lunghezza dell'array, il risultato è 2. **rand()%2:** Calcola il resto, che sarà **0** o **1**, ottenuto dividendo un numero casuale generato per 2. **waypoint=arrow[i].word:** Il risultato dovrebbe essere \"right\" o \"left\". .. code-block:: c void checkPoint(char *inputKey){     alarm(0)==0;     if(inputKey==waypoint||inputKey=="empty")     {         waypoint="wrong";     }     else{         waypoint="right";     }     stage="CHECK";     alarm(1); } La funzione checkPoint() viene utilizzata per verificare l'input del pulsante; se il pulsante non viene premuto o viene premuto nella stessa direzione della freccia, il risultato del waypoint sarà "sbagliato" e apparirà una \"**x**\" sulla matrice a punti. Al contrario, se il waypoint è corretto, la matrice mostrerà il simbolo \"**√**\". In questo caso, lo **stato** è impostato su **CHECK**, e può essere impostata una funzione di allarme di 1 secondo. La funzione alarm(), chiamata anche \"allarme\", consente di impostare un timer che invia segnali **SIGALRM** al processo una volta scaduto il tempo definito. .. code-block:: c void getKey(){     if (digitalRead(AButtonPin)==1&&digitalRead(BButtonPin)==0)     {checkPoint("right");}     else if (digitalRead(AButtonPin)==0&&digitalRead(BButtonPin)==1)     {checkPoint("left");} } getKey() legge gli stati dei due pulsanti; se è premuto il pulsante destro, il parametro per checkPoint() è "destra"; se è premuto quello sinistro, il parametro è "sinistra". .. code-block:: c void timer(){     if (stage=="PLAY"){         checkPoint("empty");     }     else if(stage=="CHECK"){         createGlyph();     } } Quando il **timer()** scade, sotto lo stato "GIOCO", viene chiamato checkPoint() per la verifica. Se il programma è impostato su "VERIFICA", chiama **createGlyph()** per una nuova freccia. .. code-block:: c void main(){     setup();     signal(SIGALRM,timer);     createGlyph();     char *code = NULL;     while(1){         if (stage == "PLAY")         {             code=lookup(waypoint,arrow,sizeof(arrow)/sizeof(arrow[0]));             display(code);             getKey();         }         else if(stage == "CHECK")         {             code = lookup(waypoint,check,sizeof(check)/sizeof(check[0]));             display(code);         }     } } **signal(SIGALRM, timer)**: Chiama **timer()** quando riceve un segnale **SIGALRM** generato dal timer **alarm()**. All'avvio del programma, **createGlyph()** viene chiamato una volta, quindi inizia il loop. Nel loop: in modalità **GIOCO**, la matrice di punti mostra le frecce e controlla lo stato dei pulsanti; in modalità **VERIFICA**, mostra "x" o "√".