STEMGAME

 

PCB CON BOTONERA


PCB INTEGRADO



CODIGO INTEGRADO 4 MENUS (#ENTEROS, #DECILAMES, BIOLOGIA Y QUIMICA)

#include <Wire.h>
#include <Adafruit_SH110X.h>
#include <Adafruit_GFX.h>

#define BUTTON_A 25
#define BUTTON_B 27
#define BUTTON_C 14
#define BUTTON_D 13
#define BUZZER 16
#define LED_RED 17
#define LED_GREEN 18
#define LED_BLUE 19

Adafruit_SH1106G display = Adafruit_SH1106G(128, 64, &Wire, -1);

// ========== VARIABLES GLOBALES ==========
int juegoActual = 0; // 0: Menú, 1: Enteros, 2: Decimales, 3: Química, 4: Biología
bool juegoSeleccionado = false;

// ========== VARIABLES PARA JUEGOS MATEMÁTICOS ==========
// Variables para el juego de números enteros
float scoreEnteros = 0;
int currentQuestionEnteros = 0;
int totalQuestionsEnteros = 10;
unsigned long startTimeEnteros = 0;
unsigned long totalTimeEnteros = 0;
bool juegoEnProgresoEnteros = false;

struct Question {
  int num1;
  int num2;
  char operation;
  int correctAnswer;
  int options[4];
};

Question questionsEnteros[10];

// Variables para el juego de números decimales
float puntuacionDecimales = 0;
int preguntaActualDecimales = 0;
unsigned long tiempoInicioDecimales = 0;
unsigned long tiempoFinalDecimales = 0;
bool midiendoTiempoDecimales = false;

float num1Decimales, num2Decimales, resultadoDecimales;
char opcionesDecimales[4][10];
int respuestaCorrectaDecimales;

// ========== VARIABLES PARA QUIZZES ==========
int pregunta_actual = 0;
int puntuacion = 0;
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 200;
int preguntas_seleccionadas[10];

// Datos de Química
const char* preguntas_quimica[] = {
  "Simbolo quimico del agua?",       // A (H2O)
  "Elemento mas abundante?",         // B (Silicio)
  "Que es un atomo?",                // A (Unidad basica)
  "Formula del Dioxido de carbono?", // C (CO2)
  "Que gas liberan las plantas durante la fotosintesis",      // B (Organizacion)
  "pH de solucion neutra?",          // A (7)
  "Que es un ion?",                  // B (Atomo cargado)
  "Gas noble mas ligero?",           // A (Helio)
  "Reaccion quimica?",               // C (Cambio composicion)
  "Elemento mas ligero?",            // A (Hidrogeno)
  "Que es compuesto quimico?",       // B (Sustancia pura)
  "Simbolo del oro?",                // B (Au)
  "Que es catalizador?",             // A (Acelera reacciones)
  "Formula del amoniaco?",           // B (NH3)
  "Que es isotopo?",                 // C (Atomo con neutrones extra)
  "Elemento mas reactivo?",          // A (Fluor)
  "Donde se da enlace covalente?",   // B (Entre no metales)
  "Formula acido sulfurico?",        // C (H2SO4)
  "Que es un acido?",                // A (Donador protones)
  "Simbolo del hierro?",             // A (Fe)
  "Metal alcalino?",                 // A (Grupo 1)
  "Formula del metano?",             // A (CH4)
  "Que es polimero?",                // B (Macromolecula)
  "Elemento mas pesado?",            // A (Uranio)
  "Enlace ionico?",                  // C (Entre iones)
  "Formula del ozono?",              // B (O3)
  "Que es gas noble?",               // A (Grupo 18)
  "Simbolo del sodio?",              // A (Na)
  "Que es anion?",                   // B (Ion negativo)
  "Formula agua oxigenada?"          // A (H2O2)
};

const char* respuestas_quimica[][3] = {
  {"A. H2O", "B. CO2", "C. NaCl"},
  {"A. Oxigeno", "B. Silicio", "C. Hierro"},
  {"A. Unidad basica", "B. Molecula", "C. Compuesto"},
  {"A. H2O", "B. O2", "C. CO2"},
  {"A. Dioxido de carbono (CO₂)", "B. Oxigeno (O₂)", "C. Nitrogeno (N₂)"},
  {"A. 7", "B. 5", "C. 10"},
  {"A. Atom neutro", "B. Atom cargado", "C. Molecula"},
  {"A. Helio", "B. Neon", "C. Argon"},
  {"A. Cambio fisico", "B. Cambio estado", "C. Cambio composicion"},
  {"A. Hidrogeno", "B. Helio", "C. Litio"},
  {"A. Mezcla", "B. Sust pura", "C. Elemento"},
  {"A. Ag", "B. Au", "C. Fe"},
  {"A. Acelera", "B. Inhibe", "C. No afecta"},
  {"A. NH4", "B. NH3", "C. NO2"},
  {"A. Enlace", "B. Molecula", "C. Atom +neutr"},
  {"A. Fluor", "B. Sodio", "C. Oro"},
  {"A. Entre metales", "B. Entre no metales", "C. Entre iones"},
  {"A. H2SO3", "B. H2CO3", "C. H2SO4"},
  {"A. Donador H+", "B. Aceptor H+", "C. Neutro"},
  {"A. Fe", "B. Au", "C. Ag"},
  {"A. Grupo 1", "B. Grupo 2", "C. Grupo 17"},
  {"A. CH4", "B. C2H6", "C. C3H8"},
  {"A. Ion", "B. Macromolec", "C. Enlace"},
  {"A. Uranio", "B. Oro", "C. Plomo"},
  {"A. No metales", "B. Metales", "C. Iones"},
  {"A. O2", "B. O3", "C. CO2"},
  {"A. Grupo 18", "B. Grupo 1", "C. Grupo 2"},
  {"A. Na", "B. K", "C. Li"},
  {"A. Ion +", "B. Ion -", "C. Atom neutro"},
  {"A. H2O2", "B. H2O", "C. HO"}
};

const int respuestas_correctas_quimica[] = {0,1,0,2,1,0,1,0,2,0,1,1,0,1,2,0,1,2,0,0,0,0,1,0,2,1,0,0,1,0};

// Datos de Biología
const char* preguntas_biologia[] = {
  "Organelo celular de la respiracion?",       // B (Mitocondria)
  "Molecula portadora de energia?",            // A (ATP)
  "Que es el ADN?",                            // C (Material genetico)
  "Funcion de los ribosomas?",                 // A (Sintesis proteica)
  "Tejido que transporta nutrientes?",        // B (Floema)
  "Organismo unicelular procariota?",          // C (Bacteria)
  "Proceso de division celular?",              // A (Mitosis)
  "Hormona del crecimiento vegetal?",          // B (Auxina)
  "Capa protectora de la piel?",               // A (Epidermis)
  "Organismo productor en ecologia?",          // A (Planta)
  "Parte del cerebro para memoria?",           // B (Hipocampo)
  "Enzima que digiere carbohidratos?",         // A (Amilasa)
  "Celula reproductora femenina?",             // B (Ovulo)
  "Proceso de fotosintesis ocurre en?",        // C (Cloroplasto)
  "Sistema que incluye el corazon?",           // A (Circulatorio)
  "Grupo sanguineo donante universal?",        // B (O negativo)
  "Organo filtrador de sangre?",               // A (Rinon)
  "Vitaminas liposolubles?",                   // C (A, D, E, K)
  "Que son los gametos?",                      // A
  "Hueso mas largo del cuerpo?",               // B (Femur)
  "Glandula productora de insulina?",          // A (Pancreas)
  "Proceso de paso de agua por membrana?",     // B (Osmosis)
  "Estructura que produce polen?",             // C (Antera)
  "Numero de cromosomas humanos?",             // A (46)
  "Organismo descomponedor?",                  // B (Hongo)
  "Hormona del estres?",                       // A (Cortisol)
  "Biomolecula formada por aminoacidos?",  // C
  "Organo del olfato?",                        // A (Nariz)
  "Ciencia que estudia los tejidos?",          // B (Histologia)
  "Proceso de formacion de gametos?"           // A (Gametogenesis)
};

const char* respuestas_biologia[][3] = {
  {"A. Nucleo", "B. Mitocondria", "C. Lisosoma"},
  {"A. ATP", "B. ADN", "C. ARN"},
  {"A. Proteina", "B. Carbohidrato", "C. Material genetico"},
  {"A. Sintesis proteica", "B. Produccion ATP", "C. Digestión"},
  {"A. Xilema", "B. Floema", "C. Epidermis"},
  {"A. Levadura", "B. Alga", "C. Bacteria"},
  {"A. Mitosis", "B. Meiosis", "C. Fotosintesis"},
  {"A. Giberelina", "B. Auxina", "C. Citocinina"},
  {"A. Epidermis", "B. Dermis", "C. Hipodermis"},
  {"A. Planta", "B. Hongo", "C. Animal"},
  {"A. Cerebelo", "B. Hipocampo", "C. Talamo"},
  {"A. Amilasa", "B. Lipasa", "C. Proteasa"},
  {"A. Esperma", "B. Ovulo", "C. Zigoto"},
  {"A. Mitocondria", "B. Nucleo", "C. Cloroplasto"},
  {"A. Circulatorio", "B. Nervioso", "C. Digestivo"},
  {"A. AB positivo", "B. O negativo", "C. B positivo"},
  {"A. Rinon", "B. Higado", "C. Pulmon"},
  {"A. B, C", "B. Complejo B", "C. A, D, E, K"},
  {"A. Celula reproductiva", "B. Semillas secas", "C. Parasitos"},
  {"A. Tibia", "B. Femur", "C. Humero"},
  {"A. Pancreas", "B. Higado", "C. Tiroides"},
  {"A. Difusion", "B. Osmosis", "C. Transp activo"},
  {"A. Estigma", "B. Estilo", "C. Antera"},
  {"A. 46", "B. 23", "C. 48"},
  {"A. Bacteria", "B. Hongo", "C. Planta"},
  {"A. Cortisol", "B. Adrenalina", "C. Insulina"},
  {"A. Carbohidratos", "B. Lipidos", "C. Proteinas"},
  {"A. Nariz", "B. Lengua", "C. Oido"},
  {"A. Citologia", "B. Histologia", "C. Embriologia"},
  {"A. Gametogenesis", "B. Fecundacion", "C. Ovulacion"}
};

const int respuestas_correctas_biologia[] = {1,0,2,0,1,2,0,1,0,0,1,0,1,2,0,1,0,2,0,1,0,1,2,0,1,0,2,0,1,0};

// ========== CONFIGURACIÓN INICIAL ==========
void setup() {
  pinMode(BUTTON_A, INPUT);
  pinMode(BUTTON_B, INPUT);
  pinMode(BUTTON_C, INPUT);
  pinMode(BUTTON_D, INPUT);
  pinMode(BUZZER, OUTPUT);
  pinMode(LED_RED, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_BLUE, OUTPUT);

  randomSeed(analogRead(12));

  display.begin(0x3C, true);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SH110X_WHITE);
  display.setCursor(0, 0);
  display.display();

  mostrarMenuPrincipal();
}

