Saper na arduino

Typ_projektu
Arduino
Zdjecie główne
Błąd wyświetlania obrazu
Krótki opis projektu

Projekt zrealizowany w ramach przedmiotu "Techniki mikroprocesorowe" na 4 semestrze Automatyki i Robotyki na wydziale MEiL Politechniki Warszawskiej. Projekt został zrealizowany z pomocą sztucznej inteligencji tj. chatGPT 3.5

Autorzy projektu: Stanisław Walczak Hubert Przybysz

Niezbędne elementy

 

1. Płytka Arduino UNO

2. wyświetlacz oled 64x128 pikseli

3. "Game Console v0.2 beta"

4. kabel usb do arduino

Sprzęt

Laptop lub komputer

Opis projektu

Projekt realizuje uproszczoną wersję sapera. W ramach gry można wybierać pole, którego stan chce się zmienić lub podejrzeć. Po najechaniu na pole można zobaczyć jego stan tj. pole niezaznaczone, pole zaznaczone wraz z ilością bomb dookoła, pole oflagowane. Można to robić za pomocą 4 przycisków poruszając się między polami w górę, dół, lewo i w prawo. Pola można edytować na dwa sposoby: poprzez postawienie flagi, lub poprzez odkrycie pola.
W przeciwieństwie do zwykłego sapera pola nie odkrywają się same, to znaczy, że każde pole z osobna trzeba kliknąć, by odkryć wszystkie. Bomby generują się przed pierwszym ruchem gracza, więc można w pierwszym ruchu trafić na bombę. Bomby generują się w losowej ilości 25 do 35 na mapie 16 na 10 pól.

kod programu
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

#define OLED_RESET    -1
#define SCREEN_ADDRESS 0x3C

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

int t[16][10];
unsigned long lastMoveTime = 0;

int miny = 0;
int activeAreaX = 0;
int activeAreaY = 0;


void placeMines() {
    randomSeed(analogRead(0)); // Inicjalizacja generatora liczb pseudolosowych

    miny = random(25, 35); // Losowa liczba min w zakresie od 25 do 35

    int minesPlaced = 0;
    while (minesPlaced < miny) {
        int x = random(10);
        int y = random(16);
        if (t[y][x] != 9) { // Sprawdzenie, czy na tym polu nie ma już miny
            t[y][x] = 9; // Umieszczenie miny
            minesPlaced++;
        }
    }
}

void calculateNumbers() {
    for (int i = 0; i < 16; i++) {
        for (int j = 0; j < 10; j++) {
            if (t[i][j] == 9) {
                continue; // Pomijamy pola z minami
            }
            int count = 0;
            // Sprawdzenie sąsiedztwa (8 pól dookoła)
            for (int dx = -1; dx <= 1; dx++) {
                for (int dy = -1; dy <= 1; dy++) {
                    int nx = j + dx;
                    int ny = i + dy;
                    if (nx >= 0 && nx < 10 && ny >= 0 && ny < 16 && t[ny][nx] == 9) {
                        count++;
                    }
                }
            }
            t[i][j] = count; // Zapisujemy liczbę min w sąsiedztwie
        }
    }
}

void setup() {
  Serial.begin(9600);
  // Inicjalizacja ekranu OLED
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("Nie udało się zainicjować wyświetlacza OLED"));
    for(;;);
  }

 // Inicjalizacja tablicy
  for (int i = 0; i < 16;i++) {
    for (int j = 0; j < 10; j++) {
      // Przykładowe wartości dla zmiennych typu int w tablicy
      t[i][j] = 0;   // Przykładowa wartość dla pierwszej zmiennej int  
    }

    
  }


pinMode(8, INPUT_PULLUP); // Pin 8 - ruch w prawo
  pinMode(7, INPUT_PULLUP); // Pin 7 - ruch w górę
  pinMode(9, INPUT_PULLUP); // Pin 9 - ruch w dół
  pinMode(10, INPUT_PULLUP); // Pin 10 - ruch w lewo

    pinMode(4, INPUT_PULLUP); // Pin 4 - kliknięcie
  pinMode(5, INPUT_PULLUP); // Pin 5 - flaga

  // Odwrócenie wyświetlacza o 180 stopni
  display.setRotation(2);

  // Wyczyszczenie ekranu
  display.clearDisplay();

  // Rysowanie siatki
  for (int i = 0; i < 17; i++) {
    display.drawFastVLine(i *6, 0,10*6+1, WHITE);                 //linie pionowe
  }
  for (int j = 0; j < 11; j++) {
    display.drawFastHLine(0, j * 6,  16*6+1, WHITE);              //linie poziome
  }
