Nota

Ciao, benvenuto nella SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts Community su Facebook! Approfondisci Raspberry Pi, Arduino ed ESP32 con altri appassionati.

Perché unirti a noi?

  • Supporto Esperto: Risolvi problemi post-vendita e sfide tecniche con l’aiuto della nostra community e del nostro team.

  • Impara & Condividi: Scambia consigli e tutorial per migliorare le tue abilità.

  • Anteprime Esclusive: Accedi in anteprima agli annunci dei nuovi prodotti e alle anticipazioni.

  • Sconti Speciali: Approfitta di sconti esclusivi sui nostri prodotti più recenti.

  • Promozioni Festive e Omaggi: Partecipa a omaggi e promozioni durante le festività.

👉 Sei pronto a esplorare e creare con noi? Clicca su [Qui] e unisciti oggi!

4.1.14 GIOCO - Indovina il Numero

Introduzione

Indovina il Numero è un gioco da festa divertente in cui tu e i tuoi amici vi alternate inserendo un numero (0~99). L’intervallo si ridurrà man mano che i numeri vengono inseriti, fino a quando un giocatore indovinerà il numero corretto. A quel punto, il giocatore perderà e sarà punito. Ad esempio, se il numero fortunato è 51, che i giocatori non possono vedere, e il giocatore ① inserisce 50, l’intervallo numerico cambia a 50~99; se il giocatore ② inserisce 70, l’intervallo sarà 50~70; se il giocatore ③ inserisce 51, questo giocatore sarà lo sfortunato. In questo progetto, utilizziamo un tastierino per inserire i numeri e un LCD per visualizzare i risultati.

Componenti Necessari

In questo progetto, abbiamo bisogno dei seguenti componenti.

../_images/4.1.17_game_guess_number_list.png

È sicuramente conveniente acquistare un kit completo, ecco il link:

Nome

COMPONENTI IN QUESTO KIT

LINK

Raphael Kit

337

Raphael Kit

Puoi anche acquistarli separatamente dai link sottostanti.

INTRODUZIONE AI COMPONENTI

LINK PER L’ACQUISTO

Scheda di estensione GPIO

ACQUISTA

Breadboard

ACQUISTA

Cavi Jumper

ACQUISTA

Resistore

ACQUISTA

Tastierino

-

I2C LCD1602

ACQUISTA

Schema Elettrico

T-Board Name

physical

wiringPi

BCM

GPIO18

Pin 12

1

18

GPIO23

Pin 16

4

23

GPIO24

Pin 18

5

24

GPIO25

Pin 22

6

25

SPIMOSI

Pin 19

12

10

GPIO22

Pin 15

3

22

GPIO27

Pin 13

2

27

GPIO17

Pin 11

0

17

SDA1

Pin 3

SDA1(8)

SDA1(2)

SCL1

Pin 5

SCL1(9)

SDA1(3)

../_images/4.1.17_game_guess_number_schematic.png

Procedura Sperimentale

Passo 1: Costruisci il circuito.

../_images/4.1.17_game_guess_number_circuit.png

Passo 2: Configura I2C (vedi Configurazione I²C.)

Passo 3: Cambia directory.

cd ~/raphael-kit/python-pi5

Passo 4: Esegui.

sudo python3 4.1.17_GAME_GuessNumber_zero.py

Dopo l’avvio del programma, la pagina iniziale apparirà sull’LCD:

Benvenuto!
Premi A per iniziare!

Premi “A” e il gioco inizierà; la pagina di gioco apparirà sull’LCD.

Inserisci numero:
0 < punto < 99

Un numero casuale “punto“ viene generato, ma non viene visualizzato sull’LCD quando il gioco inizia, e il tuo compito è indovinarlo. Il numero digitato appare alla fine della prima linea fino al completamento del calcolo finale. (Premi “D” per avviare il confronto, e se il numero inserito è maggiore di 10, il confronto automatico inizierà.)

