Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pm:prj2023:adarmaz:utictactoe [2023/05/04 15:28]
mihai_cosmin.rosu
pm:prj2023:adarmaz:utictactoe [2023/05/27 18:17] (current)
mihai_cosmin.rosu
Line 1: Line 1:
 ====== Ultimate Tic-Tac-Toe - Roșu Mihai Cosmin - 333CA ====== ====== Ultimate Tic-Tac-Toe - Roșu Mihai Cosmin - 333CA ======
 +
 +===== Demo =====
 +
 +<​html>​
 +  <​iframe ​
 +    src="​https://​www.youtube.com/​embed/​XRYpv7-YvOo" ​
 +    title="​YouTube video player" ​
 +    frameborder="​0" ​
 +    allow="​accelerometer;​ autoplay; clipboard-write;​ encrypted-media;​ gyroscope; picture-in-picture;​ web-share" ​
 +    allowfullscreen
 +    style="​aspect-ratio:​ 16/9; width: 100%;"
 +  ></​iframe>​
 +</​html>​
  
 ===== Introducere ===== ===== Introducere =====
Line 17: Line 30:
 ==== Explicarea proiectului ==== ==== Explicarea proiectului ====
  
-Pentru început, jucătorul poate folosi butoanele pentru a-și alege modul de joc dorit, iar apoi, în cazul în care a fost ales modul de Singleplayer,​ dificultatea dorită. Odată alese, jocul începe. Pentru a selecta căsuța dorită pentru plasarea unui X (sau 0) este folosit potențiometrul,​ care oferă posibilitatea parcurgerii tablei de joc linie cu linie, de la stânga la dreapta. După ce este aleasă casuța dorită, este folosit unul dintre butoane pentru a definitiva alegerea. În final, la terminarea jocului, buzzer-ul va face un sunet reprezentativ ​pentru ​rezultatul ​jocului.+  * Pentru început, jucătorul poate folosi butoanele pentru a-și alege modul de joc dorit, iar apoi, în cazul în care a fost ales modul de Singleplayer,​ dificultatea dorită ​și cu ce simbol vrea să joace (X sau 0). Odată alese, jocul începe. 
 +  * Pentru a selecta căsuța dorită pentru plasarea unui X (sau 0) este folosit potențiometrul,​ care oferă posibilitatea parcurgerii tablei de joc linie cu linie, de la stânga la dreapta. După ce este aleasă casuța dorită, este folosit unul dintre butoane pentru a definitiva alegerea. ​Dacă alegerea făcută nu este permisă, acest lucru este anunțat de buzzer, iar jucătorul trebuie sa aleagă din nou o căsuță. 
 +  * În final, la terminarea jocului, buzzer-ul va face un sunet pentru ​a semnala încheierea ​jocului.
 ==== Laboratoare folosite ==== ==== Laboratoare folosite ====
  
 Laboratoarele folosite pentru realizarea proiectului sunt: Laboratoarele folosite pentru realizarea proiectului sunt:
 +  * [[pm:​lab:​lab2-2023| Laborator 2.]] Întreruperi hardware
   * [[pm:​lab:​lab3-2023| Laborator 3.]] Timere. PWM   * [[pm:​lab:​lab3-2023| Laborator 3.]] Timere. PWM
   * [[pm:​lab:​lab4-2022| Laborator 4.]] ADC   * [[pm:​lab:​lab4-2022| Laborator 4.]] ADC
Line 32: Line 48:
  
 ===== Hardware Design ===== ===== Hardware Design =====
 +
 +==== Lista componentelor ====
  
 Lista componentelor folosite în cadrul proiectului:​ Lista componentelor folosite în cadrul proiectului:​
Line 40: Line 58:
   * Buzzer   * Buzzer
   * 2 x Butoane   * 2 x Butoane
 +  * 2 x Rezistențe 10K
   * Breadboard   * Breadboard
-  * Fire de legatură+  * Fire de legătură 
 + 
 +==== Schema circuitului ==== 
 +{{ :​pm:​prj2023:​adarmaz:​schema_circuit_utictactoe.png?​700 |}} 
 + 
 +===== Software Design ===== 
 + 
 +==== Detalii generale ==== 
 +  * Pentru dezvoltarea proiectului am folosit **Arduino IDE**, în cadrul căruia am importat următoarele biblioteci:​ 
 +    - **Adafruit GFX**, bibliotecă ce se poate importa direct din IDE, necesară pentru a desena/​scrie pe ecran 
 +    - **Arduino ST7789 Fast**, bibliotecă externă, folosită pentru a comunica cu ecranul prin **SPI**, folosește **Adafruit GFX** și **SPI.h** 
 +  * În cadrul implementării am folosit și operații cu registre pentru: 
 +    - **ADC**: Am ales să configurez și să folosesc ADC astfel, fiindcă am avut nevoie să controlez prescalerul folosit de acesta. Acest lucru era necesar fiindcă pentru o citire de ADC, de fapt au loc 100 de citiri, pentru a reduce noise-ul. 
 +    - **PWM**: Pentru a trimite un semnal PWM buzzer-ului,​ am ales să folosesc registre pentru a configura **Timer1** în modul **FastPWM**. De asemenea, pentru a determina când trebuie oprit semnalul PWM, folosesc întreruperea de overflow a timer-ului. 
 +    - **Întreruperi**:​ Pentru întreruperile externe **INT0**, **INT1** și întreruperea de timer **TIMER1_OVF**. 
 + 
 +==== Implementare generală ==== 
 +  * Jocul are **5 stări**, care coordonează ce este afișat pe ecran: __Meniu principal__,​ __alegerea dificultății__ pentru Singleplayer,​ __alegerea simbolului__,​ __joc__ și __final__. 
 +  * În funcție de starea în care se află jocul, întreruperile fac lucruri diferite. De asemenea, în starea de Joc se citește constant din ADC pentru a actualiza căsuța selectată. 
 +  * Tabla de joc este reprezentată prin două matrice, una de 9x9 (tabla completă) și una de 3x3 (tabla mare/tabla ce conține rezultatele tablelor mici) și o variabila care indică tabla în care trebuie plasată mutarea. 
 +  * Timer-ul folosit pentru PWM stă oprit până când trebuie ca buzzer-ul să scoată un sunet. Atunci, timer-ul este pornit în modul FastPWM, și oprit (registrele sunt resetate) după un număr de overflow-uri. 
 + 
 +==== Multiplayer ==== 
 +  * Ambii jucători folosesc aceleași controale. După ce un jucător face o mutare validă, este rândul celuilalt. 
 + 
 +==== Singleplayer ==== 
 +  * Modul de singleplayer se bazează pe rularea unui algoritm pentru a determina cea mai bună mutare, luând în calcul diferiți factori. 
 +  * Algoritmii folosiți iau în calcul **1-2 ture** în față. 
 +  * Cele două dificultăți diferă prin factorii folosiți pentru determinarea mutării. Pentru ambele dificultăți,​ dacă sunt mai multe mutări care sunt considerate la fel de bune, se alege prima găsită. 
 + 
 +=== Singleplayer Easy === 
 +  * Algoritmul folosit pentru dificultatea **Easy** se bazează pe **prioritatea** pe care o are mutarea în tabla curentă în care se află. Acesta verifică prioritatea pentru fiecare posibilă mutare din tabla curentă. 
 +  * Dacă următoarea mutare permite plasarea în orice tablă, se rulează algoritmul în tabla mare pentru a determina în ce tabla mică va avea loc mutarea. 
 +  * Prioritățile folosite sunt (jucător curent = AI): 
 +    * **0.** Jucătorul curent câștigă tabla curentă 
 +    * **1.** Jucătorul curent blochează adversarul din a câștiga tabla 
 +    * **2.** Dacă tabla este goală, mutare în colț 
 +    * **3.** Dacă jucătorul curent nu a mutat deloc în tabla curentă, iar adversarul a mutat în centru, mutare în colț 
 +    * **3.** Dacă jucătorul curent nu a mutat deloc în tabla curentă, iar adversarul nu a mutat în centru, mutare în colț 
 +    * **4.** Mutare care duce tabla într-o stare din care jucătorul curent poate câștiga cu o mutare 
 +    * **5.** Mutare în colț 
 +    * **6.** Altfel 
 + 
 +=== Singleplayer Hard === 
 +  * Algoritmul folosit pentru dificultatea **Hard** se bazează pe **prioritatea** pe care o are mutarea la nivelul întregului joc. Din nou, algoritmul calculează această prioritate pentru posibilele mutări din tabla curentă. 
 +  * Dacă următoarea mutare permite plasarea în orice tablă, se rulează mai întâi algoritmul folosit de dificultatea Easy în tabla mare pentru a determina în ce tabla mică va avea loc mutarea. 
 +  * Prioritățile folosite sunt (jucător curent = AI): 
 +    * **0.** Mutare care face ca jucătorul curent să câștige întregul joc 
 +    * **9.** Mutare care duce inamicul într-o tablă finalizată 
 +    * **10.** Mutare care duce inamicul într-o tablă pe care o poate câștiga, caz în care câștigă întregul joc 
 +    * **6.** Mutare care duce inamicul într-o tablă pe care jucătorul curent o poate câștiga 
 +    * **7.** Mutare care duce inamicul într-o tablă pe care o poate câștiga, iar dacă o câștigă duce jucătorul curent într-o tablă terminată sau pe care o poate câștiga 
 +    * **8.** Mutare care duce inamicul într-o tablă pe care o poate câștiga, iar dacă o câștigă duce jucătorul curent într-o tablă pe care nu o poate câștiga 
 +    * **1.** Mutare care duce inamicul într-o tablă în care nu a mutat deloc 
 +    * **2.** Mutare care duce inamicul într-o tablă în care a mutat o singură dată 
 +    * **3.** Mutare care duce inamicul într-o tablă în care a mutat de minim două ori, dar jucătorul curent a mutat de mai multe ori 
 +    * **4.**Mutare care duce inamicul într-o tablă în care a mutat de minim două ori, dar jucătorul curent a mutat de cel mult atâtea ori cât inamicul 
 +    * **5.** Altfel 
 +  * **Ordinea** priorităților nu este întâmplătoare,​ întrucât este important în ce ordine sunt verificate posibilele priorități. Acest lucru este datorat faptului că necesitățile unor priorități sunt îndeplinite și de altele, care adaugă restricții suplimentare. 
 + 
 +===== Rezultate obținute ===== 
 + 
 +==== Părere personală ==== 
 + 
 +Rezultatul obținut mi-a depășit cu mult așteptările. Acesta fiind **primul proiect** pe care l-am făcut folosind **Arduino**,​ mă așteptam ca din ce mi-am propus inițial să trebuiască să renunț la unele funcționalități. 
 + 
 +Din fericire, nu a fost nevoie, deoarece, deși m-am lovit de diferite dificultăți pe parcursul implementării proiectului,​ am reușit să rezolv problemele, astfel încat proiectul să funcționeze în modul în care mi-l imaginasem la început. 
 + 
 +==== Imagini proiect ==== 
 + 
 +{{ :​pm:​prj2023:​adarmaz:​utictactoe_meniu.jpg?​700 |}} 
 + 
 +{{ :​pm:​prj2023:​adarmaz:​utictactoe_img1.jpg?​700 |}} 
 + 
 +{{ :​pm:​prj2023:​adarmaz:​utictactoe_img2.jpg?​700 |}} 
 + 
 +===== Concluzii ===== 
 + 
 +În primul rand, personal **mă bucur că am avut de făcut acest proiect**, procesul de implementare fiind complet diferit față de o temă obișnuită. Datorită acestuia, acum consider că am văzut măcar o parte din câte lucruri se pot face folosint o simplă placuță Arduino și sper să nu fie ultima dată când interacționez cu una. 
 + 
 +În al doilea rând, aș vrea să menționez câteva probleme ale proiectului:​ 
 +  * Deoarece ecranul are nevoie de un timp scurt, dar care nu este neglijabil, pentru a desena ceva, este posibil ca atunci când jocul se termina să se apese un buton, care te duce înapoi în meniu, înainte ca textul "X WINS" sau "0 WINS" să se afișeze, ceea ce duce programul în starea de meniu, deși pe ecran este afișat textul de sfârșit de joc. 
 +  * Uneori, o singură apăsare de buton declanșează de două ori întreruperea. Acest lucru poate fi observat ușor încercând o mutare invalidă, fiindcă se va auzi buzzer-ul de două ori. 
 +  * Pe dificultatea Hard, la începutul jocului, când tabla este în mare parte goală, o mutare a AI-ului durează aproximativ 10 secunde, ceea ce este mult. Deși nu este o problemă la fel de gravă ca celelalte două, este deranjant pentru utilizator. Timpul poate fi redus prin eficientizarea codului. 
 + 
 +===== Download ===== 
 +<note important>​**Codul sursă, biblioteca Arduino_ST7789_Fast,​ schemele și imaginile din această documentație pot fi găsite în următoarea arhivă: {{:​pm:​prj2023:​adarmaz:​pm_rosu_mihai_cosmin_333ca_2023.zip|}}.** 
 + 
 +**De asemenea, proiectul poate fi găsit și pe GitHub: [[https://​github.com/​mehigh8/​UltimateTicTacToePM|Ultimate Tic-Tac-Toe]]**</​note>​ 
 + 
 +===== Bibliografie/​Resurse ===== 
 + 
 +==== Resurse documentație ==== 
 +  * [[https://​miro.com/​index/​|Tool folosit la realizarea schemei bloc]] 
 +  * [[https://​fritzing.org/​|Tool folosit la realizarea schemei circuitului]] 
 + 
 +==== Resurse hardware și software ==== 
 +  * [[https://​ocw.cs.pub.ro/​courses/​_media/​pm/​atmel-7810-automotive-microcontrollers-atmega328p_datasheet.pdf|Documentație ATMega328P]] 
 +  * [[https://​docs.arduino.cc/​built-in-examples/​digital/​Button|Tutorial conectare buton Arduino]] 
 +  * [[https://​www.youtube.com/​watch?​v=-nECx4DOE84|Tutorial folosire ecran ST7789]] 
 +  * [[https://​docs.arduino.cc/​tutorials/​generic/​secrets-of-arduino-pwm|Tutorial PWM cu registre]] 
 +  * [[https://​github.com/​cbm80amiga/​Arduino_ST7789_Fast|Biblioteca Arduino_ST7789_Fast]] 
 +  * [[pp:​22:​teme:​prolog-ultimate-ttt|Sursă inspirație pentru prioritățile folosite în modul Singleplayer]] 
  
 <​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​Export to PDF</​a></​html>​ <​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​Export to PDF</​a></​html>​
  
pm/prj2023/adarmaz/utictactoe.1683203313.txt.gz · Last modified: 2023/05/04 15:28 by mihai_cosmin.rosu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0