jueves, 1 de marzo de 2018

Juego Simón con placa Picuino

  1. /***************************************************************************
  2.    JUEGO SIMON
  3.  ***************************************************************************/
  4. #include <Wire.h>
  5. #include <PC42.h>
  6.  
  7. /***************************************************************************
  8.    DEFINICIÓN DE DATOS Y CONSTANTES
  9.  ***************************************************************************/
  10.  
  11. // Tones
  12. #define TONE_R    Re_4    // 311.1 Hz  Rojo
  13. #define TONE_Y    Si3     // 246.9 Hz  Amarillo
  14. #define TONE_G    Fa_4    // 370.0 Hz  Verde
  15. #define TONE_B    Fa_3    // 185.0 Hz  Azul
  16. #define TONE_ERR  Si1     // 59 Hz Simón original
  17.  
  18. #define TIME_BETWEEN_SEQUENCES 1060
  19. #define TIME_ERROR_TONE        2540
  20.  
  21. #define SIMON_LEN_MAX 20
  22. typedef struct {
  23.    char data[SIMON_LEN_MAX];
  24.    char len;
  25.    char pos;
  26.    char state;
  27.    char sound;
  28. } simon_t;
  29.  
  30. enum {
  31.   INIT, WAIT_RUN, INIT_RUN, ADD_SEQUENCE,
  32.   PLAY_SEQUENCE, TEST_SEQUENCE,
  33.   RIGHT_SEQUENCE, ERROR_IN_SEQUENCE,
  34.   WIN_GAME, WAIT_INIT,
  35. };
  36.  
  37. simon_t simon;
  38.  
  39.  
  40. /***************************************************************************
  41.    SETUP Y BUCLE PRINCIPAL
  42.  ***************************************************************************/
  43. void setup() {
  44.   pc.begin();
  45.   simon.state = INIT;
  46. }
  47.  
  48. void loop() {
  49.  
  50.   switch(simon.state) {
  51.  
  52.   case INIT:   // Init System
  53.     pc.ledWrite(5, HIGH);
  54.     simon.state = WAIT_RUN;
  55.     break;
  56.  
  57.   case WAIT_RUN:  // Wait Run
  58.     if (pc.keyCount(KEY_ENTER))
  59.       simon.state = INIT_RUN;
  60.     break;
  61.  
  62.   case INIT_RUN:  // Init Run
  63.     simon_init();
  64.     pc.ledWrite(5, LOW);
  65.     randomSeed(millis());
  66.     simon.state = ADD_SEQUENCE;
  67.     break;
  68.    
  69.   case ADD_SEQUENCE:  // Add Sequence
  70.     simon.data[simon.len] = random(1, 4+1);
  71.     simon.len++;
  72.     simon.state = PLAY_SEQUENCE;
  73.     break;
  74.    
  75.   case PLAY_SEQUENCE:  // Play Sequence
  76.     pc.dispNum(simon.len);
  77.     delay(TIME_BETWEEN_SEQUENCES);
  78.     simon_play();
  79.     simon.state = TEST_SEQUENCE;
  80.     break;
  81.    
  82.   case TEST_SEQUENCE:  // Test Sequence
  83.     if (simon_test() == 1)
  84.       simon.state = RIGHT_SEQUENCE;
  85.     else
  86.       simon.state = ERROR_IN_SEQUENCE;
  87.     break;
  88.    
  89.   case RIGHT_SEQUENCE:  // Right Sequence
  90.     if (simon.len >= SIMON_LEN_MAX)
  91.       simon.state = WIN_GAME;
  92.     else
  93.       simon.state = ADD_SEQUENCE;
  94.     break;
  95.    
  96.   case ERROR_IN_SEQUENCE:  // Error in Sequence
  97.       simon_error();
  98.       simon.len = 0;
  99.       simon.state = INIT;
  100.     break;
  101.  
  102.   case WIN_GAME:  // Win Game
  103.     pc.dispWrite(DD_G, DD_A, DD_n, DD_A);
  104.     pc.ledBlink(5, 100, 400);
  105.     simon.state = WAIT_INIT;
  106.     break;
  107.    
  108.   case WAIT_INIT:  // Wait Init
  109.     if (pc.keyCount(KEY_ENTER)) {
  110.       pc.dispBegin();
  111.       pc.ledBegin();
  112.       simon.state = INIT;
  113.     }
  114.     break;
  115.  
  116.   default:
  117.     simon.state = 0;
  118.   }
  119.    
  120. };
  121.  
  122.  
  123. /***************************************************************************
  124.    FUNCIONES
  125.  ***************************************************************************/
  126.  
  127. //
  128. // Inicializar datos de Simón
  129. //
  130. void simon_init(void) {
  131.    uint8_t i;
  132.    for(i=sizeof(simon.data); --i;) {
  133.       simon.data[i] = 0;
  134.    }
  135.    simon.len = 0;
  136.    simon.pos = 0;
  137.    simon.sound = 1;  
  138. }
  139.  
  140.  
  141. //
  142. // Visualizar la secuencia de colores y tonos
  143. //
  144. void simon_play(void) {
  145.   int i;
  146.   for(i=0; i<simon.len; i++) {
  147.      simon_color(simon.data[i]);
  148.   }
  149. }
  150.  
  151.  
  152. //
  153. //  Comprueba si el jugador repite toda la secuencia
  154. //
  155. char simon_test(void) {
  156.   int i;
  157.   char color, key;
  158.  
  159.   i = 0;
  160.   while(1) {
  161.     if (i >= simon.len)
  162.       return 1;  
  163.     color = simon.data[i];
  164.    
  165.     key = key_num();
  166.     if (key == 0)
  167.       continue;
  168.    
  169.     if (key == color) {
  170.       simon_color(color);
  171.       i = i + 1;
  172.     }
  173.     else {
  174.       return 0;
  175.     }
  176.   }
  177. }
  178.  
  179.  
  180. //
  181. // Devuelve el número de tecla pulsado
  182. //
  183. char key_num(void) {
  184.   char keys = pc.keyPressed(0);
  185.   if (keys & (1<<0)) return 1;
  186.   if (keys & (1<<1)) return 2;
  187.   if (keys & (1<<2)) return 3;
  188.   if (keys & (1<<3)) return 4;
  189.   if (keys & (1<<4)) return 5;
  190.   if (keys & (1<<5)) return 6;
  191. }
  192.  
  193.  
  194. //
  195. // Enciende un led y suena un tono
  196. // durante un tiempo determinado
  197. //
  198. void simon_color(char color) {
  199.   char numtone;
  200.   int i;
  201.  
  202.   if (color < 1 || color > 4) return;
  203.   if (simon.sound) {
  204.     switch(color) {
  205.     case 1: numtone = TONE_R;  break;
  206.     case 2: numtone = TONE_Y;  break;
  207.     case 3: numtone = TONE_G;  break;
  208.     case 4: numtone = TONE_B;  break;
  209.     }
  210.   }
  211.   pc.ledWrite(color, HIGH);
  212.   pc.buzzTone(numtone);
  213.   delay(simon_time_tone(simon.len));
  214.   pc.buzzTone(0);
  215.   pc.ledWrite(color, LOW);
  216.   delay(simon_time_silence(simon.len));
  217. }
  218.  
  219. //
  220. // Enciende la señal de error
  221. //
  222. void simon_error(void) {
  223.   if (simon.sound)
  224.     pc.buzzTone(TONE_ERR);
  225.   pc.ledWrite(6, HIGH);
  226.   pc.ledWrite(8, HIGH);
  227.   delay(TIME_ERROR_TONE);
  228.   pc.buzzTone(0);
  229.   pc.ledWrite(6, LOW);
  230.   pc.ledWrite(8, LOW);
  231.   delay(100);
  232. }
  233.  
  234. //
  235. // Devuelve el tiempo que dura un tono dependiendo de
  236. // la longitud de la secuencia de colores
  237. //
  238. int simon_time_tone(char len) {
  239.    if (len <= 1) return 660;
  240.    if (len <= 5) return 475;
  241.    if (len <= 9) return 380;
  242.    if (len <=13) return 317;
  243.    return 272;
  244. }
  245.  
  246. //
  247. // Devuelve el tiempo que dura una pausa entre tonos dependiendo de
  248. // la longitud de la secuencia de colores
  249. //
  250. int simon_time_silence(char len) {
  251.    if (len <= 1) return 132;
  252.    if (len <= 5) return 93;
  253.    if (len <= 9) return 75;
  254.    if (len <=13) return 63;
  255.    return 54;
  256. }

No hay comentarios:

Publicar un comentario