L’intervallo numerico del ‘punto’ è visualizzato sulla seconda linea. Devi inserire il numero all’interno dell’intervallo. Quando inserisci un numero, l’intervallo si restringe; se hai indovinato il numero fortunato, apparirà «Hai indovinato!»

Nota

  • Se ricevi l’errore FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1', fai riferimento a Configurazione I²C per abilitare l’I2C.

  • Se ricevi l’errore ModuleNotFoundError: No module named 'smbus2', esegui sudo apt install python3-smbus2.

  • Se appare l’errore OSError: [Errno 121] Remote I/O error, significa che il modulo è cablato male o è danneggiato.

  • Se il codice e il cablaggio sono corretti, ma l’LCD non visualizza ancora nulla, puoi regolare il potenziometro sul retro per aumentare il contrasto.

<<<<<<< HEAD Codice ======= .. warning:

Se viene visualizzato l'errore ``RuntimeError: Cannot determine SOC peripheral base address``, fare riferimento a :ref:`faq_soc`.

Code >>>>>>> 387505b31ef24b78d49967f4b4dcfb048c8f48cb

Nota

Puoi Modificare/Resettare/Copiare/Eseguire/Fermare il codice qui sotto. Ma prima di tutto, devi andare al percorso del codice sorgente come raphael-kit/python-pi5. Dopo aver modificato il codice, puoi eseguirlo direttamente per vedere l’effetto.

#!/usr/bin/env python3

from gpiozero import DigitalOutputDevice, Button
from time import sleep
import LCD1602
import random

class Keypad:
   def __init__(self, rows_pins, cols_pins, keys):
      """
      Initialize the keypad with specified row and column pins and key layout.
      :param rows_pins: List of GPIO pins for the rows.
      :param cols_pins: List of GPIO pins for the columns.
      :param keys: Layout of keys on the keypad.
      """
      self.rows = [DigitalOutputDevice(pin) for pin in rows_pins]  # Configura i pin delle righe
      self.cols = [Button(pin, pull_up=False) for pin in cols_pins]  # Configura i pin delle colonne
      self.keys = keys  # Definisce il layout dei tasti

   def read(self):
      """
      Read and return the currently pressed keys.
      :return: List of pressed keys.
      """
      pressed_keys = []
      for i, row in enumerate(self.rows):
            row.on()  # Attiva la riga corrente
            for j, col in enumerate(self.cols):
               if col.is_pressed:
                  index = i * len(self.cols) + j
                  pressed_keys.append(self.keys[index])  # Aggiungi il tasto premuto
            row.off()  # Disattiva la riga
      return pressed_keys

# Variabili relative al gioco
count = 0
pointValue = 0
upper = 99
lower = 0

def setup():
   """
   Setup function for initializing the keypad and LCD display.
   """
   global keypad, last_key_pressed, keys
   rowsPins = [18, 23, 24, 25]
   colsPins = [10, 22, 27, 17]
   keys = ["1", "2", "3", "A",
            "4", "5", "6", "B",
            "7", "8", "9", "C",
            "*", "0", "#", "D"]
   keypad = Keypad(rowsPins, colsPins, keys)
   last_key_pressed = []
   LCD1602.init(0x27, 1)  # Inizializza LCD
   LCD1602.clear()
   LCD1602.write(0, 0, 'Welcome!')
   LCD1602.write(0, 1, 'Press A to Start!')

def init_new_value():
   """
   Initialize a new target value and reset game parameters.
   """
   global pointValue, upper, lower, count
   pointValue = random.randint(0, 99)
   upper = 99
   lower = 0
   count = 0
   print('point is %d' % pointValue)

def detect_point():
   """
   Check if the guessed number is the target, too high, or too low.
   :return: 1 if correct guess, 0 otherwise.
   """
   global count, upper, lower
   if count > pointValue and count < upper:
      upper = count
   elif count < pointValue and count > lower:
      lower = count
   elif count == pointValue:
      count = 0
      return 1
   count = 0
   return 0

