lunes, 2 de septiembre de 2013

Arduino Tutorial 14: Juego Simon Says


En esta entrada, os vamos a enseñar cómo hacer el juego de “Simon Says”, ese famoso juego de memorizar una secuencia aleatoria de colores. De nuevo tengo que dar las gracias a Eloy, que ha hecho la parte de programar, y juntos hemos podido hacer este juego.
El esquema que debemos hacer es muy fácil, solo necesitamos tres leds, tres pulsadores y un zumbador (optativo, ya que solo es para dar sonido al juego):

Esquema de montaje del juego Simon



El código de este juego es un poco complicado, sobre todo para los que no saben demasiada programación:

   
       #define LEVELS 3
    #define COLORS 3
    #define TIME_INTERVAL 1500
    #define TONO_1 1700
    #define TONO_2 1432
    #define TONO_3 956
    #define TONO_ERROR 600
    //--------------------------------------------------
    //  Variables SIMON
    //--------------------------------------------------
    double status_simon = 0; 
    int nivel = 0;
    double secuencia = 0;
    int colores_pulsados = 0;
   
    //--------------------------------------------------
    // Puertos
    //--------------------------------------------------
    // LEDS
    double led_Rojo = 13;    //Declarar Pin LED Rojo
    double led_Verde = 11;    //Declarar Pin LED Verde
    double led_Amarillo = 9;     //Declarar Pin LED Amarillo
   
    // PULSADORES
    double pulsador_Rojo = 12;
    double pulsador_Verde = 10;
    double pulsador_Amarillo = 8;
   
    //ZUMBADOR
    double zumbador = 7;
   
    //------------------------------------
    // Funcion principal
    //------------------------------------
    void setup()    // Se ejecuta cada vez que el Arduino se inicia
    {
      Serial.begin(9600);
      randomSeed(analogRead(0));
     
      pinMode(pulsador_Rojo,INPUT); // Pulsador 1 como entrada
      pinMode(led_Rojo,OUTPUT);  //El LED 1 Rojo como salida
     
      pinMode(pulsador_Verde,INPUT); // Pulsador 2 como entrada
      pinMode(led_Verde,OUTPUT); //El LED Verde como salida
     
      pinMode(pulsador_Amarillo,INPUT); // Pulsador 3 como entrada
      pinMode(led_Amarillo,OUTPUT);  //El LED Rojo como salida
     
      pinMode(zumbador,OUTPUT); // El zumbador como salida
    }
   
    //------------------------------------
    //Funcion ciclicla
    //------------------------------------
    void loop()       // Esta funcion se mantiene ejecutando
    {                       //  cuando se da energia al Arduino
      if(digitalRead(pulsador_Rojo) == HIGH && digitalRead(pulsador_Verde) == HIGH && digitalRead(pulsador_Amarillo) == HIGH)
      {
        nivel = 0;
        status_simon = 0;
        delay(TIME_INTERVAL*2);
        return;
      }
      // Reproducir secuencia
      if(status_simon == 0){
        Serial.println("\n\n--------------------------\nMODO IMPRESION SEC.");
        if( nivel == 0 )
        {
          nivel = 1;
          randomSeed(analogRead(0));
          secuencia = random(1,COLORS+1);
        }
        else
        {
          nivel++;
          randomSeed(analogRead(0));
          double double_rand = random(1,COLORS+1);
          double double_exp =  (double)pow(10,nivel-1 );
          //double value = double_rand * double_exp;
          //secuencia = secuencia + value;
          secuencia = (secuencia * 10) + double_rand;
        }
        Serial.print("\nlvl: ");
        Serial.print(nivel);
        Serial.print("\n");
        Serial.print("Secu.: ");
        Serial.print(secuencia);
        Serial.print("\n");
        imprimir_secuencia();
       
        status_simon = 1;
        colores_pulsados = 0;
      }
      // Secuencia del usuario - Registro de los pulsadores
      else if(status_simon == 1){
        if(digitalRead(pulsador_Rojo) == HIGH){
          Serial.println("Rojo pulsado");
          pulsar_elemento('1');
          colores_pulsados++;
          verificar_secuencia('1');
        }
        else if(digitalRead(pulsador_Verde) == HIGH){
          Serial.println("Verde pulsado");
          pulsar_elemento('2');
          colores_pulsados++;
          verificar_secuencia('2');
        }
        else if(digitalRead(pulsador_Amarillo) == HIGH){
          Serial.println("Amarillo pulsado");
          pulsar_elemento('3');
          colores_pulsados++;
          verificar_secuencia('3');
        }
      }
    }
   
    //------------------------------------
    //Funcion Verificar secüencia
    //------------------------------------
    void verificar_secuencia(char color)
    {
      String string = String(round(secuencia) );
      Serial.print("\nColor usuario:");
      Serial.print(color);
      Serial.print(" Seq. Valor:");
      Serial.print(string[colores_pulsados-1]);
      if(string[colores_pulsados-1] == color){
        if(nivel == colores_pulsados){
          Serial.print("\nFin del lvl: ");
          Serial.print(nivel);
          status_simon = 0;
        }
        else{
          // CONTINUA MODO USUARIO
          Serial.print("\nContinuar modo usuario");
        } 
      }
      else{
        // ERROR DE USUARIO
        Serial.print("\nERROR DE USUARIO");
        status_simon = 4;
        error_usuario();
      }
    }
   
    //------------------------------------
    //Funcion Imprimir secuencia
    //------------------------------------
    void imprimir_secuencia()
    {
      String string = String(round(secuencia) );
      Serial.print("\nIMPRIMIR SERIE: ");
      Serial.print(string);
      for(int i = 0 ; i < nivel  ;i++)
      {
        delay(TIME_INTERVAL*0.5);
        pulsar_elemento(string[i]);
      }
    }
   
    //------------------------------------
    // PULSAR ELEMENTO
    // Luce el led del indicador pasádo por parámetro
    //------------------------------------
    void pulsar_elemento(char num_color)
    {
      switch(num_color){
        case '1':
          Serial.println("\nPulsador Rojo ON");
          digitalWrite(led_Rojo,HIGH);
          sonarTono(TONO_1,TIME_INTERVAL*0.5);
          digitalWrite(led_Rojo,LOW);
          Serial.println("Pulsador Rojo OFF");
        break;
        case '2':
          Serial.println("\nPulsador Verde ON");
          digitalWrite(led_Verde,HIGH);
          sonarTono(TONO_2,TIME_INTERVAL*0.5);
          digitalWrite(led_Verde,LOW);
          Serial.println("Pulsador Verde OFF");
        break;
        case '3':
          Serial.println("\nPulsador Amarillo ON");
          digitalWrite(led_Amarillo,HIGH);
          sonarTono(TONO_3,TIME_INTERVAL*0.5);
          digitalWrite(led_Amarillo,LOW);
          Serial.println("Pulsador Amarillo OFF");    
        break;
      }
    }
   
    //------------------------------------
    // ERROR USUARIO
    // Realiza una secuencia de luz y sonido diez veces seguidas para indicar que
    // el usuario ha errado al introducir la
    // secuencia
    //------------------------------------------
    void error_usuario()
    {
      for(int i=0; i<3; i++)
      {
        delay(TIME_INTERVAL*0.3);
        digitalWrite(led_Rojo, HIGH);   // turn the LED on (HIGH is the voltage level)
        digitalWrite(led_Verde, HIGH);   // turn the LED on (HIGH is the voltage level)
        digitalWrite(led_Amarillo, HIGH);   // turn the LED on (HIGH is the voltage level)
        digitalWrite(zumbador,HIGH);
       
        sonarTono(TONO_ERROR,TIME_INTERVAL);
        digitalWrite(zumbador,LOW);
        digitalWrite(led_Rojo, LOW);    // turn the LED off by making the voltage LOW
        digitalWrite(led_Verde, LOW);    // turn the LED off by making the voltage LOW
        digitalWrite(led_Amarillo, LOW);    // turn the LED off by making the voltage LOW 
      }
    }
   
    //------------------------------------
    // SONAR TONO
    //------------------------------------
    void sonarTono(int tono, int duracion)
    {
      tone(zumbador,tono,duracion);
      delay(duracion);
    }
   
    //FIN DEL PROGRAMA



Aquí os dejo un vídeo de cómo funciona este Simon, ya que hemos puesto alguna función específica, tales como que para reiniciar el Simon tienes que pulsar a la vez los tres pulsadores, o que cuando te equivocas en la secuencia de colores, parpadean los tres leds a la vez tres veces: