.. note::
Hallo und willkommen in der SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasten-Gemeinschaft auf Facebook! Tauchen Sie tiefer ein in die Welt von Raspberry Pi, Arduino und ESP32 mit anderen Enthusiasten.
**Warum beitreten?**
- **Expertenunterstützung**: Lösen Sie Nachverkaufsprobleme und technische Herausforderungen mit Hilfe unserer Gemeinschaft und unseres Teams.
- **Lernen & Teilen**: Tauschen Sie Tipps und Anleitungen aus, um Ihre Fähigkeiten zu verbessern.
- **Exklusive Vorschauen**: Erhalten Sie frühzeitigen Zugang zu neuen Produktankündigungen und exklusiven Einblicken.
- **Spezialrabatte**: Genießen Sie exklusive Rabatte auf unsere neuesten Produkte.
- **Festliche Aktionen und Gewinnspiele**: Nehmen Sie an Gewinnspielen und Feiertagsaktionen teil.
👉 Sind Sie bereit, mit uns zu erkunden und zu erschaffen? Klicken Sie auf [|link_sf_facebook|] und treten Sie heute bei!
.. _4.1.17_py_pi5:
4.1.14 SPIEL – Zahlenraten
==============================
Einführung
------------------
Zahlenraten ist ein unterhaltsames Partyspiel, bei dem du und deine Freunde abwechselnd eine Zahl (0~99) eingeben. Mit jeder Eingabe verkleinert sich der Bereich, bis ein Spieler die richtige Zahl errät. Dann wird dieser Spieler „geschlagen“ und „bestraft“. Zum Beispiel, wenn die Glückszahl 51 ist, die die Spieler nicht sehen können, und Spieler ① gibt 50 ein, ändert sich der Bereichszahlenprompt zu 50~99; wenn Spieler ② 70 eingibt, kann der Zahlenbereich 50~70 sein; wenn Spieler ③ 51 eingibt, ist dieser Spieler der Pechvogel. Hier nutzen wir ein Tastenfeld für die Eingabe der Zahlen und ein LCD, um die Ergebnisse anzuzeigen.
Benötigte Komponenten
------------------------------
Für dieses Projekt benötigen wir die folgenden Komponenten.
.. image:: ../python_pi5/img/4.1.17_game_guess_number_list.png
:width: 800
:align: center
Es ist definitiv praktisch, ein ganzes Kit zu kaufen, hier ist der Link:
.. list-table::
:widths: 20 20 20
:header-rows: 1
* - Name
- ARTIKEL IN DIESEM KIT
- LINK
* - Raphael Kit
- 337
- |link_Raphael_kit|
Sie können sie auch separat über die untenstehenden Links kaufen.
.. list-table::
:widths: 30 20
:header-rows: 1
* - KOMPONENTENVORSTELLUNG
- KAUF-LINK
* - :ref:`cpn_gpio_board`
- |link_gpio_board_buy|
* - :ref:`cpn_breadboard`
- |link_breadboard_buy|
* - :ref:`cpn_wires`
- |link_wires_buy|
* - :ref:`cpn_resistor`
- |link_resistor_buy|
* - :ref:`cpn_keypad`
- \-
* - :ref:`cpn_i2c_lcd`
- |link_i2clcd1602_buy|
Schaltplan
-----------------------
============ ======== ======== =======
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)
============ ======== ======== =======
.. image:: ../python_pi5/img/4.1.17_game_guess_number_schematic.png
:align: center
Experimentelle Verfahren
-----------------------------
**Schritt 1:** Bauen Sie den Schaltkreis.
.. image:: ../python_pi5/img/4.1.17_game_guess_number_circuit.png
**Schritt 2**: I2C einrichten (siehe :ref:`i2c_config`.)
**Schritt 3**: Verzeichnis wechseln.
.. raw:: html
.. code-block::
cd ~/raphael-kit/python-pi5
**Schritt 4**: Ausführen.
.. raw:: html
.. code-block::
sudo python3 4.1.17_GAME_GuessNumber_zero.py
Nachdem das Programm gestartet wurde, zeigt das LCD die Startseite:
.. code-block::
Willkommen!
Drücke A zum Start!
Drücke 'A', und das Spiel beginnt, und die Spieloberfläche erscheint auf dem LCD.
.. code-block::
Zahl eingeben:
0 ‹Punkt‹ 99
Eine zufällige Zahl ‹\ **Punkt**\› wird produziert, aber nicht auf dem LCD angezeigt, wenn das Spiel startet, und deine Aufgabe ist es, sie zu erraten. Die von dir getippte Zahl erscheint am Ende der ersten Zeile, bis die endgültige Berechnung abgeschlossen ist. (Drücke 'D' zum Starten des Vergleichs, und wenn die eingegebene Zahl größer als **10** ist, startet der automatische Vergleich.)
Der Zahlenbereich von 'Punkt' wird in der zweiten Zeile angezeigt. Und du musst eine Zahl innerhalb des Bereichs tippen. Wenn du eine Zahl tippst, verengt sich der Bereich; wenn du die Glückszahl glücklich oder unglücklich triffst, erscheint "Du hast es geschafft!"
.. note::
* Wenn der Fehler ``FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1'`` auftritt, beziehe dich auf :ref:`i2c_config`, um das I2C zu aktivieren.
* Wenn der Fehler ``ModuleNotFoundError: No module named 'smbus2'`` auftritt, führe bitte ``sudo apt install python3-smbus2`` aus.
* Wenn der Fehler ``OSError: [Errno 121] Remote I/O error`` erscheint, bedeutet dies, dass das Modul falsch verdrahtet ist oder das Modul defekt ist.
* Wenn der Code und die Verdrahtung in Ordnung sind, aber das LCD immer noch keinen Inhalt anzeigt, kannst du das Potentiometer auf der Rückseite drehen, um den Kontrast zu erhöhen.
.. warning::
Wenn die Fehlermeldung ``RuntimeError: Cannot determine SOC peripheral base address`` angezeigt wird, lesen Sie bitte :ref:`faq_soc`
**Code**
.. note::
Du kannst den untenstehenden Code **Modifizieren/Zurücksetzen/Kopieren/Ausführen/Stoppen**. Aber davor musst du zum Quellcodepfad wie ``raphael-kit/python-pi5``. Nachdem du den Code modifiziert hast, kannst du ihn direkt ausführen, um den Effekt zu sehen.
.. raw:: html
.. code-block:: python
#!/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] # Setup row pins
self.cols = [Button(pin, pull_up=False) for pin in cols_pins] # Setup column pins
self.keys = keys # Define keypad layout
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() # Activate current row
for j, col in enumerate(self.cols):
if col.is_pressed:
index = i * len(self.cols) + j
pressed_keys.append(self.keys[index]) # Append pressed key
row.off() # Deactivate row
return pressed_keys
# Game-related variables
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) # Initialize 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() # Clear LCD on interrupt
**Code-Erklärung**
#. Dieser Abschnitt importiert die notwendigen Klassen aus der GPIO Zero-Bibliothek, um digitale Ausgabegeräte und Tasten zu handhaben. Außerdem wird die sleep-Funktion aus dem time-Modul zum Einführen von Verzögerungen im Skriptablauf importiert. Die LCD1602-Bibliothek wird für die Bedienung des LCD-Displays importiert, was nützlich ist, um Text oder Datenausgaben anzuzeigen. Zusätzlich wird die random-Bibliothek eingefügt, die Funktionen zur Erzeugung zufälliger Zahlen bietet, was für verschiedene Aspekte des Projekts vorteilhaft sein kann.
.. code-block:: python
#!/usr/bin/env python3
from gpiozero import DigitalOutputDevice, Button
from time import sleep
import LCD1602
import random
#. Definiert eine Klasse für das Keypad, initialisiert es mit Zeilen- und Spaltenpins und definiert eine Methode zum Lesen gedrückter Tasten.
.. code-block:: python
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] # Setup row pins
self.cols = [Button(pin, pull_up=False) for pin in cols_pins] # Setup column pins
self.keys = keys # Define keypad layout
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() # Activate current row
for j, col in enumerate(self.cols):
if col.is_pressed:
index = i * len(self.cols) + j
pressed_keys.append(self.keys[index]) # Append pressed key
row.off() # Deactivate row
return pressed_keys
#. Initialisiert eine Variable „count“ als Null, möglicherweise verwendet, um Versuche oder spezifische Werte im Spiel zu verfolgen. Konfiguriert das Keypad und LCD-Display mit einer Begrüßungsnachricht und Anweisungen. Initialisiert die Variable „pointValue“ auf Null, möglicherweise repräsentiert sie einen Zielwert oder Punktestand im Spiel. Definiert eine „obere“ Grenze für das Spiel, zunächst auf 99 gesetzt, was das Maximum in einem Zahlenratespiel sein könnte. Setzt die „untere“ Grenze beginnend von Null, wahrscheinlich verwendet als minimale Grenze im Spiel.
.. code-block:: python
# Game-related variables
count = 0
pointValue = 0
upper = 99
lower = 0
#. Richtet das Keypad und LCD-Display ein, zeigt eine Begrüßungsnachricht und Anweisungen an.
.. code-block:: python
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) # Initialize LCD
LCD1602.clear()
LCD1602.write(0, 0, 'Welcome!')
LCD1602.write(0, 1, 'Press A to Start!')
#. Initialisiert einen neuen Zielwert für das Spiel und setzt die Spielparameter zurück.
.. code-block:: python
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)
#. Überprüft, ob die geratene Zahl dem Ziel entspricht und aktualisiert entsprechend den Ratebereich.
.. code-block:: python
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
#. Zeigt den Spielstand auf dem LCD an, zeigt die aktuelle Vermutung, den Bereich und das Ergebnis.
.. code-block:: python
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))
#. Die Hauptschleife zur Handhabung der Keypad-Eingabe, Aktualisierung des Spielstands und Anzeige der Ergebnisse auf dem LCD.
.. code-block:: python
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)
#. Führt das Setup aus und tritt in die Hauptschleife ein, ermöglicht einen sauberen Ausstieg mit einem Tastaturinterrupt.
.. code-block:: python
try:
setup()
loop()
except KeyboardInterrupt:
LCD1602.clear() # Clear LCD on interrupt