Nota

¡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 [Aquí] 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

_images/list_GAME_Guess_Number.png

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)

_images/Schematic_three_one12.png

Procedimientos Experimentales

Paso 1: Construye el circuito.

Guess Number_bb

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.

cd ~/davinci-kit-for-raspberry-pi/c/3.1.12/

Paso 4: Compila.

gcc 3.1.12_GAME_GuessNumber.c -lwiringPi

Paso 5: Ejecuta.

sudo ./a.out

Después de ejecutar el programa, la pantalla LCD muestra la página inicial:

Welcome!
Press A to go!

Presiona 'A', y el juego comenzará mostrando la página de juego en la LCD.

Enter number:
0 ‹point‹ 99

Nota

Si no funciona después de ejecutarlo, o aparece un mensaje de error: "wiringPi.h: No such file or directory», consulta ¿El código en C no funciona?.

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 1.1.7 I2C LCD1602 y 2.1.5 Keypad

Aquí, lo que necesitamos saber es lo siguiente:

/****************************************/
//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".

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.

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'.

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,"<Point<");
    Int2Str(str,upper);
    write(12,1,str);
}

Esta función muestra la página del juego. Presta atención a la función Int2Str(str, count), que convierte las variables count, lower, y upper de entero a cadena de caracteres para la visualización correcta en la LCD.

int main(){
    unsigned char pressed_keys[BUTTON_NUM];
    unsigned char last_key_pressed[BUTTON_NUM];
    if(wiringPiSetup() == -1){ //when initialize wiring failed,print messageto screen
        printf("setup wiringPi failed !");
        return 1;
    }
    init();
    init_new_value();
    while(1){
        keyRead(pressed_keys);
        bool comp = keyCompare(pressed_keys, last_key_pressed);
        if (!comp){
            if(pressed_keys[0] != 0){
                bool result = 0;
                if(pressed_keys[0] == 'A'){
                    init_new_value();
                    lcd_show_input(0);
                }
                else if(pressed_keys[0] == 'D'){
                    result = detect_point();
                    lcd_show_input(result);
                }
                else if(pressed_keys[0] >='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.

cd ~/davinci-kit-for-raspberry-pi/python/

Paso 4: Ejecuta.

sudo python3 3.1.12_GAME_GuessNumber.py

Después de ejecutar el programa, la pantalla LCD muestra la página inicial:

Welcome!
Press A to go!

Presiona 'A', y el juego comenzará mostrando la página de juego en la LCD.

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

Nota

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.

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 1.1.7 I2C LCD1602 y 2.1.5 Keypad.

Aquí, lo que necesitamos saber es lo siguiente:

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.

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'.

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.

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

_images/image274.jpeg