// ========== BUCLE PRINCIPAL ==========
void loop() {
  if (!juegoSeleccionado) {
    int opcion = esperarSeleccionMenu();
    juegoSeleccionado = true;
    juegoActual = opcion + 1; // +1 porque el menú empieza en 0
   
    switch(juegoActual) {
      case 1: iniciarJuegoEnteros(); break;
      case 2: iniciarJuegoDecimales(); break;
      case 3: iniciarQuizQuimica(); break;
      case 4: iniciarQuizBiologia(); break;
    }
  } else {
    switch(juegoActual) {
      case 1: loopEnteros(); break;
      case 2: loopDecimales(); break;
      case 3: loopQuizQuimica(); break;
      case 4: loopQuizBiologia(); break;
    }
  }
}

// ========== FUNCIONES DEL MENÚ ==========
void mostrarMenuPrincipal() {
  display.clearDisplay();
  centerText("SELECCIONE JUEGO", 5);
  display.setCursor(0, 20);
  display.println("A: Numeros Enteros");
  display.println("B: Numeros Decimales");
  display.println("C: Quiz de Quimica");
  display.println("D: Quiz de Biologia");
  display.display();
}

int esperarSeleccionMenu() {
  while(true) {
    if (debounce(BUTTON_A)) return 0;
    if (debounce(BUTTON_B)) return 1;
    if (debounce(BUTTON_C)) return 2;
    if (debounce(BUTTON_D)) return 3;
    delay(10);
  }
}