def lcd_show_input(result):
   """
   Display the current game state and results on the LCD.
   :param result: Result of the last guess (0 or 1).
   """
   LCD1602.clear()
   if result == 1:
      LCD1602.write(0, 1, 'You have got it!')
      sleep(5)
      init_new_value()
      lcd_show_input(0)
   else:
      LCD1602.write(0, 0, 'Enter number:')
      LCD1602.write(13, 0, str(count))
      LCD1602.write(0, 1, str(lower))
      LCD1602.write(3, 1, ' < Point < ')
      LCD1602.write(13, 1, str(upper))

def loop():
   """
   Main game loop for handling keypad input and updating game state.
   """
   global keypad, last_key_pressed, count
   while True:
      result = 0
      pressed_keys = keypad.read()
      if pressed_keys and pressed_keys != last_key_pressed:
            if pressed_keys == ["A"]:
               init_new_value()
               lcd_show_input(0)
            elif pressed_keys == ["D"]:
               result = detect_point()
               lcd_show_input(result)
            elif pressed_keys[0] in keys:
               if pressed_keys[0] in ["A", "B", "C", "D", "#", "*"]:
                  continue
               count = count * 10 + int(pressed_keys[0])
               if count >= 10:
                  result = detect_point()
               lcd_show_input(result)
            print(pressed_keys)
      last_key_pressed = pressed_keys
      sleep(0.1)

try:
   setup()
   loop()
except KeyboardInterrupt:
   LCD1602.clear()  # Pulisci LCD all'interruzione

