.. note:: ¡Hola! Bienvenido a la Comunidad de Entusiastas de SunFounder Raspberry Pi & Arduino & ESP32 en Facebook. Sumérgete más en Raspberry Pi, Arduino y ESP32 con otros entusiastas. **¿Por qué unirse?** - **Soporte experto**: Resuelve problemas postventa y desafíos técnicos con la ayuda de nuestra comunidad y equipo. - **Aprende y comparte**: Intercambia consejos y tutoriales para mejorar tus habilidades. - **Previsualizaciones exclusivas**: Obtén acceso anticipado a nuevos anuncios de productos y adelantos. - **Descuentos especiales**: Disfruta de descuentos exclusivos en nuestros productos más nuevos. - **Promociones y sorteos festivos**: Participa en sorteos y promociones navideñas. 👉 ¿Listo para explorar y crear con nosotros? Haz clic en [|link_sf_facebook|] y únete hoy mismo. .. _4.1.17_py: 4.1.17 JUEGO – Adivina el Número ============================================== Introducción ------------------ Adivinar Números es un divertido juego de fiesta donde tú y tus amigos toman turnos para ingresar un número (0~99). El rango será más pequeño con la entrada del número hasta que un jugador responda el acertijo correctamente. Entonces el jugador es derrotado y castigado. Por ejemplo, si el número de la suerte es 51, que los jugadores no pueden ver, y el jugador ① ingresa 50, el rango de números cambia a 50~99; si el jugador ② ingresa 70, el rango de números puede ser 50~70; si el jugador ③ ingresa 51, este jugador es el desafortunado. Aquí, usamos un teclado para ingresar números y una pantalla LCD para mostrar los resultados. Componentes necesarios ------------------------------ En este proyecto, necesitamos los siguientes componentes. .. image:: ../img/list_GAME_Guess_Number.png :align: center Es definitivamente conveniente comprar un kit completo, aquí está el enlace: .. list-table:: :widths: 20 20 20 :header-rows: 1 * - Nombre - ARTÍCULOS EN ESTE KIT - ENLACE * - Kit Raphael - 337 - |link_Raphael_kit| También puedes comprarlos por separado en los enlaces a continuación. .. list-table:: :widths: 30 20 :header-rows: 1 * - INTRODUCCIÓN DEL COMPONENTE - ENLACE DE COMPRA * - :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| Diagrama esquemático ------------------------- ============== ========== ======== ======= Nombre T-Board Pin físico 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:: ../img/Schematic_three_one12.png :align: center Procedimientos Experimentales --------------------------------- **Paso 1:** Construye el circuito. .. image:: ../img/image273.png **Paso 2**: Configura I2C (ver :ref:`i2c_config`). **Paso 3**: Cambia de directorio. .. raw:: html .. code-block:: cd ~/raphael-kit/python/ **Paso 4**: Ejecuta. .. raw:: html .. code-block:: sudo python3 4.1.17_GAME_GuessNumber.py Después de que el programa se ejecute, se muestra la página inicial en la LCD: .. code-block:: Welcome! Press A to go! Presiona 'A' y el juego comenzará y la página del juego aparecerá en la LCD. .. code-block:: Enter number: 0 ‹punto‹ 99 Se produce un número aleatorio 'punto' pero no se muestra en la LCD cuando el juego comienza, y lo que necesitas hacer es adivinarlo. El número que has escrito aparece al final de la primera línea hasta que se finaliza el cálculo. (Presiona 'D' para iniciar la comparación, y si el número ingresado es mayor que 10, la comparación automática comenzará). El rango de números de 'punto' se muestra en la segunda línea. Y debes escribir el número dentro del rango. Cuando escribes un número, el rango se reduce; si adivinaste el número de la suerte afortunada o desafortunadamente, aparecerá "¡Lo conseguiste!". .. note:: * Si obtienes el error ``FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1'``, necesitas consultar :ref:`i2c_config` para habilitar el I2C. * Si obtienes el error ``ModuleNotFoundError: No module named 'smbus2'``, por favor ejecuta ``sudo apt install python3-smbus2``. * Si aparece el error ``OSError: [Errno 121] Remote I/O error``, significa que el módulo está mal conectado o está dañado. * Si el código y las conexiones están bien, pero la LCD aún no muestra contenido, puedes girar el potenciómetro en la parte posterior para aumentar el contraste. **Código** .. note:: Puedes **Modificar/Restablecer/Copiar/Ejecutar/Detener** el código a continuación. Pero antes de eso, necesitas ir a la ruta del código fuente como ``raphael-kit/python``. Después de modificar el código, puedes ejecutarlo directamente para ver el efecto. .. raw:: html .. code-block:: python #!/usr/bin/env python3 import RPi.GPIO as GPIO import time import LCD1602 import random ##################### AQUÍ ESTÁ LA LIBRERÍA DE TECLADO TRANSPLANTADA DESDE Arduino ############ #class Key: Define algunas propiedades de Key class Keypad(): def __init__(self, rowsPins, colsPins, keys): self.rowsPins = rowsPins self.colsPins = colsPins self.keys = keys GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) GPIO.setup(self.rowsPins, GPIO.OUT, initial=GPIO.LOW) GPIO.setup(self.colsPins, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) def read(self): pressed_keys = [] for i, row in enumerate(self.rowsPins): GPIO.output(row, GPIO.HIGH) for j, col in enumerate(self.colsPins): index = i * len(self.colsPins) + j if (GPIO.input(col) == 1): pressed_keys.append(self.keys[index]) GPIO.output(row, GPIO.LOW) return pressed_keys ################ EL CÓDIGO DE EJEMPLO EMPIEZA AQUÍ ################ count = 0 pointValue = 0 upper=99 lower=0 def setup(): 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) # init(slave address, background light) LCD1602.clear() LCD1602.write(0, 0, 'Welcome!') LCD1602.write(0, 1, 'Press A to Start!') def init_new_value(): global pointValue,upper,count,lower pointValue = random.randint(0,99) upper = 99 lower = 0 count = 0 print('point is %d' %(pointValue)) def detect_point(): global count,upper,lower if count > pointValue: if count < upper: upper = count elif count < pointValue: if count > lower: lower = count elif count == pointValue: count = 0 return 1 count = 0 return 0 def lcd_show_input(result): LCD1602.clear() if result == 1: LCD1602.write(0,1,'You have got it!') time.sleep(5) init_new_value() lcd_show_input(0) return 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(): global keypad, last_key_pressed,count while(True): result = 0 pressed_keys = keypad.read() if len(pressed_keys) != 0 and last_key_pressed != pressed_keys: 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 list(["A","B","C","D","#","*"]): continue count = count * 10 count += int(pressed_keys[0]) if count >= 10: result = detect_point() lcd_show_input(result) print(pressed_keys) last_key_pressed = pressed_keys time.sleep(0.1) # Define una función destroy para limpiar todo después de que el script termine def destroy(): # Liberar recursos GPIO.cleanup() LCD1602.clear() if __name__ == '__main__': # Program start from here try: setup() while True: loop() except KeyboardInterrupt: # Cuando se presiona 'Ctrl+C', se ejecutará la función destroy(). destroy() **Explicación del Código** En la parte inicial del código se encuentran las funciones funcionales del **teclado** y del **I2C LCD1602**. Puedes aprender más detalles sobre ellas en :ref:`1.1.7_py` y :ref:`2.1.8_py`. Aquí, lo que necesitamos saber es lo siguiente: .. code-block:: python def init_new_value():     global pointValue,upper,count,lower     pointValue = random.randint(0,99)     upper = 99     lower = 0     count = 0     print('point is %d' %(pointValue)) La función produce el número aleatorio ‘\ **point**\ ’ y restablece el rango de pistas del punto. .. code-block:: python def detect_point():     global count,upper,lower     if count > pointValue:         if count < upper:             upper = count      elif count < pointValue:         if count > lower:             lower = count     elif count == pointValue:         count = 0         return 1     count = 0     return 0 ``detect_point()`` compara el número ingresado (**count**) con el número producido “\ **point**\ ”. Si el resultado de la comparación indica que no son iguales, **count** asignará valores a **upper** y **lower** y devolverá ‘\ **0**\ ’; de lo contrario, si el resultado indica que son iguales, se devolverá ‘\ **1**\ ’. .. code-block:: python def lcd_show_input(result): LCD1602.clear()     if result == 1:         LCD1602.write(0,1,'You have got it!') time.sleep(5) init_new_value() lcd_show_input(0) return     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)) Esta función se utiliza para mostrar la página del juego. ``str(count)``: Debido a que ``write()`` solo puede soportar el tipo de dato — **cadena** , se necesita ``str()`` para convertir el **número** en **cadena**. .. code-block:: python def loop():     global keypad, last_key_pressed,count while(True):         result = 0         pressed_keys = keypad.read()         if len(pressed_keys) != 0 and last_key_pressed != pressed_keys:             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 list(["A","B","C","D","#","*"]): continue                 count = count * 10                 count += int(pressed_keys[0])                 if count >= 10:                     result = detect_point() lcd_show_input(result) print(pressed_keys)         last_key_pressed = pressed_keys time.sleep(0.1) ``main()`` contiene todo el proceso del programa, como se muestra a continuación: 1) Inicializa **I2C LCD1602** y **Keypad**. 2) Juzga si se ha presionado el botón y obtiene la lectura del botón. 3) Si se presiona el botón ‘\ **A**\ ’, aparecerá un número aleatorio **0-99** y luego comenzará el juego. 4) Si se detecta que el botón ‘\ **D**\ ’ ha sido presionado, el programa entrará en el juicio del resultado. 5) Si se presiona el botón **0-9**, el valor de **count** cambiará; si **count** es mayor que **10**, entonces comenzará el juicio. 6) Los cambios del juego y sus valores se muestran en **LCD1602**. Imagen del Fenómeno ------------------------ .. image:: ../img/image274.jpeg :align: center