void reiniciarMenu() {
  juegoSeleccionado = false;
  juegoActual = 0;
  mostrarMenuPrincipal();
}

// ========== FUNCIONES COMUNES ==========
bool debounce(int button) {
  static unsigned long lastDebounceTime = 0;
  if (digitalRead(button) == HIGH && millis() - lastDebounceTime > 200) {
    lastDebounceTime = millis();
    return true;
  }
  return false;
}

void centerText(const char *text, int y) {
  int16_t x1, y1;
  uint16_t w, h;
  display.getTextBounds(text, 0, 0, &x1, &y1, &w, &h);
  int x = (128 - w) / 2;
  display.setCursor(x, y);
  display.print(text);
}

void playFunTone() {
  tone(BUZZER, 1000, 200);
  delay(200);
  tone(BUZZER, 1500, 200);
  delay(200);
  tone(BUZZER, 2000, 200);
  delay(200);
  noTone(BUZZER);
}

void playWrongTone() {
  tone(BUZZER, 500, 500);
  delay(500);
  noTone(BUZZER);
}

// ========== JUEGO DE NÚMEROS ENTEROS ==========
void generarPreguntasEnteros() {
  for (int i = 0; i < totalQuestionsEnteros; i++) {
    questionsEnteros[i].num1 = random(-10, 10);
    questionsEnteros[i].operation = random(0, 4);

    if (questionsEnteros[i].operation == 3) { // Para división
      do {
        questionsEnteros[i].num2 = random(-10, 10);
      } while (questionsEnteros[i].num2 == 0 || questionsEnteros[i].num1 % questionsEnteros[i].num2 != 0);
    } else {
      questionsEnteros[i].num2 = random(-10, 10);
    }

    // Calcular respuesta correcta
    switch (questionsEnteros[i].operation) {
      case 0: questionsEnteros[i].correctAnswer = questionsEnteros[i].num1 + questionsEnteros[i].num2; break;
      case 1: questionsEnteros[i].correctAnswer = questionsEnteros[i].num1 - questionsEnteros[i].num2; break;
      case 2: questionsEnteros[i].correctAnswer = questionsEnteros[i].num1 * questionsEnteros[i].num2; break;
      case 3: questionsEnteros[i].correctAnswer = questionsEnteros[i].num1 / questionsEnteros[i].num2; break;
    }

    // Generar opciones de respuesta
    bool answerSet[4] = {false, false, false, false};
    for (int j = 0; j < 4; j++) {
      if (j == 0) {
        questionsEnteros[i].options[j] = questionsEnteros[i].correctAnswer;
        answerSet[j] = true;
      } else {
        int wrongAnswer;
        if (j == 1) {
          // Respuesta incorrecta relacionada
          switch (questionsEnteros[i].operation) {
            case 0: wrongAnswer = questionsEnteros[i].num1 - questionsEnteros[i].num2; break;
            case 1: wrongAnswer = questionsEnteros[i].num1 + questionsEnteros[i].num2; break;
            case 2: wrongAnswer = questionsEnteros[i].num1 / questionsEnteros[i].num2; break;
            case 3: wrongAnswer = questionsEnteros[i].num1 * questionsEnteros[i].num2; break;
          }
        } else {
          // Respuesta incorrecta aleatoria
          do {
            wrongAnswer = random(-20, 20);
          } while (wrongAnswer == questionsEnteros[i].correctAnswer);
        }

        // Asignar a la primera posición disponible
        for (int k = 0; k < 4; k++) {
          if (!answerSet[k]) {
            questionsEnteros[i].options[k] = wrongAnswer;
            answerSet[k] = true;
            break;
          }
        }
      }
    }

    // Mezclar opciones
    for (int j = 3; j > 0; j--) {
      int randomIndex = random(0, j + 1);
      int temp = questionsEnteros[i].options[j];
      questionsEnteros[i].options[j] = questionsEnteros[i].options[randomIndex];
      questionsEnteros[i].options[randomIndex] = temp;
    }
  }
}

void iniciarJuegoEnteros() {
  scoreEnteros = 0;
  currentQuestionEnteros = 0;
  startTimeEnteros = millis();
  juegoEnProgresoEnteros = true;

  display.clearDisplay();
  centerText("Números Enteros", 20);
  display.display();
  delay(2000);

  generarPreguntasEnteros();
  displayQuestionEnteros();
}

void loopEnteros() {
  if (juegoEnProgresoEnteros) {
    if (currentQuestionEnteros < totalQuestionsEnteros) {
      if (debounce(BUTTON_A)) {
        checkAnswerEnteros(questionsEnteros[currentQuestionEnteros].options[0]);
      } else if (debounce(BUTTON_B)) {
        checkAnswerEnteros(questionsEnteros[currentQuestionEnteros].options[1]);
      } else if (debounce(BUTTON_C)) {
        checkAnswerEnteros(questionsEnteros[currentQuestionEnteros].options[2]);
      } else if (debounce(BUTTON_D)) {
        checkAnswerEnteros(questionsEnteros[currentQuestionEnteros].options[3]);
      }
    } else {
      juegoEnProgresoEnteros = false;
      totalTimeEnteros = millis() - startTimeEnteros;
      displayFinalScoreEnteros();
    }
  } else {
    if (debounce(BUTTON_A)) {
      delay(500);
      playFunTone();
      reiniciarMenu();
    }
  }
}

void displayQuestionEnteros() {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.print("Pregunta ");
  display.print(currentQuestionEnteros + 1);
  display.print(" de ");
  display.println(totalQuestionsEnteros);

  display.setCursor(0, 15);
  display.print(questionsEnteros[currentQuestionEnteros].num1);
  display.print(" ");
  display.print(getOperationSymbol(questionsEnteros[currentQuestionEnteros].operation));
  display.print(" ");
  display.print(questionsEnteros[currentQuestionEnteros].num2);
  display.print(" = ?");

  char optionsLabel[] = {'A', 'B', 'C', 'D'};
  for (int i = 0; i < 4; i++) {
    display.setCursor(0, 25 + i * 10);
    display.print(optionsLabel[i]);
    display.print(") ");
    display.print(questionsEnteros[currentQuestionEnteros].options[i]);
  }

  display.display();
}

char getOperationSymbol(int operation) {
  switch (operation) {
    case 0: return '+';
    case 1: return '-';
    case 2: return '*';
    case 3: return '/';
    default: return '?';
  }
}

void checkAnswerEnteros(int selectedAnswer) {
  if (selectedAnswer == questionsEnteros[currentQuestionEnteros].correctAnswer) {
    digitalWrite(LED_GREEN, HIGH);
    tone(BUZZER, 1000, 200);
    delay(200);
    tone(BUZZER, 1500, 200);
    delay(200);
    tone(BUZZER, 2000, 200);
    delay(200);
    digitalWrite(LED_GREEN, LOW);
    scoreEnteros += 0.5;
    display.clearDisplay();
    centerText("CORRECTO", 20);
    display.display();
    delay(1000);
  } else {
    digitalWrite(LED_RED, HIGH);
    playWrongTone();
    digitalWrite(LED_RED, LOW);
    display.clearDisplay();
    centerText("Respuesta incorrecta", 20);
    display.display();
    delay(1000);
  }

  currentQuestionEnteros++;
  if (currentQuestionEnteros >= totalQuestionsEnteros) {
    juegoEnProgresoEnteros = false;
    totalTimeEnteros = millis() - startTimeEnteros;
    displayFinalScoreEnteros();
  } else {
    displayQuestionEnteros();
  }
}

void displayFinalScoreEnteros() {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("Puntuacion final:");
  display.setCursor(0, 10);
  display.print(scoreEnteros);
  display.print(" de ");
  display.print(totalQuestionsEnteros * 0.5);

  display.setCursor(0, 20);
  display.print("Tiempo: ");
  display.print(totalTimeEnteros / 1000);
  display.print(" segundos");

  display.setCursor(0, 40);
  display.println("Oprima boton A");
  display.println("para nueva partida");
  display.display();
}

// ========== JUEGO DE NÚMEROS DECIMALES ==========
void generarPreguntaDecimales() {
  num1Decimales = random(1, 100) / 10.0;
  num2Decimales = random(1, 100) / 10.0;
  resultadoDecimales = num1Decimales + num2Decimales;

  respuestaCorrectaDecimales = random(0, 4);

  for (int i = 0; i < 4; i++) {
    if (i == respuestaCorrectaDecimales) {
      dtostrf(resultadoDecimales, 4, 2, opcionesDecimales[i]);
    } else {
      float incorrecta = resultadoDecimales + (random(-20, 20) / 10.0);
      dtostrf(incorrecta, 4, 2, opcionesDecimales[i]);
    }
  }
}

void iniciarJuegoDecimales() {
  puntuacionDecimales = 0;
  preguntaActualDecimales = 0;
  tiempoInicioDecimales = millis();
  midiendoTiempoDecimales = true;

  display.clearDisplay();
  centerText("Números Decimales", 20);
  display.display();
  delay(2000);

  generarPreguntaDecimales();
  mostrarPreguntaConOpcionesDecimales();
}

