Nume: Marian Melania-Valentina
Grupă: 331CC
Proiectul este bazat pe faimosul joc Wordle. Ideea jocului este următoarea: utilizatorul are 6 încercări pentru a ghici un cuvânt în limba engleză, format din 5 litere - în urma fiecărui cuvânt introdus, utilizatorul primește indicii legate de literele ce aparțin cuvântului, prin colorarea căsuței corespunzătoare fiecărei litere astfel:
Utilizatorul interacționează cu jocul prin intermediul tastaturilor matriceale 4×4, fiecare literă fiind reprezentată printr-un buton al tastaturilor. De asemenea, există pe a doua tastatură un buton ce are asociată acțiunea de Enter (înregistrarea cuvântului în joc) și un buton cu acțiunea de ștergere a unei litere din cuvânt. Pe ecranul LCD există un buton de reset, a cărui apăsare declanșează reînceperea jocului. Întregul joc este afișat pe ecranul LCD, iar în momentul finalizării jocului se aprinde unul dintre cele două led-uri, în funcție de rezultatul jucătorului: dacă cuvântul a fost ghicit, se aprinde led-ul verde, iar dacă jucătorul nu a ghicit cuvântul, se aprinde cel roșu.
Listă de piese utilizate:
Schema electrică, realizată în Fusion:
Close-up label-uri:
Componentele sunt conectate la placă astfel:
Am realizat implementarea software în mediul de dezvoltare PlatformIO. Limbajul utilizat pentru dezvoltarea proiectului este C++.
Biblioteci utilizate:
La începutul fiecărui joc, programul alege în mod aleator un cuvânt pe care utilizatorul trebuie să îl ghicească. Pentru stocarea cuvintelor de ghicit, am creat o matrice de caractere, pe fiecare linie a acesteia aflându-se un cuvânt. Pentru alegerea aleatoare a unui cuvânt, am utilizat funcția analogRead() pe un pin analogic care nu era conectat la nimic, aceasta întorcând un număr random.
// selectarea unui cuvânt random random_row = analogRead(A15) % 50; for(int i = 0; i < 6; i ++) { selected_word[i] = all_words[random_row][i]; }
În funcția loop() am implementat desfășurarea unui joc complet. Utilizatorul are 6 încercări pentru a ghici cuvântul, interacționând în fiecare rundă cu tastaturile astfel:
Voi introduce bucăți din codul funcției loop(), pentru o înțelegere mai aprofundată a implementării, unde:
Afișarea unei litere pe ecran
if(pressedLetter1 && pressedLetter1 != '#' && pressedLetter1 != '*' && pressedLetter1 != '1' && pressedLetter1 != '2' && pressedLetter1 != '3' && pressedLetter1 != '4' && i < 5) { // afișarea literei apăsate tft.setTextColor(TFT_WHITE); tft.setCursor(letter_x, letter_y); tft.setTextFont(1); tft.setTextSize(3); tft.print(pressedLetter1); // updatarea coordonatelor pentru următoarea literă letter_x += 60; box_x += 60; // updatarea cuvântului curent guess[i] = pressedLetter1; i ++; continue; }
Ștergerea unei litere
if(pressedLetter2 && pressedLetter2 == '#') { // verificăm să nu ieșim din parametrii zonei de joc if(letter_x >= 92 && letter_x <= 332 && i >= 1 && i <= 5) { // updatăm coordonatele pentru a ne întoarce la litera anterioară box_x -= 60; letter_x -= 60; i --; // ștergerea literei prin desenarea unui pătrat peste cel existent tft.drawRect(box_x, box_y, 50, 50, SQUARE_INITIAL); tft.fillRect(box_x, box_y, 50, 50, SQUARE_INITIAL); // updatare cuvânt ghicit guess[i] = '0'; } continue; }
Apăsarea tastei ENTER
if(pressedLetter2 && pressedLetter2 == '*' && i == 5) { valid_enter = 1; box_x = 15; letter_x = 32; // verificăn ce litere din cuvântul introdus corespund cu cele din cuvântul care trebuie ghicit validateGuess(selected_word, guess, box_x, box_y, letter_x, letter_y); // verficăm dacă s-a ghicit cuvântul if(isGuessCorrect(selected_word, guess)) { end_game = true; delay(1000); // aprindem led-ul verde pentru câștig digitalWrite(ledPinGreen, HIGH); continue; } // verificam dacă s-a terminat jocul și cuvântul nu a fost ghicit if(!isGuessCorrect(selected_word, guess) && tries == 0) { end_game = true; delay(1000); // aprindem led-ul roșu pentru pierdere digitalWrite(ledPinRed, HIGH); continue; } }
Pentru verificarea literelor comune dintre cuvântul introdus și cel care trebuie ghicit, am creat funcția checkWord(), care returnează un șir ce conține caracterele 0, 1 sau 2 corespunzătoare celor 5 litere, care este folosit de funcția validateGuess() pentru a crea animația astfel:
Funcția de realizare a animației
void validateGuess(char selected_word[], char guess[], int box_x, int box_y, int letter_x, int letter_y) { String color_codes = checkWord(selected_word, guess); for(int i = 0; i < 5; i ++) { delay(500); colorBox(color_codes, box_x, box_y, i); writeLetter(guess, letter_x, letter_y, i); box_x += 60; letter_x += 60; } }
În urma finalizării jocului, pe ecran apare un mesaj în funcție de rezultatul obținut:
Am implementat această funcționalitate folosind întreruperi, care se declanșau în urma detectării trecerii pinilor led-urilor din starea LOW în starea HIGH. De asemenea, am configurat led-urile pe pinii 2 și 3, care suportă întreruperi pe ATMEGA.
// în funcția setup() attachInterrupt(digitalPinToInterrupt(ledPinGreen), ISRCastig, RISING); attachInterrupt(digitalPinToInterrupt(ledPinRed), ISRPierdere, RISING); // funcția ISR pentru câștig void ISRCastig() { tft.setTextColor(TFT_GREEN); tft.setCursor(50, 420); tft.setTextFont(1); tft.setTextSize(4); tft.print("YOU WIN!:)"); } // funcția ISR pentru pierdere void ISRPierdere() { tft.setTextColor(TFT_RED); tft.setCursor(70, 420); tft.setTextFont(1); tft.setTextSize(3); tft.print("YOU LOSE!:("); tft.setTextColor(TFT_WHITE); tft.setCursor(55, 450); tft.setTextFont(1); tft.setTextSize(2); tft.print("The word was "); tft.setTextColor(TFT_GREEN); tft.print(selected_word); }
În aceste poze se observă aspectul jocului în urma câștigării sau pierderii unui joc.
Am înregistrat, de asemenea, și un videoclip cu o demonstrație a jocului: Wordle - Proiect PM
Pentru mine, realizarea acestui proiect a fost foarte interesantă, atât datorită faptului că am avut ocazia de a implementa unul dintre jocurile mele preferate, dar și deoarece am experimentat pentru prima oară realizarea unui proiect ce implică o placă Arduino de la 0, realizând atât conectarea acesteia de celelalte componente hardware, cât și implementarea codului.
marian_melania_proiect_pm.zip - Arhivă Proiect