Differences

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

Link to this comparison view

pm:prj2024:ddosaru:marius.cristea1811 [2024/05/27 02:04]
marius.cristea1811 [Software Design]
pm:prj2024:ddosaru:marius.cristea1811 [2024/05/27 02:10] (current)
marius.cristea1811 [Software Design]
Line 62: Line 62:
 ===== Conexiuni pini ===== ===== Conexiuni pini =====
 pinuri digitale: \\ pinuri digitale: \\
-SCK - pin 13 pentru microSD card reader si LCD (la comun) ​\\ +SCK - pin 13 pentru microSD card reader si LCD \\ 
-MOSI - pin 11 pentru microSD card reader si LCD (la comun) ​\\+MOSI - pin 11 pentru microSD card reader si LCD  \\
 pin 4 - CS microSD card reader \\ pin 4 - CS microSD card reader \\
 pin 8 - RES LCD \\ pin 8 - RES LCD \\
 pin 9 - DC LCD \\ pin 9 - DC LCD \\
 +pin 9 - Speaker (pe arduino nano) \\
 pin 10 - CS LCD \\ pin 10 - CS LCD \\
 pinuri analog: \\ pinuri analog: \\
  
-pin 2: input pentru speaker conectat la IN - amplificator \\ +pin A0,A1,A2,A3,A4: pinii pentru butoane \\
-pin 0,1,3,4,5: pinii pentru butoane \\+
  
  
Line 88: Line 88:
 </​note>​ </​note>​
  
 +Codul pentru joc: \\
 +<file PM_project>​
 +
 +#include <​Adafruit_GFX.h>​
 +#include <​Adafruit_ST7735.h>​
 +#include <​SPI.h>​
 +
 +// Definirea pinilor pentru LCD
 +#define TFT_CS ​    10
 +#define TFT_RST ​   8
 +#define TFT_DC ​    9
 +
 +// Definirea pinilor pentru butoane
 +#define BUTTON_UP ​     A0
 +#define BUTTON_DOWN ​   A4
 +#define BUTTON_LEFT ​   A1
 +#define BUTTON_RIGHT ​  A2
 +#define BUTTON_SELECT ​ A3
 +
 +// Crearea unui obiect Adafruit_ST7735 pentru ecranul LCD
 +Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,​ TFT_DC, TFT_RST);
 +
 +// Dimensiuni grilă
 +#define GRID_SIZE 3
 +#define CELL_SIZE 30 
 +
 +// Debounce
 +unsigned long lastDebounceTime = 0;
 +unsigned long debounceDelay = 200;
 +
 +// Starea jocului
 +char board[GRID_SIZE][GRID_SIZE];​
 +int currentPlayer = 0; // 0 pentru X, 1 pentru O
 +int currentRow = 0, currentCol = 0;
 +
 +// Structuri pentru a ține evidența mutărilor fiecărui jucător
 +struct Move {
 +  int row;
 +  int col;
 +};
 +
 +Move movesX[3];
 +Move movesO[3];
 +int moveCountX = 0;
 +int moveCountO = 0;
 +
 +// Calcularea coordonatelor pentru centrare
 +int gridStartX = (tft.width() - (GRID_SIZE * CELL_SIZE)) / 2;
 +int gridStartY = (tft.height() - (GRID_SIZE * CELL_SIZE) - 40) / 2;
 +
 +bool gameWon = false;
 +bool alreadyDisplayed = false;
 +unsigned long winTime;
 +
 +void setup() {
 +  Serial.begin(9600);​
 +
 +  // Inițializarea LCD-ului
 +  tft.initR(INITR_BLACKTAB);​
 +  tft.fillScreen(ST77XX_BLACK);​ // Curățarea ecranului și umplerea cu negru
 +
 +  // Inițializarea pinilor pentru butoane
 +  pinMode(BUTTON_UP,​ INPUT_PULLUP);​
 +  pinMode(BUTTON_DOWN,​ INPUT_PULLUP);​
 +  pinMode(BUTTON_LEFT,​ INPUT_PULLUP);​
 +  pinMode(BUTTON_RIGHT,​ INPUT_PULLUP);​
 +  pinMode(BUTTON_SELECT,​ INPUT_PULLUP);​
 +
 +  // Inițializarea tablei de joc
 +  for (int i = 0; i < GRID_SIZE; i++) {
 +    for (int j = 0; j < GRID_SIZE; j++) {
 +      board[i][j] = ' ';
 +    }
 +  }
 +
 +  // Desenarea grilei
 +  drawGrid();
 +  highlightCell(currentRow,​ currentCol, true);
 +}
 +
 +
 +void loop() {
 +  if (gameWon) {
 +    if (millis() - winTime > 10000) { // Așteaptă 10 secunde înainte de resetare
 +      resetBoard();​
 +      gameWon = false;
 +      alreadyDisplayed = false;
 +      tft.fillScreen(ST77XX_BLACK);​
 +      drawGrid();
 +    } else {
 +      if (!alreadyDisplayed) {
 +        char winner;
 +        if (currentPlayer == 0) {
 +          winner = '​X';​
 +        } else {
 +          winner = '​O';​
 +        }
 +        displayWinner(winner);​
 +        alreadyDisplayed = true;
 +        currentPlayer = 0;
 +      }
 +    }
 +    return;
 +  } else {
 +    readButtons();​
 +    // Evidențiere celula curentă
 +    highlightCell(currentRow,​ currentCol, true);
 +  }
 +}
 +
 +void readButtons() {
 +  if (millis() - lastDebounceTime > debounceDelay) {
 +    if (digitalRead(BUTTON_UP) == LOW) {
 +      lastDebounceTime = millis();
 +      moveCursor(0,​ -1); // Muta sus
 +    }
 +    ​
 +    if (digitalRead(BUTTON_DOWN) == LOW) {
 +      lastDebounceTime = millis();
 +      moveCursor(0,​ 1); // Muta jos
 +    }
 +    ​
 +    if (digitalRead(BUTTON_LEFT) == LOW) {
 +      lastDebounceTime = millis();
 +      moveCursor(-1,​ 0); // Muta stânga
 +    }
 +    ​
 +    if (digitalRead(BUTTON_RIGHT) == LOW) {
 +      lastDebounceTime = millis();
 +      moveCursor(1,​ 0); // Muta dreapta
 +    }
 +
 +    if (digitalRead(BUTTON_SELECT) == LOW) {
 +      lastDebounceTime = millis();
 +      placeMark();​ // Selecteaza miscare
 +    }
 +  }
 +}
 +
 +void drawGrid() {
 +  for (int i = 1; i < GRID_SIZE; i++) {
 +    tft.drawLine(gridStartX + CELL_SIZE * i, gridStartY, gridStartX + CELL_SIZE * i, gridStartY + GRID_SIZE * CELL_SIZE, ST77XX_WHITE);​
 +    tft.drawLine(gridStartX,​ gridStartY + CELL_SIZE * i, gridStartX + GRID_SIZE * CELL_SIZE, gridStartY + CELL_SIZE * i, ST77XX_WHITE);​
 +  }
 +}
 +
 +void highlightCell(int row, int col, bool highlight) {
 +  // Curățăm celula anterioară (dacă există)
 +  for (int i = 0; i < GRID_SIZE; i++) {
 +    for (int j = 0; j < GRID_SIZE; j++) {
 +      if (i == row && j == col) continue;
 +      int x = gridStartX + j * CELL_SIZE;
 +      int y = gridStartY + i * CELL_SIZE;
 +      tft.drawRect(x,​ y, CELL_SIZE, CELL_SIZE, ST77XX_WHITE);​
 +      if (board[i][j] != ' ') {
 +        drawMark(i, j, board[i][j]);​
 +      }
 +    }
 +  }
 +
 +  // Evidențiem celula curentă
 +  int x = gridStartX + col * CELL_SIZE;
 +  int y = gridStartY + row * CELL_SIZE;
 +  tft.drawRect(x,​ y, CELL_SIZE, CELL_SIZE, highlight ? ST77XX_BLUE : ST77XX_WHITE);​
 +  // Redesenăm conținutul celulei după evidențiere pentru a nu o pierde
 +  if (board[row][col] != ' ') {
 +    drawMark(row,​ col, board[row][col]);​
 +  }
 +}
 +
 +void moveCursor(int dx, int dy) {
 +  currentCol = (currentCol + dx + GRID_SIZE) % GRID_SIZE;
 +  currentRow = (currentRow + dy + GRID_SIZE) % GRID_SIZE;
 +}
 +
 +void placeMark() {
 +  if (board[currentRow][currentCol] == ' ') {
 +    char mark = currentPlayer == 0 ? '​X'​ : '​O';​
 +    board[currentRow][currentCol] = mark;
 +    drawMark(currentRow,​ currentCol, mark);
 +
 +    // Adaugă mutarea la istoricul mutărilor jucătorului curent
 +    if (currentPlayer == 0) {
 +      if (moveCountX >= 3) {
 +        Move oldestMove = movesX[moveCountX % 3];
 +        board[oldestMove.row][oldestMove.col] = ' ';
 +        drawMark(oldestMove.row,​ oldestMove.col,​ ' ');
 +      }
 +      movesX[moveCountX % 3] = {currentRow,​ currentCol};​
 +      moveCountX++;​
 +    } else {
 +      if (moveCountO >= 3) {
 +        Move oldestMove = movesO[moveCountO % 3];
 +        board[oldestMove.row][oldestMove.col] = ' ';
 +        drawMark(oldestMove.row,​ oldestMove.col,​ ' ');
 +      }
 +      movesO[moveCountO % 3] = {currentRow,​ currentCol};​
 +      moveCountO++;​
 +    }
 +
 +    // Verifică dacă jucătorul curent a câștigat
 +    if (checkWin(currentRow,​ currentCol, mark)) {
 +      winTime = millis(); // Setează timpul de câștig
 +      gameWon = true;     // Setează starea de câștig
 +      return;
 +    }
 +
 +    // Schimbă jucătorul
 +    currentPlayer = 1 - currentPlayer;​
 +    displayCurrentPlayer();​
 +
 +  }
 +}
 +
 +void drawMark(int row, int col, char mark) {
 +  int x = gridStartX + col * CELL_SIZE + CELL_SIZE / 2 - 5;
 +  int y = gridStartY + row * CELL_SIZE + CELL_SIZE / 2 - 8;
 +  tft.setCursor(x,​ y);
 +  tft.setTextColor(ST77XX_WHITE);​
 +  tft.setTextSize(2);​
 +  if (mark == ' ') {
 +    // Curățăm marca
 +    tft.fillRect(gridStartX + col * CELL_SIZE + 1, gridStartY + row * CELL_SIZE + 1, CELL_SIZE - 2, CELL_SIZE - 2, ST77XX_BLACK);​
 +  } else {
 +    tft.print(mark);​
 +  }
 +}
 +
 +bool checkWin(int row, int col, char mark) {
 +  // Verifică rândul
 +  if (board[row][0] == mark && board[row][1] == mark && board[row][2] == mark) return true;
 +  // Verifică coloana
 +  if (board[0][col] == mark && board[1][col] == mark && board[2][col] == mark) return true;
 +  // Verifică diagonalele
 +  if (board[0][0] == mark && board[1][1] == mark && board[2][2] == mark) return true;
 +  if (board[0][2] == mark && board[1][1] == mark && board[2][0] == mark) return true;
 +  return false;
 +}
 +
 +void displayWinner(char winner) {
 +  tft.fillScreen(ST77XX_BLACK);​
 +
 +  // Definim variabilele pentru a stoca limitele textului
 +  int16_t x1, y1;
 +  uint16_t w, h;
 +
 +  // Creăm textul complet care va fi afișat
 +  String text = "​Player ";
 +  text += winner;
 +  text += " won!";
 +
 +  // Setăm dimensiunea textului
 +  tft.setTextSize(1);​
 +
 +  // Obținem limitele textului
 +  tft.getTextBounds(text.c_str(),​ 0, 0, &x1, &y1, &w, &h);
 +
 +  // Calculăm pozițiile cursorului pentru a centra textul
 +  int16_t centeredX = (tft.width() - w) / 2;
 +  int16_t centeredY = (tft.height() - h) / 2;
 +
 +  // Setăm culoarea textului
 +  tft.setTextColor(ST77XX_WHITE);​
 +
 +  // Setăm cursorul la poziția calculată
 +  tft.setCursor(centeredX,​ centeredY);
 +
 +  // Afișăm textul
 +  tft.print(text);​
 +
 +  // Coordonatele centrului smiley face-ului
 +  int16_t smileyX = tft.width() / 2;
 +  int16_t smileyY = centeredY / 2; // Poziționăm smiley face-ul deasupra textului
 +
 +  // Dimensiunea smiley face-ului
 +  int16_t radius = 20;
 +
 +  // Desenam smiley face-ul
 +  tft.drawCircle(smileyX,​ smileyY, radius, ST77XX_WHITE);​
 +  tft.fillCircle(smileyX - radius / 3, smileyY - radius / 3, 2, ST77XX_WHITE);​
 +  tft.fillCircle(smileyX + radius / 3, smileyY - radius / 3, 2, ST77XX_WHITE);​
 +  drawArc(smileyX,​ smileyY, radius - 5, 0, 180, ST77XX_WHITE);​
 +}
 +
 +void drawArc(int16_t x, int16_t y, int16_t radius, int16_t startAngle, int16_t endAngle, uint16_t color) {
 +  for (int16_t angle = startAngle; angle <= endAngle; angle++) {
 +    float rad = angle * 3.14 / 180;
 +    int16_t x1 = x + cos(rad) * radius;
 +    int16_t y1 = y + sin(rad) * radius;
 +    tft.drawPixel(x1,​ y1, color);
 +  }
 +}
 +
 +void resetBoard() {
 +  for (int i = 0; i < GRID_SIZE; i++) {
 +    for (int j = 0; j < GRID_SIZE; j++) {
 +      board[i][j] = ' ';
 +    }
 +  }
 +  moveCountX = 0;
 +  moveCountO = 0;
 +  drawGrid();
 +  highlightCell(currentRow,​ currentCol, true);
 +}
 +
 +void displayCurrentPlayer() {
 +  // Șterge zona jucătorului curent
 +  tft.fillRect(0,​ GRID_SIZE * CELL_SIZE + gridStartY, tft.width(),​ 20, ST77XX_BLACK);​
 +
 +  // Definim variabilele pentru a stoca limitele textului
 +  int16_t x1, y1;
 +  uint16_t w, h;
 +
 +  // Creăm textul complet care va fi afișat
 +  String text = "​Player:​ ";
 +  text += (currentPlayer == 0) ? '​X'​ : '​O';​
 +
 +  // Setăm dimensiunea textului
 +  tft.setTextSize(1);​
 +
 +  // Obținem limitele textului
 +  tft.getTextBounds(text.c_str(),​ 0, 0, &x1, &y1, &w, &h);
 +
 +  // Calculăm pozițiile cursorului pentru a centra textul
 +  int16_t centeredX = (tft.width() - w) / 2;
 +  int16_t centeredY = gridStartY + GRID_SIZE * CELL_SIZE + 5;
 +
 +  // Setăm cursorul la poziția calculată
 +  tft.setCursor(centeredX,​ centeredY);
 +
 +  // Setăm culoarea textului
 +  tft.setTextColor(ST77XX_WHITE);​
 +
 +  // Afișăm textul
 +  tft.print(text);​
 +}
 +
 +</​file>​
 +
 +Codul pentru muzica: \\
 +<file music>
 +#include <​SPI.h>​
 +#include <​SD.h>​
 +#include <​TMRpcm.h>​
 +
 +#define CS_SD 4
 +#define Speaker 9
 +TMRpcm audio;
 +
 +void setup() {
 +  Serial.begin(9600);​
 +
 +  if(!SD.begin(CS_SD)) {
 +    Serial.println("​A esuat initializarea cardului SD");
 +    while(1);
 +  }
 +
 +  audio.CSPin = CS_SD;
 +  audio.speakerPin = Speaker;
 +  audio.setVolume(6);​
 +
 +}
 +
 +void loop() {  ​
 +  if (!audio.isPlaying()) {
 +    audio.play("​powerup.wav"​);​
 +  }
 +}
 +
 +
 +
 +
 +
 +</​file>​
 ===== Rezultate Obţinute ===== ===== Rezultate Obţinute =====
  
pm/prj2024/ddosaru/marius.cristea1811.1716764681.txt.gz · Last modified: 2024/05/27 02:04 by marius.cristea1811
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