void loopDecimales() {
  if (preguntaActualDecimales < 10) {
    if (!midiendoTiempoDecimales) {
      tiempoInicioDecimales = millis();
      midiendoTiempoDecimales = true;
    }

    mostrarPreguntaConOpcionesDecimales();

    int respuestaElegida = -1;
    if (debounce(BUTTON_A)) respuestaElegida = 0;
    else if (debounce(BUTTON_B)) respuestaElegida = 1;
    else if (debounce(BUTTON_C)) respuestaElegida = 2;
    else if (debounce(BUTTON_D)) respuestaElegida = 3;

    if (respuestaElegida != -1) {
      if (respuestaElegida == respuestaCorrectaDecimales) {
        indicarResultadoDecimales(true);
        puntuacionDecimales += 0.5;
      } else {
        indicarResultadoDecimales(false);
      }

      preguntaActualDecimales++;
      if (preguntaActualDecimales < 10) {
        generarPreguntaDecimales();
      } else {
        tiempoFinalDecimales = millis();
        midiendoTiempoDecimales = false;
      }
      delay(1000);
    }
  } else {
    mostrarPuntuacionYTiempoDecimales();

    if (debounce(BUTTON_A)) {
      delay(500);
      playFunTone();
      reiniciarMenu();
    }
  }
}

void mostrarPreguntaConOpcionesDecimales() {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.print("Pregunta ");
  display.println(preguntaActualDecimales + 1);
  display.print(num1Decimales, 1);
  display.print(" + ");
  display.print(num2Decimales, 1);
  display.print(" = ?");

  display.setCursor(0, 20);
  for (int i = 0; i < 4; i++) {
    display.print((char)('A' + i));
    display.print(". ");
    display.println(opcionesDecimales[i]);
  }
  display.display();
}

void indicarResultadoDecimales(bool esCorrecta) {
  display.clearDisplay();
  display.setCursor(0, 0);
  if (esCorrecta) {
    centerText("CORRECTO", 20);
    digitalWrite(LED_GREEN, HIGH);
    tone(BUZZER, 1000, 200);
  } else {
    centerText("INCORRECTO", 20);
    digitalWrite(LED_RED, HIGH);
    tone(BUZZER, 500, 200);
  }
  display.display();
  delay(1000);
  digitalWrite(LED_GREEN, LOW);
  digitalWrite(LED_RED, LOW);
}

void mostrarPuntuacionYTiempoDecimales() {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.print("Puntuacion final: ");
  display.print(puntuacionDecimales);
  display.print("/5.0");

  unsigned long tiempoTotal = tiempoFinalDecimales - tiempoInicioDecimales;
  unsigned long segundos = tiempoTotal / 1000;
  unsigned long minutos = segundos / 60;
  segundos = segundos % 60;

  display.setCursor(0, 20);
  display.print("Tiempo total: ");
  display.print(minutos);
  display.print(":");
  if (segundos < 10) {
    display.print("0");
  }
  display.print(segundos);

  display.setCursor(0, 40);
  display.println("Oprima el boton A");
  display.println("para nueva ronda.");
  display.display();
}

// ========== QUIZ DE QUÍMICA ==========
void seleccionarPreguntasAleatorias(const char* preguntas[], int total_preguntas) {
  randomSeed(analogRead(12));
  for(int i = 0; i < 10; i++) {
    bool repetida;
    int nueva_pregunta;
    do {
      repetida = false;
      nueva_pregunta = random(total_preguntas);
      for(int j = 0; j < i; j++) {
        if(preguntas_seleccionadas[j] == nueva_pregunta) {
          repetida = true;
          break;
        }
      }
    } while(repetida);
    preguntas_seleccionadas[i] = nueva_pregunta;
  }
}

void iniciarQuizQuimica() {
  pregunta_actual = 0;
  puntuacion = 0;
 
  seleccionarPreguntasAleatorias(preguntas_quimica, 30);
 
  display.clearDisplay();
  centerText("QUIZ DE QUIMICA", 10);
  centerText("10 PREGUNTAS", 25);
  centerText("Presiona A", 45);
  display.display();
  esperarCualquierBoton();
}

