.. note::

    ¡Hola! Bienvenido a la Comunidad de Entusiastas de SunFounder para Raspberry Pi, Arduino y ESP32 en Facebook. Sumérgete en el mundo de Raspberry Pi, Arduino y ESP32 junto a otros apasionados.

    **¿Por qué unirte?**

    - **Soporte Experto**: Resuelve problemas postventa y desafíos técnicos con ayuda de nuestra comunidad y equipo.
    - **Aprende y Comparte**: Intercambia consejos y tutoriales para mejorar tus habilidades.
    - **Preestrenos Exclusivos**: Accede anticipadamente a anuncios de nuevos productos.
    - **Descuentos Especiales**: Disfruta de descuentos exclusivos en nuestros productos más recientes.
    - **Promociones Festivas y Sorteos**: Participa en sorteos y promociones especiales.

    👉 ¿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 divertido en el que tú y tus amigos turnan 
para ingresar un número (0~99). El rango se reducirá con cada intento hasta 
que uno de los jugadores adivine el número correcto y, al hacerlo, pierde el 
juego y recibe una “penalización”. Por ejemplo, si el número oculto es 51 y 
el jugador ① introduce 50, el rango cambia a 50~99; si el jugador ② introduce 
70, el rango cambia a 50~70; si el jugador ③ introduce 51, es el jugador 
desafortunado. En este proyecto, utilizamos un teclado para introducir los 
números y una pantalla LCD para mostrar los resultados.

Componentes
-------------

.. image:: img/list_GAME_Guess_Number.png
    :align: center

Diagrama de 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).

**Paso 3**: Cambia de directorio.

.. raw:: html

   <run></run>

.. code-block::

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

**Paso 4**: Compila el código.

.. raw:: html

   <run></run>

.. code-block::

    gcc 3.1.12_GAME_GuessNumber.c -lwiringPi

**Paso 5**: Ejecuta el archivo compilado.

.. raw:: html

   <run></run>

.. code-block::

    sudo ./a.out

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

.. code-block:: 

   Welcome!
   Press A to go!

Presiona 'A' para iniciar el juego, y la pantalla LCD mostrará la página del juego.

.. code-block:: 

   Enter number:
   0 ‹point‹ 99

.. note::

   Si no funciona tras ejecutarse o aparece un mensaje de error como : \"wiringPi.h: No such file or directory\", consulta :ref:`C code is not working?`.


Cuando comienza el juego, se genera un número aleatorio \'**point**\', 
que no se muestra en la pantalla LCD. Debes adivinarlo. El número ingresado 
aparecerá al final de la primera línea hasta que se realice el cálculo final. 
(Presiona 'D' para iniciar la comparación y, si el número ingresado es mayor 
de **10**, la comparación se iniciará automáticamente).

El rango del número \'point\' se muestra en la segunda línea, y debes ingresar 
un número dentro de este rango. Cada vez que introduces un número, el rango se 
reduce; si adivinas el número por suerte (o por mala suerte), aparecerá el mensaje \"You've got it!\"

**Explicación del Código**

La primera parte del código contiene las funciones de 
**teclado** y **LCD I2C 1602**. Para conocer más detalles, 
consulta **1.1.7 LCD I2C 1602** y **2.1.5 Teclado**.

Aquí lo que necesitamos saber es lo siguiente:

.. code-block:: c

    /****************************************/
    //Inicio 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 define inicialmente **LCD I2C 1602** y **Teclado**, 
y muestra "Welcome!" y "Press A to go!".

.. 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 produce el número aleatorio \'**point**\' y restablece el 
rango de sugerencia 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 introducido con el \"point\" generado. 
Si el resultado de la comparación indica que no son iguales, **count** 
asignará valores a **upper** y **lower** y retornará \'**0**\'; en caso 
contrario, si son iguales, retornará \'**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,"<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 una visualización correcta en **lcd**.

.. code-block:: c

    int main(){
        unsigned char pressed_keys[BUTTON_NUM];
        unsigned char last_key_pressed[BUTTON_NUM];
        if(wiringPiSetup() == -1){ //si la inicialización de wiring falla, muestra mensaje en pantalla
            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 el proceso completo del programa, como se muestra a continuación:

1) Inicializa **LCD I2C 1602** y **Teclado**.

2) Usa **init_new_value()** para crear un número aleatorio entre **0-99**.

3) Verifica si se ha presionado algún botón y obtiene la lectura.

4) Si se presiona el botón \'**A**\', aparecerá un número aleatorio entre **0-99** y comenzará el juego.

5) Si se detecta que se presionó el botón \'**D**\', el programa ingresará al 
   proceso de verificación y mostrará el resultado en la pantalla LCD. Esto permite 
   verificar el resultado incluso si se introduce solo un número y luego se presiona 
   el botón \'**D**\'.

6) Si se presiona un botón entre **0-9**, el valor de **count** cambiará; 
   si **count** es mayor que **10**, comenzará la verificación.

7) Los cambios del juego y sus valores se muestran en **LCD1602**.

