Arduino Mastermind Logik Schematics Code WS2812

Mastermind - YT Video:


Hra je určená pre dvoch hráčov, ktorí hru hrajú


Hráč 1 (háda)


  • Úlohou hráča je uhádnuť čísla druhého hráča a aj ich poradie
  • Hráč na vstup do systému využíva 5x pushbutton, pričom 4 z tlačidiel fungujú ako inkrementátor čísla na tej danej pozícii v rozsahu 0-9.
  • Piatym tlačidlom sa údaje odošlú na kontrolu. Priráta sa pokus, vyhodnotí sa kombinácia.
  • Dáta sa zapisujú a sú vizualizované aj na LCD displej.
  • V prípade, že hráč uhádne číslo a aj jeho pozíciu, rozsvieti sa zelená dióda na tej danej pozícii (vypíše sa na displej = na danú pozíciu).
  • V opačnom prípade pri neuhádnutí čísla, respektíve pri uhádnutí čísla ale neuhádnutí pozície sa zosvieti červená dióda na znak nepravdy (vypíše sa na displej - na danú pozíciu).
  • V prípade, že hráč uhádne číslo a nie jeho pozíciu, rozsvieti sa modrá dióda na tej danej pozícii (vypíše sa na displej C na danú pozíciu).
  • Pre hráča sa hra končí pri presiahnutí 10 pokusov, alebo pri uhádnutí kombinácie.

  • Hráč 2 (určuje kombináciu čísel a ich poradie)


  • V úlohe mikrokontróler Arduino Uno, alebo iný, prípadne AtMega čip.
  • Vygeneruje číslo 0000-9999, ktoré bude hráč hádať
  • Odoslané dáta od používateľa overí jednoduchou podmienkovou logikou
  • V prípade uhádnutia farby i pozície rozsvieti príslušnú diódu na zeleno.
  • V prípade neuhádnutia farby, alebo pozície rozsvieti príslušnú diódu na červeno.
  • Arduino overuje aj počet krokov (ťahov), ktoré hráč použil, skúma, či je hra ukončená.
  • Hra sa končí, ak hráč 1 uhádne všetky čísla aj ich pozície (všetky 4 diódy budú zelené), vstup sa zablokuje, alebo pri neúspešnej hre s dosiahnutím 10 pokusov.
  • O stave hry je používateľ vždy informovaný na displeji.

  • Hardvér pre projekt

  • Arduino Uno R3
  • 4x RGB LED WS2812 (jeden modul)
  • 5x tlačidlo - spínacie
  • LCD 20x4 alebo 16x2
  • I2C prevodník pre LCD
  • Zapojenie



    LCD displej s I2C prevodníkom Arduino Uno
    Vcc 5V
    GND GND
    SDA A4 (SDA)
    SCK/SCL A5 (SCK/SCL)
    Tlačidlo Arduino Uno
    IN 1 D6
    IN 2 D5
    IN 3 D4
    IN 4 D3
    Enter D2
    RGB led diódy Arduino Uno
    DIN D13
    GND GND
    5V -
    5V pin sa pripája na externý zdroj z dôvodu veľkého nárazového odberu prúdu zvlášť pri rozsvietení všetkých diód, rádovo 200mA.

    Mastermind - hracie pole - DEBUG OFF

    Mastermind - DEBUG OFF - Logik

    Mastermind - hracie pole - DEBUG ON

    Mastermind - DEBUG ON - Logik

    Autodesk Eagle export (Wiring)

    Mastermind - schéma zapojenia - Arduino

    Mastermind - Arduino - Source

    Wokwi Mastermind simulation: HERE
    /*|----------------------------------------------------------------------------|*/
    /*|SKETCH PRE MASTERMIND IMPLEMENTACIU                                         |*/
    /*|VYHOTOVIL: martinius96@gmail.com                                            |*/
    /*|Doska: Arduino Uno / ATmega328P                                             |*/
    /*|MAXIMALNY POCET POKUSOV: 10                                                 |*/
    /*|POCET VSTUPOV: 5X PUSHBUTTON - SPINACIE TLACIDLA                            |*/
    /*|VYGENEROVANE 4-CISLIE: KAZDE CISLO JE ROZNE V ROZSAHU 0-9 BEZ OPAKOVANIA!   |*/
    /*|PRE ZOBRAZENIE VYGENEROVANEHO CISLA POUZITE DEBUG (ODKOMENTOVAT)            |*/
    /*|----------------------------------------------------------------------------|*/
    /*|VYSVETLIVKY PRE ZNAČKY NA DISPLEJI:                                         |*/
    /*| C --> uhadnute cislo na inej pozicii                                       |*/
    /*| = --> uhadnute cislo aj s poziciou (SPRAVNE CISLO!)                        |*/
    /*| - --> neuhadnute cislo, ani pozicia                                        |*/
    /*|----------------------------------------------------------------------------|*/
    /*|Podporte projekt pre viac variant: https://paypal.me/chlebovec              |*/
    /*|----------------------------------------------------------------------------|*/
    
    #define DEBUG //odkomentuj pre DEBUG INFO (ZOBRAZENIE HLADANEHO CISLA)
    //#define NULUJ //vynuluj cisla po zadani ENTEROM
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    LiquidCrystal_I2C lcd(0x27, 20, 4);
    
    const int buttonPin1 = 6;
    const int buttonPin2 = 5;
    const int buttonPin3 = 4;
    const int buttonPin4 = 3;
    const int buttonPin5 = 2;
    
    int cislo1 = 0;
    int cislo2 = 0;
    int cislo3 = 0;
    int cislo4 = 0;
    
    
    int cielovecislo1 = 0;
    int cielovecislo2 = 0;
    int cielovecislo3 = 0;
    int cielovecislo4 = 0;
    
    int buttonState1 = HIGH;
    int buttonState2 = HIGH;
    int buttonState3 = HIGH;
    int buttonState4 = HIGH;
    int buttonState5 = HIGH;
    
    int lastButtonState1 = HIGH;
    int lastButtonState2 = HIGH;
    int lastButtonState3 = HIGH;
    int lastButtonState4 = HIGH;
    int lastButtonState5 = HIGH;
    
    unsigned long lastDebounceTime1 = 0;
    unsigned long lastDebounceTime2 = 0;
    unsigned long lastDebounceTime3 = 0;
    unsigned long lastDebounceTime4 = 0;
    unsigned long lastDebounceTime5 = 0;
    unsigned long debounceInterval = 50;
    int pokus = 0;
    
    void setup() {
      lcd.begin(); //incializacia displeja na I2C zbernici
      lcd.backlight(); //zapnutie podsvietenia
      pinMode(buttonPin1, INPUT_PULLUP);
      pinMode(buttonPin2, INPUT_PULLUP);
      pinMode(buttonPin3, INPUT_PULLUP);
      pinMode(buttonPin4, INPUT_PULLUP);
      pinMode(buttonPin5, INPUT_PULLUP);
      randomSeed(analogRead(0));
      lcd.setCursor(0, 0); //nastav kurzor pre zapis na 1. riadok, 1. stlpec
      lcd.print("ZADANE CISLO:   0000");
      generuj_cisla();
    #ifdef DEBUG
      lcd.setCursor(0, 2);
      lcd.print("DEBUG ON:");
      lcd.setCursor(0, 3);
      lcd.print("HLADANE CISLO:  ");
      lcd.print(cielovecislo1);
      lcd.print(cielovecislo2);
      lcd.print(cielovecislo3);
      lcd.print(cielovecislo4);
    #endif
    }
    
    void loop() {
      if (pokus >= 10) {
        lcd.setCursor(0, 2);
        lcd.print("PREHRALI STE!");
        lcd.setCursor(0, 3);
        lcd.print("KONIEC HRY          ");
        while (1);
      } else {
        int reading1 = digitalRead(buttonPin1);
        int reading2 = digitalRead(buttonPin2);
        int reading3 = digitalRead(buttonPin3);
        int reading4 = digitalRead(buttonPin4);
        int reading5 = digitalRead(buttonPin5);
    
        if (reading1 != lastButtonState1) {
          lastDebounceTime1 = millis();
        }
    
        if (reading2 != lastButtonState2) {
          lastDebounceTime2 = millis();
        }
    
        if (reading3 != lastButtonState3) {
          lastDebounceTime3 = millis();
        }
    
        if (reading4 != lastButtonState4) {
          lastDebounceTime4 = millis();
        }
    
        if (reading5 != lastButtonState5) {
          lastDebounceTime5 = millis();
        }
    
        if ((millis() - lastDebounceTime1) > debounceInterval) {
          if (reading1 != buttonState1) {
            buttonState1 = reading1;
            if (buttonState1 == HIGH) {
              cislo1++;
              if (cislo1 > 9) {
                cislo1 = 0;
              }
            }
          }
          updateLCD();
        }
    
        if ((millis() - lastDebounceTime2) > debounceInterval) {
          if (reading2 != buttonState2) {
            buttonState2 = reading2;
            if (buttonState2 == HIGH) {
              cislo2++;
              if (cislo2 > 9) {
                cislo2 = 0;
              }
            }
          }
          updateLCD();
        }
    
        if ((millis() - lastDebounceTime3) > debounceInterval) {
          if (reading3 != buttonState3) {
            buttonState3 = reading3;
            if (buttonState3 == HIGH) {
              cislo3++;
              if (cislo3 > 9) {
                cislo3 = 0;
              }
            }
          }
          updateLCD();
        }
    
        if ((millis() - lastDebounceTime4) > debounceInterval) {
          if (reading4 != buttonState4) {
            buttonState4 = reading4;
            if (buttonState4 == HIGH) {
              cislo4++;
              if (cislo4 > 9) {
                cislo4 = 0;
              }
            }
          }
          updateLCD();
        }
    
        if ((millis() - lastDebounceTime5) > debounceInterval) {
          if (reading5 != buttonState5) {
            lcd.setCursor(16, 1);
            lcd.print(cislo1);
            lcd.print(cislo2);
            lcd.print(cislo3);
            lcd.print(cislo4);
            buttonState5 = reading5;
            if (buttonState5 == HIGH) {
              pokus++;
              updateLCD();
              over_cisla();
              #ifdef NULUJ
              cislo1 = 0;
              cislo2 = 0;
              cislo3 = 0;
              cislo4 = 0;
              #endif
            }
          }
        }
        lastButtonState1 = reading1;
        lastButtonState2 = reading2;
        lastButtonState3 = reading3;
        lastButtonState4 = reading4;
        lastButtonState5 = reading5;
      }
    }
    
    void updateLCD() {
      lcd.setCursor(16, 0);
      lcd.print(cislo1);
      lcd.print(cislo2);
      lcd.print(cislo3);
      lcd.print(cislo4);
      lcd.setCursor(0, 1);
      lcd.print("POKUS: ");
      lcd.print(pokus);
    }
    
    void generuj_cisla() {
      cielovecislo1 = random(0, 9);
      cielovecislo2 = random(0, 9);
      while (cielovecislo2 == cielovecislo1) {
        cielovecislo2 = random(0, 9);
      }
      cielovecislo3 = random(0, 9);
      while ((cielovecislo3 == cielovecislo1) || (cielovecislo3 == cielovecislo2)) {
        cielovecislo3 = random(0, 9);
      }
      cielovecislo4 = random(0, 9);
      while ((cielovecislo4 == cielovecislo1) || (cielovecislo4 == cielovecislo2) || (cielovecislo4 == cielovecislo3)) {
        cielovecislo4 = random(0, 9);
      }
    }
    
    void over_cisla() {
      if (cislo1 == cielovecislo1) {
        lcd.setCursor(10, 1);
        lcd.print("="); //UHADNUTE CISLO VRATANE POZICIE
      } else if ((cislo1 == cielovecislo2) || (cislo1 == cielovecislo3) || (cislo1 == cielovecislo4)) {
        lcd.setCursor(10, 1);
        lcd.print("C"); //UHADNUTE CISLO BEZ POZICIE
      } else {
        lcd.setCursor(10, 1);
        lcd.print("-"); //NEUHADNUTE CISLO, ANI POZICIA
      }
    
      if (cislo2 == cielovecislo2) {
        lcd.setCursor(11, 1);
        lcd.print("="); //UHADNUTE CISLO VRATANE POZICIE
      } else if ((cislo2 == cielovecislo1) || (cislo2 == cielovecislo3) || (cislo2 == cielovecislo4)) {
        lcd.setCursor(11, 1);
        lcd.print("C"); //UHADNUTE CISLO BEZ POZICIE
      } else {
        lcd.setCursor(11, 1);
        lcd.print("-"); //NEUHADNUTE CISLO, ANI POZICIA
      }
    
      if (cislo3 == cielovecislo3) {
        lcd.setCursor(12, 1);
        lcd.print("="); //UHADNUTE CISLO VRATANE POZICIE
      } else if ((cislo3 == cielovecislo1) || (cislo3 == cielovecislo2) || (cislo3 == cielovecislo4)) {
        lcd.setCursor(12, 1);
        lcd.print("C"); //UHADNUTE CISLO BEZ POZICIE
      } else {
        lcd.setCursor(12, 1);
        lcd.print("-"); //NEUHADNUTE CISLO, ANI POZICIA
      }
    
      if (cislo4 == cielovecislo4) {
        lcd.setCursor(13, 1);
        lcd.print("="); //UHADNUTE CISLO VRATANE POZICIE
      } else if ((cislo4 == cielovecislo1) || (cislo4 == cielovecislo2) || (cislo4 == cielovecislo3)) {
        lcd.setCursor(13, 1);
        lcd.print("C"); //UHADNUTE CISLO BEZ POZICIE
      } else {
        lcd.setCursor(13, 1);
        lcd.print("-"); //NEUHADNUTE CISLO, ANI POZICIA
      }
    
      if ((cislo1 == cielovecislo1) && (cislo2 == cielovecislo2) && (cislo3 == cielovecislo3) && (cislo4 == cielovecislo4)) {
        lcd.setCursor(0, 2);
        lcd.print("VYHRALI STE!");
        lcd.setCursor(0, 3);
        lcd.print("KONIEC HRY          ");
        while (1);
      }
    }