SIMON

Dependencies:   mbed tsi_sensor

Revision:
1:6cb3e90ec4f3
Parent:
0:31131c8fdcfb
--- a/main.cpp	Wed Jun 19 12:44:51 2019 +0000
+++ b/main.cpp	Sat Jun 22 00:02:57 2019 +0000
@@ -1,53 +1,52 @@
 #include "mbed.h"
 
-enum{MUESTRA,MUESTRA2,NO_MUESTRA,NO_MUESTRA2,NO_INGRESA,INGRESA,ESPERA,FAIL};
+//Creo los estados
+enum{MUESTRA,MUESTRA2,NO_MUESTRA,NO_MUESTRA2,NO_INGRESA,INGRESA,ESPERA,FIN,LEE,APAGA,AGUARDA};
+//   |--------------------------------------|-----------------------------|-----------------|
+//          GENERACIÓN DE SECUENCIA                 CONFIRMACIÓN              PULSADORES
 
-const int MaxElem=5;
+//Defino la cantidad máxima de elementos
+const int MaxElem=24;
 
+//Defino como salidas el led RGB en los tres colores, Red, Green y Blue
 DigitalOut ledR(LED1);
 DigitalOut ledG(LED2);
 DigitalOut ledB(LED3);
 
-DigitalIn E1r(D2);
-DigitalIn E2r(D3);
-DigitalIn E3r(D4);
+//Defino como entradas los 3 pulsadores (para Red, Green y Blue) y el pulsador para el reseteo
+DigitalIn E1r(D2);  //Pulsador para el color Rojo  (R)
+DigitalIn E2r(D3);  //Pulsador para el color Verde (G)
+DigitalIn E3r(D4);  //Pulsador para el color Azul  (B)
 DigitalIn reseteo(D5);
 
+//Variables donde guardo los valores de las entradas de los 3 colores
+int E1; // <-- E1r
+int E2; // <-- E2r
+int E3; // <-- E3r
+
+//Creo los tickers
 Ticker pantalla;
-Ticker leer;
+Ticker mostrarLeds;
 Ticker Interludio;
 
-int HG=1;
-int E1;
-int E2;
-int E3;
+//Las funciones de cada ticker respectivamente
+void visualizaTexto();      //Muestra en el Hercules los datos cada vez que se entra a la función
+void visualizaSecuencia();  //Hace que, cada cierto tiempo, se prenda el led correspondiente a la parte de la secuencia en la que está  
+void tiempoLedsOn();        //Define básicamente cuánto tiempo quedan prendidos los leds antes de apagarse otra vez para esperar el próx.color o botón presionado
+
+//Función encargada del reseteo de todas las variables y volver al estado inicial de cada máquina de estados
+void reset();
 
-int i=0;
-int i2=0;
-int i3=0;
-int i4=0;
-int iMuestra=0;
+//Funciones que son las máquinas de estados
+void detectorPulsado();     //Detecta qué botón de los 3 de colores tocaste quitando el rebote
+void generadorSecuencia();  //Genera la secuencia
+void confirmacion();        //Confirma si lo ingresado con los pulsadores corresponde con la secuencia
 
-int a=0;
-int b=0;
-int c=0;
-
+//Variables que indican los estados de las máquinas de estados
+int estadosPulsadores;
 int estadosSecuencia;
 int estadosConfirm;
 
-int CT=0;
-int EP;
-int LED;
-
-int print=0;
-
-int contar=0;
-
-int j;
-int x;
-int w;
-int p;
-int l=0;
 
 int vecR[MaxElem];
 int vecG[MaxElem];
@@ -56,59 +55,71 @@
 int vecE2[MaxElem];
 int vecE3[MaxElem];
 
