Gonzalo Martinez
/
TPSimon
SIMON
main.cpp
- Committer:
- gonzaloMS
- Date:
- 2019-06-22
- Revision:
- 1:6cb3e90ec4f3
- Parent:
- 0:31131c8fdcfb
File content as of revision 1:6cb3e90ec4f3:
#include "mbed.h" //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 //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); //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 mostrarLeds; Ticker Interludio; //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(); //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 //Variables que indican los estados de las máquinas de estados int estadosPulsadores; int estadosSecuencia; int estadosConfirm; int vecR[MaxElem]; int vecG[MaxElem]; int vecB[MaxElem]; int vecE1[MaxElem]; int vecE2[MaxElem]; int vecE3[MaxElem]; //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; //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",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) { break; } printf("%d %d %d \n",vecR[p],vecG[p],vecB[p]); } printf("\n \n"); print=0; } } else { if(print==1) { printf("Por favor, empiece otra vez \n"); print=0; } } } } 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 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() { //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; } decideLedOff++; } void detectorPulsado() { 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(){ switch(estadosConfirm) { 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; } //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: //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(iCorrecto!=CT) { if((vecR[iChequeo]==vecE1[iChequeo]) && (vecG[iChequeo]==vecE2[iChequeo]) && (vecB[iChequeo]==vecE3[iChequeo])) { iCorrecto++; estadosConfirm=INGRESA; } else { estadosConfirm=FIN; } } } //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 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; } } void generadorSecuencia(){ switch(estadosSecuencia) { default: case NO_MUESTRA: //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: //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) { vecR[iSecuencia]=0; vecG[iSecuencia]=0; vecB[iSecuencia]=1; } if(iSecuencia<CT) { iSecuencia++; } 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: //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++; } else { iMuestra=0; estadosSecuencia=NO_MUESTRA; } doSec=0; } break; } }