display.fillRect(0, 0, 7, 7, BLACK);   //// pierwsze aktywne pole
  // Wyświetlenie siatki




 placeMines();

    // Obliczenie liczby min w sąsiedztwie każdego pola
    calculateNumbers();


for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 16; j++) {
            Serial.print(t[j][i]); // Wyświetl wartość elementu tablicy
            Serial.print("\t"); // Dodaj tabulator po każdym elemencie
        }
        Serial.println(); // Przejdź do nowej linii po zakończeniu wiersza
    }

moje(113,19,0);

displayTwoDigitNumber(112, 30, miny);



 display.setCursor(112, 1);
    
    // Wyświetl znak zapytania na ekranie
    display.println('?');
  
  display.display();
}


void loop() {
// Sprawdzenie ruchu w górę
   if (millis() - lastMoveTime >= 250) {
    if (digitalRead(8) == LOW) {
      
      moveActiveArea(6, 0);
    } else if (digitalRead(7) == LOW) {
      
      moveActiveArea(0, -6);
    } else if (digitalRead(9) == LOW) {
      
      moveActiveArea(0, 6);
    } else if (digitalRead(10) == LOW) {
      
      moveActiveArea(-6, 0);
    }else if (digitalRead(4) == LOW) {
      if(t[activeAreaX/6][activeAreaY/6]<10)
      {
        t[activeAreaX/6][activeAreaY/6]+=10;


          if(t[activeAreaX/6][activeAreaY/6]==19)
          {
            display.clearDisplay(); // Wyczyść ekran
            display.setTextSize(2); // Ustaw rozmiar tekstu
            display.setTextColor(WHITE); // Ustaw kolor tekstu (biały)

            int x = 27; 
            int y = 20; 

        
            display.setCursor(x, y);

  
            display.println("BOOM!!!");
            display.display();

            delay(3000000);
            }
            
int            xx = activeAreaX/6;
int yy = activeAreaY/6;
int zz = t[xx][yy];
            displayOnesDigit(112,1,zz);

moje(113,19,1);













            
            /*
           
              }
               */
        delay(50);
        }  
    
    }else if (digitalRead(5) == LOW) {
       if(t[activeAreaX/6][activeAreaY/6]<10)
      {
        t[activeAreaX/6][activeAreaY/6]+=20;
        delay(50);
        moje(113,19,2);
        
        miny-=1;
        displayTwoDigitNumber(112, 30, miny);
        
        }  else if (t[activeAreaX/6][activeAreaY/6]>19)
        {
        t[activeAreaX/6][activeAreaY/6]-=20;
          moje(113,19,0);
          miny+=1;
          displayTwoDigitNumber(112, 30, miny);
          delay(50);
          }
        
 
    }
  }




/*
for (int i = 0; i < 16; i++) {
        for (int j = 0; j < 10; j++) {
            Serial.print(t[i][j]); // Wyświetl wartość elementu tablicy
            Serial.print("\t"); // Dodaj tabulator po każdym elemencie
        }
        Serial.println(); // Przejdź do nowej linii po zakończeniu wiersza
    }
*/



  
delay(50);
}

void moveActiveArea(int deltaX, int deltaY) {
  int xx = activeAreaX/6;
  int yy = activeAreaY/6;
  int zz = t[xx][yy];
   Serial.println(xx);
    Serial.println(yy);
  Serial.println(zz);
  int w = 0;
  if(zz < 10)
  {
    w=0;
    }
    else if (zz<20)
    {
      w=1;
      }
      else
      {
        w=2;
        }
  moje(activeAreaX,activeAreaY,w);
  // Clear previous active area
  
//Serial.println(activeAreaX);
activeAreaX += deltaX;
  activeAreaY += deltaY;
  activeAreaX = constrain(activeAreaX, 0, 90);
  activeAreaY = constrain(activeAreaY, 0, 54);
  // Draw new active area
  display.fillRect(activeAreaX, activeAreaY, 7, 7, BLACK);
  display.display();

xx = activeAreaX/6;
yy = activeAreaY/6;
zz = t[xx][yy];

if(zz < 10)
  {
    w=0;
    }
    else if (zz<20)
    {
      w=1;
      }
      else
      {
        w=2;
        }

moje(113,19,w);


displayOnesDigit(112,1,zz);




  
  lastMoveTime = millis();
















  
}