-void generadorSecuencia();
-void detectorPulsado();
-void confirmacion();
-void leerFuncion();
-void cutled();
-void pantalleate();
+//Variable que determina si se tiene que generar una nueva secuencia o no (Habilita Generación)
+int HG;
+//Variable que indica la Cantidad Total de posiciones de la secuencia
+int CT=0;
+//Variable que indica en cuál de las posiciones de la secuencia está en el momento (Estado Parcial)
+int EP;
+//Variable que guarda un número random del cuál depende cuál color se va a guardar en esa posición de la secuencia
+int LED;
+
+//Variables que cuentan diferentes cosas
+int iSecuencia=0;   //Posición de la secuencia para generar la secuencia
+int iIngresado=0;   //Cantidad de veces que algo fue ingresado mediante los pulsadores
+int iCorrecto=0;    //Cantidad de veces que lo ingresado fue correcto / coincide con la secuencia
+int iChequeo=0;     //Posición para chequear si lo ingresado fue correcto / coincide con la secuencia
+int iMuestra=0;     //Posición para mostrar la secuencia en los leds 
+
+//Variables que sirven para eliminar el rebote de los pulsadores y detectar solo el flanco ascendente
+int mantieneRojo=0;
+int mantieneVerde=0;
+int mantieneAzul=0;
+
+//Variable que indica si se tienen que mostrar los printf o no en el Hercules
+int print=0;
+//Variable que, según su valor, indica si los leds tienen que estar apagados o mantener su estado
+int decideLedOff=0;
+
+//Variables que se usan para pasar por las posiciones de los vectores cuando estos se tienen que reiniciar o se quiere mostrar la secuencia en el Hercules
+int j;
+int w;
+int p;
+
+//Variable que indica si se tienen que prender los leds con respecto a las posiciones de la secuencia
+int doSec=0;
 
 int main(void) {
+    //Configuro en modo Pull-Up las 4 entradas con pulsadores 
+    E1r.mode(PullUp);
+    E2r.mode(PullUp);
+    E3r.mode(PullUp);
     reseteo.mode(PullUp);
+    //Apago los leds
     ledR=1;
     ledG=1;
     ledB=1;
-    leer.attach(&leerFuncion,0.4);
-    Interludio.attach(&cutled,0.2);
-    pantalla.attach(&pantalleate,1);
-    while (true) {
-        if(reseteo==0)
-        {
-            for(j=0;j<MaxElem;j++){
-                vecR[j]=0;
-                vecG[j]=0;
-                vecB[j]=0;
-                vecE1[j]=0;
-                vecE2[j]=0;
-                vecE3[j]=0;
-            }
-            CT=0;
-            HG=0;
-            EP=0;
-            l=0;
-            contar=0;
-            print=0;
-            LED=0;
-            a=0;
-            b=0;
-            c=0;
-            i=0;
-            i2=0;
-            i3=0;
-            i4=0;
-            estadosSecuencia=NO_MUESTRA;
-            estadosConfirm=NO_INGRESA;
-            
-            
-        }
+    //Asigno las funciones a los tickers
+    pantalla.attach(&visualizaTexto,1);             //Se ejecuta visualizaTexto cada 1 segundo
+    mostrarLeds.attach(&visualizaSecuencia,0.6);    //Se ejecuta visualizaSecuencia cada 0,6 segundos 
+    Interludio.attach(&tiempoLedsOn,0.2);           //Se ejecuta tiempoLedsOn cada 0,2 segundos
+    while(true) {
+        //Llamo a la función reset todo el tiempo
+        reset();
+        //Si la cantidad total de elementos de una secuencia todavía no pasó el máximo permitido, se ejecutan las funciones y muestran los printf
+        //Sino, se para todo y se indica al jugador que debe apretar el botón reset para empezar de nuevo
         if(CT<=MaxElem)
         {
+            detectorPulsado();
+            confirmacion();
+            generadorSecuencia();
             if(print==1)
             {
                 printf("Cant. Total Secuencia:%d \n",CT);
-                printf("Cant. Total de veces Ingresado:%d \n",i2);
-                printf("Cant. Total de veces que fue correcto lo ingresado:%d \n",i3);
+                printf("Cant. Total de veces Ingresado:%d \n",iIngresado);
+                printf("Cant. Total de veces que fue correcto lo ingresado:%d \n",iCorrecto);
                 printf("Secuencia a lograr: \n");
+                printf("R G B \n");
                 for(p=0;p<=(CT-1);p++)
                 {
                     if(CT==MaxElem+1)
@@ -120,43 +131,174 @@
                 printf("\n \n");
                 print=0;   
             }
-            if(l==1)
-            {
-            detectorPulsado();
-            generadorSecuencia();
-            confirmacion();
-            l=0;
-            }
         }
         else
         {
-            if(l==1)
+            if(print==1)
             {
                 printf("Por favor, empiece otra vez \n");
-                l=0;  
+                print=0;  
             }
         }
     }
 }
 
-void pantalleate()
+void reset()
 {
+    //Resetea todas las variables, los vectores y vuelve a los estados iniciales de las máquinas de estados
+    if(reseteo==0)
+    {
+        for(j=0;j<MaxElem;j++)
+        {
+            vecR[j]=0;
+            vecG[j]=0;
+            vecB[j]=0;
+            vecE1[j]=0;
+            vecE2[j]=0;
+            vecE3[j]=0;
+        }
+        CT=0;
+        HG=0;
+        EP=0;
+        doSec=0;
+        decideLedOff=0;
+        print=0;
+        LED=0;
+        mantieneRojo=0;
+        mantieneVerde=0;
+        mantieneAzul=0;
+        iSecuencia=0;
+        iIngresado=0;
+        iCorrecto=0;
+        iChequeo=0;
+        estadosSecuencia=NO_MUESTRA;
+        estadosConfirm=NO_INGRESA;        
+    }
+}
+
+void visualizaTexto()
+{
+    //Cada 1 segundo, esto se pone en 1 para mostrar los printf. Al instante se vuelve 0 y deja de mostrar los printf, esperando que se vuelva a llamar a la función
     print=1;   
 }
 
-void cutled()
+void visualizaSecuencia()
+{
+    //Cada 0,6 segundos, la variable se hace 1. Cuando llegue la parte de mostrar la secuencia, la variable se va a hacer 0 y va a esperar a que se llame a la función otra vez
+    doSec=1;     
+}
+
+void tiempoLedsOn()
 {   
-    if(contar%2==0)
+    //Cada 0,2 segundos, se le suma 1 a la variable y, cada vez que es par, apaga los leds sin importar sus estados anteriores
+    if(decideLedOff%2==0)
     {
         ledR=1;
         ledG=1;
         ledB=1;
     }
-    contar++;
+    decideLedOff++;
 }
-void leerFuncion()
+
+void detectorPulsado()
 {
-    l=1;     
+    switch(estadosPulsadores)
+    {
+        default:
+        case LEE:
+        //Espera a que se toque el pulsador de rojo
+        //Si es así guarda eso en los vectores, pone la variable E1 en 1, suma 1 a iIngresado y prende el led rojo, que va a ser apagado por la función tiempoLedsOn
+        //También se pone en 1 la variable mantieneRojo que es un indicador del estado anterior
+        //Cambia el estado a APAGA
+        if(E1r==0 && mantieneRojo==0)
+        {
+            E1=1;
+            mantieneRojo=1;
+            vecE1[iIngresado]=1;
+            vecE2[iIngresado]=0;
+            vecE3[iIngresado]=0;
+            ledR=0;
+            iIngresado++;
+            estadosPulsadores=APAGA;
+        }
+        //Espera a que se toque el pulsador de Verde
+        //Si es así guarda eso en los vectores, pone la variable E2 en 1, suma 1 a iIngresado y prende el led verde, que va a ser apagado por la función tiempoLedsOn
+        //También se pone en 1 la variable mantieneVerde que es un indicador del estado anterior
+        //Cambia el estado a APAGA
+        if(E2r==0 && mantieneVerde==0)
+        {
+            E2=1;
+            mantieneVerde=1;
+            vecE1[iIngresado]=0;
+            vecE2[iIngresado]=1;
+            vecE3[iIngresado]=0;
+            ledG=0;
+            iIngresado++;
+            estadosPulsadores=APAGA;
+        }
+        //Espera a que se toque el pulsador de Azul
+        //Si es así guarda eso en los vectores, pone la variable E3 en 1, suma 1 a iIngresado y prende el led verde, que va a ser apagado por la función tiempoLedsOn
+        //También se pone en 1 la variable mantieneAzul que es un indicador del estado anterior
+        //Cambia el estado a APAGA
+        if(E3r==0 && mantieneAzul==0)
+        {
+            E3=1;
+            mantieneAzul=1;
+            vecE1[iIngresado]=0;
+            vecE2[iIngresado]=0;
+            vecE3[iIngresado]=1;
+            ledB=0;
+            iIngresado++;
+            estadosPulsadores=APAGA;
+        }
+        break;
+        
+        case APAGA:
+        //Si el pulsador de uno de los colores se mantiene pulsado y ya pasó por el estado anterior, E1 se vuelve 0 (E1 va a estar en 1 por muy poco tiempo)
+        //Se pasa al estado AGUARDA
+        if(E1r==0 && mantieneRojo==1)
+        {
+            E1=0;
+            estadosPulsadores=AGUARDA;
+        }
+        //Si el pulsador de uno de los colores se mantiene pulsado y ya pasó por el estado anterior, E2 se vuelve 0 (E2 va a estar en 1 por muy poco tiempo)
+        //Se pasa al estado AGUARDA
+        if(E2r==0 && mantieneVerde==1)
+        {
+            E2=0;
+            estadosPulsadores=AGUARDA;
+        }
+        //Si el pulsador de uno de los colores se mantiene pulsado y ya pasó por el estado anterior, E3 se vuelve 0 (E3 va a estar en 1 por muy poco tiempo)
+        //Se pasa al estado AGUARDA
+        if(E3r==0 && mantieneAzul==1)
+        {
+            E3=0;
+            estadosPulsadores=AGUARDA;
+        }
+        break;
+        
+        case AGUARDA:
+        //Si ya se tocó el pulsador una vez y ahora se suelta, el E se mantiene como estaba, se indica con la otra variable que terminó el proceso y vuelve al estado LEE
+        if(E1r==1 && mantieneRojo==1)
+        {
+            E1=0;
+            mantieneRojo=0;
+            estadosPulsadores=LEE;
+        }
+        if(E2r==1 && mantieneVerde==1)
+        {
+            E2=0;
+            mantieneVerde=0;
+            estadosPulsadores=LEE;
+        }
+        if(E3r==1 && mantieneAzul==1)
+        {
+            E3=0;
+            mantieneAzul=0;
+            estadosPulsadores=LEE;
+        }
+        break;   
+    }
 }
 
 void confirmacion(){
@@ -164,52 +306,67 @@
     {
         default:
         case NO_INGRESA:
+        //Se reinicia el contenido de los vectores de entrada, así cuando completás una secuencia tenés que escribir toda la que sigue desde cero
+        //El contenido de los vectores de secuencia, que guardan los colores y su posición en la secuencia, no se reinicia porque es parte del juego que la secuencia
+        //siguiente siempre es igual que la anterior solo que con un color random más agregado al final
         for(w=0;w<MaxElem;w++)
         {
             vecE1[w]=0;
             vecE2[w]=0;
             vecE3[w]=0;
         }
-        i2=0;
-        i4=0;
-        i3=0;
+        //Se reinician los indicadores cuando completás una secuencia
+        iIngresado=0;
+        iChequeo=0;
+        iCorrecto=0;
+        //Se habilita la generación de una nueva secuencia
         HG=1;
+        //Se pasa directamente al siguiente estado
         estadosConfirm=ESPERA;
         break;
         
         case INGRESA:
-        i4++;
+        //Se le suma 1 a iChequeo para que la proxima vez que se ingrese algo lo verifique con la siguiente posición de la secuencia
+        iChequeo++;
+        //Pasa directamente a ESPERA
         estadosConfirm=ESPERA;
         break;
         
         case ESPERA:
+        //Automáticamente se deshabilita la generación
         HG=0;
+        //Si no se ingresa nada mediante los pulsadores, queda en ESPERA
         if(E1==0 && E2==0 && E3==0)
         {
             estadosConfirm=ESPERA;
         }
+        //Si se ingresa algo, se fija si esa posición concuerda con la misma posición de la secuencia
+        //De ser correcto, va a INGRESA
+        //De ser incorrecto, el jugador perdió cambia el estado a FIN
         else
         {
-            if(i3!=CT)
+            if(iCorrecto!=CT)
             {
-                if((vecR[i4]==vecE1[i4]) && (vecG[i4]==vecE2[i4]) && (vecB[i4]==vecE3[i4]))
+                if((vecR[iChequeo]==vecE1[iChequeo]) && (vecG[iChequeo]==vecE2[iChequeo]) && (vecB[iChequeo]==vecE3[iChequeo]))
                 {
-                    i3++; 
+                    iCorrecto++; 
                     estadosConfirm=INGRESA;
                 }
                 else
                 {
-                    estadosConfirm=FAIL;   
+                    estadosConfirm=FIN;   
                 }
             }
         }
-        if(i3==CT)
+        //Si se ingresó toda la secuencia correctamente, vuelve al estado inicial NO_INGRESA donde se va a habilitar una nueva generación y reiniciar variables
+        if(iCorrecto==CT)
         {
             estadosConfirm=NO_INGRESA;
         }
         break;
         
-        case FAIL:
+        case FIN:
+        //En caso de perder, se hace que CT sea mayor a la máxima cantidad de elementos posibles, condición en la que se termina el juego y espera el reseteo
         CT=MaxElem+1;
         break;
     }
@@ -219,136 +376,93 @@
     {
         default:
         case NO_MUESTRA:
-            LED=0;
-            if(HG==0)
-            {
-                estadosSecuencia=NO_MUESTRA;
-            }
-            else
-            {
-                estadosSecuencia=NO_MUESTRA2;
-            }
-            break;
+        //La variable LED empieza en 0, que no hace nada
+        LED=0;
+        //Si se habilitó la generación de una secuencia, pasa al siguiente estado, NO_MUESTRA2
+        //Sino, se queda en este estado
+        if(HG==0)
+        {
+            estadosSecuencia=NO_MUESTRA;
+        }
+        else
+        {
+            estadosSecuencia=NO_MUESTRA2;
+        }
+        break;
         
         case NO_MUESTRA2:
+        //De ser habilitada la generación de una nueva secuencia, se le suma 1 a la cantidad total de elementos/posiciones que va a tener la secuencia
+        //CT empieza en 0, cuando se habilita la generación, CT pasa a ser 1, entonces dentro de la secuencia solo va a haber un color random
+        //Cuando se toque bien ese color, vuelve a generar una secuencia, solo que ahora va a hacer CT++ otra vez y la secuencia va a constar de 2 colores random
         CT++;
+        //Pasa a MUESTRA directamente
         estadosSecuencia=MUESTRA;
         break;
         
         case MUESTRA:
-            if(EP!=CT)
+        //Si el estado parcial en que se encuentra no es último de la secuencia, hace que LED sea un número random entre 1 y 3
+        //Basado en eso decide que color corresponde a ese estado parcial/posición de la secuencia
+        //Eso lo guarda en los vectores de secuencia, que tienen qué color corresponde a qué posición
+        //EP empieza en 0 y solo se reinicia en el reset, de manera que siempre se va a añadir un color random al final de la secuencia anterior para hacer la nueva
+        if(EP!=CT)
+        {
+            LED=rand()%3+1;
+            if(LED==1)
+            {
+                vecR[iSecuencia]=1;
+                vecG[iSecuencia]=0;
+                vecB[iSecuencia]=0;
+            }
+            else if(LED==2)
+            {
+                vecR[iSecuencia]=0;
+                vecG[iSecuencia]=1;
+                vecB[iSecuencia]=0;
+            }
+            else if(LED==3)
             {
-                LED=rand()%3+1;
-                if(LED==1)
-                {
-                    vecR[i]=1;
-                    vecG[i]=0;
-                    vecB[i]=0;
-                }
-                else if(LED==2)
-                {
-                    vecR[i]=0;
-                    vecG[i]=1;
-                    vecB[i]=0;
-                }
-                else if(LED==3)
-                {
-                    vecR[i]=0;
-                    vecG[i]=0;
-                    vecB[i]=1;
-                }
-                if(i<CT)
-                {
-                    i++;
-                }
-                EP++;
+                vecR[iSecuencia]=0;
+                vecG[iSecuencia]=0;
+                vecB[iSecuencia]=1;
+            }
+            if(iSecuencia<CT)
+            {
+                iSecuencia++;
             }
-            else
-            {
-                estadosSecuencia=MUESTRA2;
-            }
-            break;
+            EP++;
+        }
+        //Al hacerlo una vez, EP pasa a ser igual que CT, por lo que cambia al estado MUESTRA2 y espera a que el proceso se vuelva a hacer para que CT valga más que EP
+        //(En el estado anterior con CT++)
+        else
+        {
+            estadosSecuencia=MUESTRA2;
+        }
+        break;
             
-            case MUESTRA2:
+        case MUESTRA2:
+        //Cada 1 segundo que doSec se hace 1 y pasa a ser 0 instantáneamente, los leds se prenden con respecto a la secuencia generada (guardada en los vectores)
+        //Se apagan con la funcion tiempoLedsOn
+        //El estado de los leds es igual a lo que contiene la posición del vector -negado- porque los leds se prenden con 0, no con 1
+        //Los vectores guardan con 1 los leds que se tienen que prender
+        //Cuando se muestra toda la secuencia en los leds, se reinicia iMuestra y vuelve al estado inicial NO_MUESTRA
+        if(doSec==1)
+        {
+            //La secuencia se guarda desde la posición 0 de los vectores. La primera secuencia se hace con CT=1. Por eso el CT-1
             if(iMuestra<=CT-1)
             {
                 ledR=!vecR[iMuestra];
                 ledG=!vecG[iMuestra];
                 ledB=!vecB[iMuestra];
                 iMuestra++;
-                estadosSecuencia=MUESTRA2;
             }
             else
             {
                 iMuestra=0;
                 estadosSecuencia=NO_MUESTRA;
             }
-            break;
+            doSec=0;
+        }
+        break;
     }
 }
 
-void detectorPulsado()
-{
-    if(E1r==1 && a==0)
-    {
-        E1=1;
-        a=1;
-        vecE1[i2]=1;
-        vecE2[i2]=0;
-        vecE3[i2]=0;
-        ledR=0;
-        i2++;
-    }
-    else if(E1r==1 && a==1)
-    {
-        ledR=1;
-        E1=0;
-    }
-    else if(E1r==0 && a==1)
-    {
-        E1=0;
-        a=0;
-    }
-    
-    if(E2r==1 && b==0)
-    {
-        E2=1;
-        b=1;
-        vecE1[i2]=0;
-        vecE2[i2]=1;
-        vecE3[i2]=0;
-        ledG=0;
-        i2++;
-    }
-    else if(E2r==1 && b==1)
-    {
-        ledG=1;
-        E2=0;
-    }
-    else if(E2r==0 && b==1)
-    {
-        E2=0;
-        b=0;
-    }
-
-    if(E3r==1 && c==0)
-    {
-        E3=1;
-        c=1;
-        vecE1[i2]=0;
-        vecE2[i2]=0;
-        vecE3[i2]=1;
-        ledB=0;
-        i2++;
-    }
-    else if(E3r==1 && c==1)
-    {
-        ledB=1;
-        E3=0;
-    }
-    else if(E3r==0 && c==1)
-    {
-        E3=0;
-        c=0;
-    }
-}
\ No newline at end of file