void loopQuizQuimica() {
  while(pregunta_actual < 10) {
    int pregunta_idx = preguntas_seleccionadas[pregunta_actual];
   
    mostrarNumeroPregunta();
    delay(800);
   
    mostrarPreguntaCompleta(preguntas_quimica[pregunta_idx], respuestas_quimica, pregunta_idx);
   
    int respuesta = esperarRespuesta();
   
    if(respuesta == 3) continue; // Botón D - repetir
   
    verificarRespuesta(respuestas_correctas_quimica[pregunta_idx], respuesta);
    pregunta_actual++;
  }
 
  mostrarResultadoFinal();
  if (debounce(BUTTON_A) || debounce(BUTTON_B) || debounce(BUTTON_C) || debounce(BUTTON_D)) {
    reiniciarMenu();
  }
}

// ========== QUIZ DE BIOLOGÍA ==========
void iniciarQuizBiologia() {
  pregunta_actual = 0;
  puntuacion = 0;
 
  seleccionarPreguntasAleatorias(preguntas_biologia, 30);
 
  display.clearDisplay();
  centerText("QUIZ DE BIOLOGIA", 10);
  centerText("10 PREGUNTAS", 25);
  centerText("Presiona A", 45);
  display.display();
  esperarCualquierBoton();
}

void loopQuizBiologia() {
  while(pregunta_actual < 10) {
    int pregunta_idx = preguntas_seleccionadas[pregunta_actual];
   
    mostrarNumeroPregunta();
    delay(800);
   
    mostrarPreguntaCompleta(preguntas_biologia[pregunta_idx], respuestas_biologia, pregunta_idx);
   
    int respuesta = esperarRespuesta();
   
    if(respuesta == 3) continue; // Botón D - repetir
   
    verificarRespuesta(respuestas_correctas_biologia[pregunta_idx], respuesta);
    pregunta_actual++;
  }
 
  mostrarResultadoFinal();
  if (debounce(BUTTON_A) || debounce(BUTTON_B) || debounce(BUTTON_C) || debounce(BUTTON_D)) {
    reiniciarMenu();
  }
}

// ========== FUNCIONES AUXILIARES PARA QUIZZES ==========
void mostrarNumeroPregunta() {
  display.clearDisplay();
  centerText("Pregunta", 15);
  char texto[20];
  sprintf(texto, "%d de 10", pregunta_actual + 1);
  centerText(texto, 35);
  display.display();
}

void mostrarPreguntaCompleta(const char* pregunta, const char* opciones[][3], int idx) {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println(pregunta);
  display.println("");
 
  for(int i = 0; i < 3; i++) {
    display.println(opciones[idx][i]);
    display.println("");
  }
 
  display.display();
}

int esperarRespuesta() {
  while(true) {
    if (debounce(BUTTON_A)) return 0;
    if (debounce(BUTTON_B)) return 1;
    if (debounce(BUTTON_C)) return 2;
    if (debounce(BUTTON_D)) return 3;
    delay(10);
  }
}

void verificarRespuesta(int respuesta_correcta, int respuesta) {
  bool correcta = (respuesta == respuesta_correcta);
 
  display.clearDisplay();
  centerText(correcta ? "CORRECTO!" : "INCORRECTO", 20);
  display.display();
 
  if(correcta) {
    puntuacion++;
    digitalWrite(LED_GREEN, HIGH);
    tone(BUZZER, 1000, 200);
  } else {
    digitalWrite(LED_RED, HIGH);
    tone(BUZZER, 300, 500);
  }
 
  delay(1000);
  digitalWrite(LED_GREEN, LOW);
  digitalWrite(LED_RED, LOW);
}

void mostrarResultadoFinal() {
  display.clearDisplay();
  centerText("RESULTADO FINAL", 10);
  display.setCursor(0, 25);
  display.print("Puntuacion: ");
  display.print(puntuacion);
  display.print("/10");
  centerText("Presione cualquier", 40);
  centerText("boton para continuar", 50);
  display.display();
}

void esperarCualquierBoton() {
  while(!(debounce(BUTTON_A) || debounce(BUTTON_B) || debounce(BUTTON_C) || debounce(BUTTON_D))) {
    delay(10);
  }
  delay(debounceDelay);
}

Comentarios

Entradas populares de este blog

CLASIFICADOR DE COLORES CON SENSOR TCS3472 (I2C) CON ARDUINO NANO

PROTOTIPO - CONTROL DE ACCESO CON RFID + TECLADO CON ALMACENAMIENTO EN MICRO SD

CONTROL DE ACCESO CON RFID YMODULO RTC DS3231