Igra u kojoj se nasumično uključuju i isključuju LED, a korisnik mora ponoviti redoslijed kojim su se uključivale. Redoslijed paljenja bira se preko potenciometra za označavanje željene LED i tipkala za potvrdu odabira. Povratne informacije o igri (poraz/nova razina/pobjeda) su napravljene uz pomoć prikladnih svjetlosnih i zvučnih efekata.

Dependencies:   mbed zvucniEfekti

https://os.mbed.com/media/uploads/nikola_cancer/igra_memory.png

Revision:
0:f1138da8bd35
diff -r 000000000000 -r f1138da8bd35 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Dec 01 13:17:00 2021 +0000
@@ -0,0 +1,312 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2019 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "mbed.h"
+#include "zvucniEfekti.h"
+
+#define MAX_BROJ_SEKVENCE 10
+#define SAMPLEFREQ 8000
+
+InterruptIn tipkaloFlipLED(D12);
+DigitalOut ledZaProvjeru(D6);
+
+Ticker sampleRate;
+AnalogOut zvucnik(PA_5);
+AnalogIn potenciometar(A0);
+DigitalIn tipkalo(D9);
+
+int kontrolaZvuka; // globalna varijabla za odabir koji zvuk se pušta (u
+                   // funkciji sviraj) na piezo
+
+class Igra {
+private:
+  int brojLedica;
+  DigitalOut *ledice;
+  float vrijednostiZaPotenciometar[10];
+
+public:
+  Igra(DigitalOut *led, int brLED) {
+    ledice = led;
+    brojLedica = brLED;
+
+    float korak = 1. / brojLedica;
+    for (int i = 0; i < brojLedica + 1; i++) {
+      if (i == 0) {
+        vrijednostiZaPotenciometar[i] = 0;
+      } else {
+        vrijednostiZaPotenciometar[i] =
+            vrijednostiZaPotenciometar[i - 1] + korak;
+      }
+    }
+
+    tipkalo.mode(PullUp);
+
+    srand(time(0));
+  }
+
+  /*
+      globalna varijabla kontrolaZvuka:
+      0 -> gameStart
+      1 -> nextLevel
+      2 -> finalLevel
+      3 -> gameWon
+      4 -> gameOver
+  */
+  void sviraj() {
+    static int i = 0;
+
+    switch (kontrolaZvuka) {
+    case 0:
+      zvucnik.write_u16(zvukGameStart[i] << 8);
+      i++;
+      if (i == brojSamplovaZvukGameStart) {
+        i = 0;
+        zvucnik.write_u16(0);
+        sampleRate.detach();
+      }
+      break;
+
+    case 1:
+      zvucnik.write_u16(zvukNextLevel[i] << 8);
+      i++;
+      if (i == brojSamplovaZvukNextLevel) {
+        i = 0;
+        zvucnik.write_u16(0);
+        sampleRate.detach();
+      }
+      break;
+
+    case 2:
+      zvucnik.write_u16(zvukFinalLevel[i] << 8);
+      i++;
+      if (i == brojSamplovaZvukFinalLevel) {
+        i = 0;
+        zvucnik.write_u16(0);
+        sampleRate.detach();
+      }
+      break;
+
+    case 3:
+      zvucnik.write_u16(zvukGameWon[i] << 8);
+      i++;
+      if (i == brojSamplovaZvukGameWon) {
+        i = 0;
+        zvucnik.write_u16(0);
+        sampleRate.detach();
+      }
+      break;
+
+    case 4:
+      zvucnik.write_u16(zvukGameOver[i] << 8);
+      i++;
+      if (i == brojSamplovaZvukGameOver) {
+        i = 0;
+        zvucnik.write_u16(0);
+        sampleRate.detach();
+      }
+      break;
+    }
+  }
+
+  void generirajRandomSekvencu(int brojUzoraka, int *sekvenca) {
+    ugasiSveLED();
+    for (int i = 0; i < brojUzoraka; i++) {
+      int num = (rand() % brojLedica); // random broj između 0 i brLED
+      sekvenca[i] = num; // spremi u sekvencu zbog kasnije usporedbe generiranog
+      // i pogađanog
+
+      // upali i ugasi random LED
+      wait_ms(500);
+      ledice[num] = 1;
+      wait_ms(500);
+      ledice[num] = 0;
+      wait_ms(500);
+    }
+    wait(2);
+  }
+
+  void spremiUnosKorisnika(int brojUzoraka, int *sekvenca) {
+    for (int k = 0; k < brojUzoraka; k++) {
+      for (;;) {
+        for (int i = 0; i < brojLedica; i++) {
+          if (potenciometar >= vrijednostiZaPotenciometar[i] &&
+              potenciometar < vrijednostiZaPotenciometar[i + 1]) {
+            ledice[i] = 1;
+          } else {
+            ledice[i] = 0;
+          }
+        }
+
+        if (tipkalo == 0) {
+          wait_ms(50); // debounce
+          if (tipkalo == 0) {
+            for (int j = 0; j < brojLedica; j++) {
+              if (ledice[j].read() == 1) {
+                sekvenca[k] = j;
+
+                // da korisnih ima feedback da je ucitan njegov odabir
+                ledice[j] = 0;
+                wait_ms(500);
+                ledice[j] = 1;
+              }
+            }
+            // cekaj dok tipkalo ne ode u jedan (radi ko rising edge)
+            // da ove beskonacne petlje nema bi spremil 4x istu vrijednost u
+            // array (jer radi brzo)
+            do {
+            } while (tipkalo.read() == 0);
+            break;
+          }
+        }
+      }
+    }
+  }
+  /*
+      funkcija vraca 0 za razlicite arraye, a 1 za iste
+  */
+  int provjeriSekvence(int *generiranaSekvenca, int *unesenaSekvenca,
+                       int brojUzorakaSekvence) {
+    int i = 0;
+    for (i = 0; i < brojUzorakaSekvence; i++) {
+      if (generiranaSekvenca[i] != unesenaSekvenca[i]) {
+        return 0; // poraz
+      }
+    }
+    return 1; // sljedeca razina/pobjeda
+  }
+
+  void ugasiSveLED() {
+    for (int i = 0; i < brojLedica; i++) {
+      ledice[i] = 0;
+    }
+  }
+
+  void sljedecaRazina(int finalniLevel) {
+    ugasiSveLED();
+    if (finalniLevel != 0) {
+      kontrolaZvuka = 2;
+    } else {
+      kontrolaZvuka = 1;
+    }
+    sampleRate.attach(this, &Igra::sviraj, 1.0 / SAMPLEFREQ);
+    for (int i = 0; i < brojLedica; i++) {
+      ledice[i] = 1;
+      wait_us(100000);
+      ledice[i] = 0;
+    }
+    wait_us(100000);
+  }
+
+  void novaIgra() {
+    kontrolaZvuka = 0;
+    sampleRate.attach(this, &Igra::sviraj, 1.0 / SAMPLEFREQ);
+    wait(2);
+  }
+
+  void pobjeda() {
+    ugasiSveLED();
+    kontrolaZvuka = 3;
+    sampleRate.attach(this, &Igra::sviraj, 1.0 / SAMPLEFREQ);
+
+    // chaser effekt 5x sim tam
+    int i = 0;
+    do {
+
+      for (int j = 0; j < brojLedica; j++) {
+        ledice[j] = 1;
+        wait_us(60000);
+        ledice[j] = 0;
+      }
+
+      for (int j = brojLedica - 1; j >= 0;
+           j--) // -1 jer sizeof(arr) za arr[20] npr daje 20 a zadnji element je
+                // 19
+      {
+        ledice[j] = 1;
+        wait_us(60000);
+        ledice[j] = 0;
+      }
+
+      i++;
+    } while (i < 10);
+    wait(2);
+  }
+
+  void poraz() {
+    ugasiSveLED();
+    kontrolaZvuka = 4;
+    sampleRate.attach(this, &Igra::sviraj, 1.0 / SAMPLEFREQ);
+    int i = 0;
+    do {
+
+      for (int j = 0; j < brojLedica; j++) {
+        ledice[j] = 1;
+      }
+      wait_us(500000);
+
+      ugasiSveLED();
+      wait_us(500000);
+
+      i++;
+    } while (i < 3);
+    wait(2);
+  }
+};
+
+void flipLED() { ledZaProvjeru = !ledZaProvjeru; }
+
+int main() {
+  wait(1);
+  tipkaloFlipLED.mode(PullUp);
+  tipkaloFlipLED.rise(&flipLED);
+  // inicijalizacija pinova za igru
+  DigitalOut led[] = {D2, D4, D7, D8, D10, D11};
+  int brojLedica = sizeof(led) / sizeof(led[0]);
+
+  // spremanje generiranih i unesenih vrijednosti
+  int generiranaSekvenca[MAX_BROJ_SEKVENCE] = {0};
+  int unosKorisnika[MAX_BROJ_SEKVENCE] = {0};
+
+  // postavke i logika igre
+  int brojUzorakaSekvence = 3; // kolko puta se LED pale/gase
+  int pobjedaPorazZastavica;
+  int trenutniLevel = 0;
+  int finalniLevel = 2;
+
+  Igra igra(led, brojLedica);
+
+  while (true) {
+    if (trenutniLevel == 0) {
+      igra.novaIgra();
+    }
+    igra.generirajRandomSekvencu(brojUzorakaSekvence, generiranaSekvenca);
+    igra.spremiUnosKorisnika(brojUzorakaSekvence, unosKorisnika);
+    pobjedaPorazZastavica = igra.provjeriSekvence(
+        generiranaSekvenca, unosKorisnika, brojUzorakaSekvence);
+
+    switch (pobjedaPorazZastavica) {
+    case 0:
+      igra.poraz();
+      brojUzorakaSekvence = 3;
+      trenutniLevel = 0;
+      break;
+    case 1:
+      if (trenutniLevel == finalniLevel - 1) {
+        igra.sljedecaRazina(1); // 1 -> šalji zvuk finalLevel
+        brojUzorakaSekvence++;
+        trenutniLevel++;
+      } else if (trenutniLevel == finalniLevel) {
+        igra.pobjeda();
+        brojUzorakaSekvence = 3;
+        trenutniLevel = 0;
+      } else {
+        igra.sljedecaRazina(0); // 0 -> šalji zvuk nextLevel
+        brojUzorakaSekvence++;
+        trenutniLevel++;
+      }
+      break;
+    }
+  }
+}