.. note::
¡Hola! Bienvenido a la comunidad de entusiastas de SunFounder para Raspberry Pi, Arduino y ESP32 en Facebook. Únete para profundizar en Raspberry Pi, Arduino y ESP32 junto a otros apasionados.
**¿Por qué unirte?**
- **Soporte de Expertos**: Resuelve problemas post-venta y desafíos técnicos con la ayuda de nuestra comunidad y equipo.
- **Aprende y Comparte**: Intercambia consejos y tutoriales para mejorar tus habilidades.
- **Avances Exclusivos**: Obtén acceso anticipado a anuncios de nuevos productos y vistas previas.
- **Descuentos Especiales**: Disfruta de descuentos exclusivos en nuestros productos más recientes.
- **Promociones Festivas y Sorteos**: Participa en sorteos y promociones de temporada.
👉 ¿Listo para explorar y crear con nosotros? Haz clic en [|link_sf_facebook|] y únete hoy.
3.1.12 JUEGO– Adivina el Número
=================================
Introducción
------------------
Adivina el Número es un juego de fiesta en el que tú y tus amigos toman
turnos para ingresar un número (0~99). El rango se reduce con cada intento
hasta que un jugador adivina correctamente, momento en el cual el jugador
pierde y recibe un castigo. Por ejemplo, si el número secreto es 51 (invisible
para los jugadores) y el jugador ① ingresa 50, el rango se ajusta a 50~99;
si el jugador ② ingresa 70, el rango será de 50~70; si el jugador ③ ingresa
51, este jugador será el desafortunado. Aquí, usamos un teclado para ingresar
números y una LCD para mostrar los resultados.
Componentes
-----------------
.. image:: img/list_GAME_Guess_Number.png
:align: center
Diagrama Esquemático
-----------------------
============ ======== ======== =======
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:: img/Schematic_three_one12.png
:align: center
Procedimientos Experimentales
---------------------------------
**Paso 1:** Construye el circuito.
.. image:: img/image273.png
:alt: Guess Number_bb
:width: 800
**Paso 2**: Configura I2C (consulta el Apéndice. Si ya lo has configurado,
omite este paso.)
**Para Usuarios de Lenguaje C**
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
**Paso 3**: Cambia de directorio.
.. raw:: html
.. code-block::
cd ~/davinci-kit-for-raspberry-pi/c/3.1.12/
**Paso 4**: Compila.
.. raw:: html
.. code-block::
gcc 3.1.12_GAME_GuessNumber.c -lwiringPi
**Paso 5**: Ejecuta.
.. raw:: html
.. code-block::
sudo ./a.out
Después de ejecutar el programa, la pantalla LCD muestra la página inicial:
.. code-block::
Welcome!
Press A to go!
Presiona \'A\', y el juego comenzará mostrando la página de juego en la
LCD.
.. code-block::
Enter number:
0 ‹point‹ 99
.. note::
Si no funciona después de ejecutarlo, o aparece un mensaje de error: \"wiringPi.h: No such file or directory", consulta :ref:`faq_c_nowork`.
Un número aleatorio \'**punto**\' es generado pero no se muestra en la pantalla
LCD cuando el juego comienza, y lo que necesitas hacer es adivinarlo. El número
ingresado aparecerá al final de la primera línea hasta que se complete el cálculo
final. (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 del número \'punto\' se muestra en la segunda línea, y debes ingresar
un número dentro de ese rango. A medida que ingresas un número, el rango se
reduce; si adivinas el número afortunado o desafortunado, aparecerá el mensaje
\"¡Lo conseguiste!\"
**Explicación del Código**
Al comienzo del código se encuentran las funciones para manejar el **teclado** y
la **LCD I2C 1602**. Puedes obtener más detalles sobre estas funciones en
:ref:`1.1.7_i2c_lcd` y :ref:`2.1.5_keypad`
Aquí, lo que necesitamos saber es lo siguiente:
.. code-block:: c
/****************************************/
//Comienza desde aquí
/****************************************/
void init(void){
fd = wiringPiI2CSetup(LCDAddr);
lcd_init();
lcd_clear();
for(int i=0 ; i<4 ; i++) {
pinMode(rowPins[i], OUTPUT);
pinMode(colPins[i], INPUT);
}
lcd_clear();
write(0, 0, "Welcome!");
write(0, 1, "Press A to go!");
}
Esta función se utiliza para definir inicialmente **I2C LCD1602** y **Teclado**
y para mostrar \"¡Bienvenido!\" y \"Presiona A para empezar\".
.. code-block:: c
void init_new_value(void){
srand(time(0));
pointValue = rand()%100;
upper = 99;
lower = 0;
count = 0;
printf("point is %d\n",pointValue);
}
La función genera el número aleatorio \'**punto**\' y restablece el rango del punto.
.. code-block:: c
bool detect_point(void){
if(count > pointValue){
if(count < upper){
upper = count;
}
}
else if(count < pointValue){
if(count > lower){
lower = count;
}
}
else if(count = pointValue){
count = 0;
return 1;
}
count = 0;
return 0;
}
detect_point() compara el número ingresado con el \"punto\" generado. Si
el resultado de la comparación es que no coinciden, **count** asignará
valores a **upper** y **lower** y devolverá \'**0**\'; de lo contrario, si
el resultado indica coincidencia, devuelve \'**1**\'.
.. code-block:: c
void lcd_show_input(bool result){
char *str=NULL;
str =(char*)malloc(sizeof(char)*3);
lcd_clear();
if (result == 1){
write(0,1,"You've got it!");
delay(5000);
init_new_value();
lcd_show_input(0);
return;
}
write(0,0,"Enter number:");
Int2Str(str,count);
write(13,0,str);
Int2Str(str,lower);
write(0,1,str);
write(3,1,"='0' && pressed_keys[0] <= '9'){
count = count * 10;
count = count + (pressed_keys[0] - 48);
if (count>=10){
result = detect_point();
}
lcd_show_input(result);
}
}
keyCopy(last_key_pressed, pressed_keys);
}
delay(100);
}
return 0;
}
Main() contiene todo el proceso del programa, como se muestra a continuación:
1) Inicializa **I2C LCD1602** y **Teclado**.
2) Usa **init_new_value()** para crear un número aleatorio entre **0-99**.
3) Determina si se ha presionado un botón y obtiene la lectura del botón.
4) Si se presiona el botón \'**A**\', aparecerá un número aleatorio **0-99** y
el juego comienza.
5) Si se detecta que se ha presionado el botón \'**D**\', el programa entra en
el juicio de resultado y muestra el resultado en la LCD. Este paso permite
que puedas juzgar el resultado presionando solo un número y luego el botón \'**D**\'.
6) Si se presiona un botón **0-9**, el valor de **count** cambiará; si **count**
es mayor que **10**, entonces comienza el juicio.
7) Los cambios en el juego y sus valores se muestran en la **LCD1602**.
**Para Usuarios de Lenguaje Python**
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
**Paso 3**: Cambia de directorio.
.. raw:: html
.. code-block::
cd ~/davinci-kit-for-raspberry-pi/python/
**Paso 4**: Ejecuta.
.. raw:: html
.. code-block::
sudo python3 3.1.12_GAME_GuessNumber.py
Después de ejecutar el programa, la pantalla LCD muestra la página inicial:
.. code-block::
Welcome!
Press A to go!
Presiona \'A\', y el juego comenzará mostrando la página de juego en la
LCD.
.. code-block::
Enter number:
0 ‹point‹ 99
Un número aleatorio \'**punto**\' es generado pero no se muestra en la
pantalla LCD cuando el juego comienza, y lo que necesitas hacer es adivinarlo.
El número ingresado aparecerá al final de la primera línea hasta que se complete
el cálculo final. (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 del número \'punto\' se muestra en la segunda línea, y debes ingresar
un número dentro de ese rango. A medida que ingresas un número, el rango se
reduce; si adivinas el número afortunado o desafortunado, aparecerá el mensaje
\"¡Lo conseguiste!\"
**Código**
.. note::
Puedes **Modificar/Restablecer/Copiar/Ejecutar/Detener** el código a
continuación. Pero antes, necesitas dirigirte a la ruta del código fuente,
como ``davinci-kit-for-raspberry-pi/python``.
.. raw:: html
.. code-block:: python
import RPi.GPIO as GPIO
import time
import LCD1602
import random
##################### AQUÍ ESTÁ LA LIBRERÍA DEL TECLADO TRANSFERIDA DESDE Arduino ############
#class Key: Define algunas de las 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 INICIA 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) # inicializar (dirección esclava, luz de fondo)
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 haya terminado
def destroy():
# Liberar recursos
GPIO.cleanup()
LCD1602.clear()
if __name__ == '__main__': # El programa comienza desde aquí
try:
setup()
while True:
loop()
except KeyboardInterrupt: # Cuando se presiona 'Ctrl+C', se ejecuta destroy().
destroy()
**Explicación del Código**
Al comienzo del código se encuentran las funciones funcionales de
**teclado** y **I2C LCD1602**. Puedes obtener más detalles sobre ellas en
:ref:`1.1.7_i2c_lcd` y :ref:`2.1.5_keypad`.
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 genera el número aleatorio \'**punto**\' y restablece el
rango 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 \"**punto**\"
generado. Si el resultado de la comparación es que no coinciden, **count**
asignará valores a **upper** y **lower** y devolverá \'**0**\';
de lo contrario, si el resultado indica coincidencia, devuelve \'**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 admite el tipo de dato —
**cadena de caracteres**, es necesario **str()** para convertir el
**número** en una **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 **Teclado**.
2) Verifica si se ha presionado un 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 el juego comenzará.
4) Si se detecta que se ha presionado el botón \'**D**\', el programa entrará
en el juicio de resultado.
5) Si se presiona un botón **0-9**, el valor de **count** cambiará; si **count**
es mayor que **10**, entonces comenzará el juicio.
6) Los cambios en el juego y sus valores se muestran en **LCD1602**.
Imagen del Fenómeno
------------------------
.. image:: img/image274.jpeg
:align: center