void moje(int x, int y, int w)
{

 display.drawRect(x, y, 7, 7, WHITE);
 display.fillRect(x+1, y+1, 5, 5, BLACK);

  if(w == 2)
  {
     display.fillRect(x+1, y+1, 1, 1, WHITE);
     display.fillRect(x+2, y+2, 1, 1, WHITE);
     display.fillRect(x+3, y+3, 1, 1, WHITE);
     display.fillRect(x+4, y+4, 1, 1, WHITE);
     display.fillRect(x+5, y+5, 1, 1, WHITE);
     display.fillRect(x+2, y+5, 1, 1, WHITE);
     display.fillRect(x+3, y+4, 1, 1, WHITE);
     display.fillRect(x+4, y+2, 1, 1, WHITE);
     display.fillRect(x+5, y+1, 1, 1, WHITE);
  }
  else if (w == 1)
  {
    display.drawRect(x+2, y+2, 3, 3, WHITE);
  }
 display.display();
}

void displayOnesDigit(int x, int y, int number) {
  display.fillRect(x, y, 10, 18, BLACK);
  if (number > 9 && number < 20) {
    int onesDigit = number % 10; // Cyfra jedności danej liczby
    
//     Ustaw rozmiar tekstu i kolor
    display.setTextSize(2); // Rozmiar tekstu
    display.setTextColor(WHITE); // Kolor tekstu
    
//     Ustaw kursor tekstu na zadanych współrzędnych
    display.setCursor(x, y);
    
    // Wyświetl cyfrę jedności na ekranie
    //display.println(String(onesDigit));


char buffer[1]; // Bufor na ciąg znaków
sprintf(buffer, "%d", onesDigit); // Formatuj liczbę do ciągu znaków
display.println(buffer); // Wyświetl bufor na ekranie OLED





    
  } else {
    // Ustaw rozmiar tekstu i kolor
    display.setTextSize(2); // Rozmiar tekstu
    display.setTextColor(WHITE); // Kolor tekstu
    
    // Ustaw kursor tekstu na zadanych współrzędnych
    display.setCursor(x, y);
    
    // Wyświetl znak zapytania na ekranie
    display.println('?');
   
  }



   display.display();
}

void displayTwoDigitNumber(int x, int y, int number) {
  // Sprawdź czy liczba jest dwucyfrowa (od 10 do 99)
display.fillRect(x, y, 10, 50, BLACK);

  
  if (number >= 10 && number <= 99) {
    // Podziel liczbę na cyfry dziesiątek i jedności
    int tens = number / 10;
    int ones = number % 10;





    
    // Ustaw rozmiar tekstu i kolor
    display.setTextSize(2); // Rozmiar tekstu
    display.setTextColor(WHITE); // Kolor tekstu

    // Wyświetl cyfrę dziesiątek na górze
    display.setCursor(x, y); // Ustaw kursor na pierwszej pozycji
char buffer[1]; // Bufor na ciąg znaków
sprintf(buffer, "%d", tens); // Formatuj liczbę do ciągu znaków
display.println(buffer); // Wyświetl bufor na ekranie OLED
    // Wyświetl cyfrę jedności poniżej
    display.setCursor(x, y + 20); // Ustaw kursor poniżej cyfry dziesiątek
    sprintf(buffer, "%d", ones);
  display.println(buffer); // Wyświetl bufor na ekranie OLED
  }
  else
  {
    
    int tens = 0; 
    int ones = number ;





    
    // Ustaw rozmiar tekstu i kolor
    display.setTextSize(2); // Rozmiar tekstu
    display.setTextColor(WHITE); // Kolor tekstu

    // Wyświetl cyfrę dziesiątek na górze
    display.setCursor(x, y); // Ustaw kursor na pierwszej pozycji
char buffer[3]; // Bufor na ciąg znaków
sprintf(buffer, "%d", tens); // Formatuj liczbę do ciągu znaków
display.println(buffer); // Wyświetl bufor na ekranie OLED
    // Wyświetl cyfrę jedności poniżej
    display.setCursor(x, y + 20); // Ustaw kursor poniżej cyfry dziesiątek
    sprintf(buffer, "%d", ones);
  display.println(buffer); // Wyświetl bufor na ekranie OLED
    
    }

    display.display();
}
Youtube
Tagi
arduino saper oled przyciski gra