Spiegazione del Codice

  1. Questa sezione importa le classi essenziali dalla libreria GPIO Zero per gestire dispositivi di uscita digitale e pulsanti. Include anche la funzione sleep dal modulo time per introdurre ritardi nell’esecuzione dello script. La libreria LCD1602 è importata per operare il display LCD, utile per visualizzare testi o dati. Inoltre, è inclusa la libreria random, che offre funzioni per generare numeri casuali, utili per vari aspetti del progetto.

    #!/usr/bin/env python3
    
    from gpiozero import DigitalOutputDevice, Button
    from time import sleep
    import LCD1602
    import random
    
  2. Definisce una classe per il tastierino, inizializzandolo con i pin delle righe e delle colonne e definendo un metodo per leggere i tasti premuti.

    class Keypad:
       def __init__(self, rows_pins, cols_pins, keys):
          """
          Initialize the keypad with specified row and column pins and key layout.
          :param rows_pins: List of GPIO pins for the rows.
          :param cols_pins: List of GPIO pins for the columns.
          :param keys: Layout of keys on the keypad.
          """
          self.rows = [DigitalOutputDevice(pin) for pin in rows_pins]  # Configura i pin delle righe
          self.cols = [Button(pin, pull_up=False) for pin in cols_pins]  # Configura i pin delle colonne
          self.keys = keys  # Definisce il layout dei tasti
    
       def read(self):
          """
          Read and return the currently pressed keys.
          :return: List of pressed keys.
          """
          pressed_keys = []
          for i, row in enumerate(self.rows):
                row.on()  # Attiva la riga corrente
                for j, col in enumerate(self.cols):
                   if col.is_pressed:
                      index = i * len(self.cols) + j
                      pressed_keys.append(self.keys[index])  # Aggiungi il tasto premuto
                row.off()  # Disattiva la riga
          return pressed_keys
    
  3. Inizializza la variabile count a zero, potenzialmente usata per tenere traccia dei tentativi o dei valori specifici nel gioco. Configura il tastierino e il display LCD con un messaggio di benvenuto e istruzioni. Inizializza la variabile pointValue a zero, probabilmente rappresentante un punteggio o un valore target nel gioco. Definisce un limite upper per il gioco, inizialmente impostato a 99, che potrebbe essere il massimo in un gioco di indovinelli numerici. Imposta il limite lower a partire da zero, probabilmente usato come limite minimo nel gioco.

    # Variabili relative al gioco
    count = 0
    pointValue = 0
    upper = 99
    lower = 0
    
  4. Configura il tastierino e il display LCD, mostrando un messaggio di benvenuto e istruzioni.

    def setup():
       """
       Setup function for initializing the keypad and LCD display.
       """
       global keypad, last_key_pressed, keys
       rowsPins = [18, 23, 24, 25]
       colsPins = [10, 22, 27, 17]
       keys = ["1", "2", "3", "A",
                "4", "5", "6", "B",
                "7", "8", "9", "C",
                "*", "0", "#", "D"]
       keypad = Keypad(rowsPins, colsPins, keys)
       last_key_pressed = []
       LCD1602.init(0x27, 1)  # Inizializza LCD
       LCD1602.clear()
       LCD1602.write(0, 0, 'Welcome!')
       LCD1602.write(0, 1, 'Press A to Start!')
    
  5. Inizializza un nuovo valore target per il gioco e reimposta i parametri del gioco.

    def init_new_value():
       """
       Initialize a new target value and reset game parameters.
       """
       global pointValue, upper, lower, count
       pointValue = random.randint(0, 99)
       upper = 99
       lower = 0
       count = 0
       print('point is %d' % pointValue)
    
  6. Verifica se il numero indovinato corrisponde al target e aggiorna di conseguenza l’intervallo di indovinelli.

    def detect_point():
       """
       Check if the guessed number is the target, too high, or too low.
       :return: 1 if correct guess, 0 otherwise.
       """
       global count, upper, lower
       if count > pointValue and count < upper:
          upper = count
       elif count < pointValue and count > lower:
          lower = count
       elif count == pointValue:
          count = 0
          return 1
       count = 0
       return 0
    
  7. Mostra lo stato del gioco sull’LCD, visualizzando l’indovinello corrente, l’intervallo e il risultato.

    def lcd_show_input(result):
       """
       Display the current game state and results on the LCD.
       :param result: Result of the last guess (0 or 1).
       """
       LCD1602.clear()
       if result == 1:
          LCD1602.write(0, 1, 'You have got it!')
          sleep(5)
          init_new_value()
          lcd_show_input(0)
       else:
          LCD1602.write(0, 0, 'Enter number:')
          LCD1602.write(13, 0, str(count))
          LCD1602.write(0, 1, str(lower))
          LCD1602.write(3, 1, ' < Point < ')
          LCD1602.write(13, 1, str(upper))
    
  8. Il ciclo principale per gestire l’input del tastierino, aggiornare lo stato del gioco e mostrare i risultati sull’LCD.

    def loop():
       """
       Main game loop for handling keypad input and updating game state.
       """
       global keypad, last_key_pressed, count
       while True:
          result = 0
          pressed_keys = keypad.read()
          if pressed_keys and pressed_keys != last_key_pressed:
                if pressed_keys == ["A"]:
                   init_new_value()
                   lcd_show_input(0)
                elif pressed_keys == ["D"]:
                   result = detect_point()
                   lcd_show_input(result)
                elif pressed_keys[0] in keys:
                   if pressed_keys[0] in ["A", "B", "C", "D", "#", "*"]:
                      continue
                   count = count * 10 + int(pressed_keys[0])
                   if count >= 10:
                      result = detect_point()
                   lcd_show_input(result)
                print(pressed_keys)
          last_key_pressed = pressed_keys
          sleep(0.1)
    
  9. Esegue la configurazione e avvia il ciclo principale del gioco, consentendo un’uscita pulita utilizzando un’interruzione della tastiera.

    try:
       setup()
       loop()
    except KeyboardInterrupt:
       LCD1602.clear()  # Pulisci LCD all'interruzione