// Librerie dichiarate
#include <Adafruit_NeoPixel.h>
#include <math.h>
// Definizioni per la matrice di LED
#define NUM_RIGHE 16
#define NUM_COL 16
#define NUM_LED (NUM_RIGHE * NUM_COL)
#define PIN_LED 5
// Definizioni per il joystick
#define PIN_VERT A0
#define PIN_ORIZ A1
#define PIN_SEL 2
// Definizioni per il potenziometro
#define PIN_POTENZ A3
// Segmento di codice utilizzato per far funzionare la libreria "Adafruit_NeoPixel"
Adafruit_NeoPixel striscia = Adafruit_NeoPixel(NUM_LED, PIN_LED, NEO_GRB + NEO_KHZ800);
// Definisci una struttura per rappresentare una nave
struct Nave
{
const char* tipo; // Nome del struct ("tipo")
int lung; // Lunghezza della nave
int pos[4][2]; // Posizioni delle celle occupate dalla nave di massimo 4 caselle.
};
// Inizializza le navi con le loro lunghezze e posizioni iniziali
Nave corazz = {"Corazzata", 4, {{0,0}, {0,1}, {0,2}, {0,3}}};
Nave sottom[3] =
{
{"Sottomarino", 3, {{0,0}, {0,1}, {0,2}}},
{"Sottomarino", 3, {{0,0}, {0,1}, {0,2}}},
{"Sottomarino", 3, {{0,0}, {0,1}, {0,2}}}
};
Nave corv[3] =
{
{"Corvetta", 2, {{0,0}, {0,1}}},
{"Corvetta", 2, {{0,0}, {0,1}}},
{"Corvetta", 2, {{0,0}, {0,1}}}
};
Nave lanc[2] =
{
{"Lancia", 1, {{0,0}}},
{"Lancia", 1, {{0,0}}}
};
// Array delle navi
Nave* navi[] = {&corazz, &sottom[0], &sottom[1], &sottom[2], &corv[0], &corv[1], &corv[2], &lanc[0], &lanc[1]};
int naveCorr = 0; // Indice della nave corrente da posizionare
// Variabile per la posizione corrente del joystick
int joystick_x = 0;
int joystick_y = 0;
// Variabile per l'angolo di rotazione, utilizzato per muovere la nave
bool verticale = true;
// Array per tenere traccia delle celle occupate
bool celle[NUM_RIGHE][NUM_COL] = {false};
void setup()
{
striscia.begin(); // Inizializza la striscia LED
striscia.show(); // Inizializza tutti i pixel a 'off'
// Imposta i pin del joystick
pinMode(PIN_SEL, INPUT_PULLUP); // Pin di selezione con pull-up interno
// Accendi tutti i LED di colore blu
for (int i = 0; i < NUM_LED; i++)
{
striscia.setPixelColor(i, striscia.Color(66, 215, 245)); // Coloro i LED in blu
}
striscia.show(); // Aggiorna la striscia per accendere tutti i LED
// Trova la prima posizione libera per iniziare
posizione_libera(); // Chiamo la funzione posizione_libera
}
void loop()
{
// Legge il valore del joystick per la posizione
int valVert = analogRead(PIN_VERT); // Legge il valore verticale
int valOriz = analogRead(PIN_ORIZ); // Legge il valore orizzontale
// Legge il valore del potenziometro
int valPot = analogRead(PIN_POTENZ); // Legge il valore del potenziometro
// Aggiorna la posizione corrente del joystick
if (valVert < 400)
{
joystick_y = max(joystick_y - 1, 0); // Muovo il joystick verso l'alto
}
else if (valVert > 600)
{
joystick_y = min(joystick_y + 1, NUM_RIGHE - 1); // Muovo il joystick verso il basso
}
if (valOriz < 400)
{
joystick_x = max(joystick_x - 1, 0); // Muovo il joystick a sinistra
}
else if (valOriz > 600)
{
joystick_x = min(joystick_x + 1, NUM_COL - 1); // Muovo il joystick a destra
}
// Aggiorna l'orientamento della nave in base al potenziometro
verticale = valPot < 512;
// Mostra la nave corrente alla posizione corrente
output_nave(); // Chiamo la funzione output_nave
// Se il pulsante centrale del joystick è premuto, conferma la posizione della nave
if (digitalRead(PIN_SEL) == LOW)
{
confermo(); // Chiamo la funzione confermo
delay(500); // Delay/ritardo di 500 ms
}
delay(100); // Delay/ritardo di 100 ms
}
// Inizio funzione "output_nave"
void output_nave()
{
// Spegni tutti i LED precendenti quando si muove il joystick
for (int i = 0; i < NUM_LED; i++)
{
striscia.setPixelColor(i, striscia.Color(66, 215, 245)); // Rimetto il colore blu visto che muovo il joystick
}
// Mostra tutte le navi posizionate
for (int n = 0; n < naveCorr; n++)
{
Nave* nave = navi[n];
for (int i = 0; i < nave->lung; i++)
{
int x = nave->pos[i][0];
int y = nave->pos[i][1];
int indiceLED = y * NUM_COL + x;
striscia.setPixelColor(indiceLED, striscia.Color(255, 0, 0)); // Colore rosso per le navi posizionate
}
}
// Mostra la nave corrente alla posizione corrente
Nave* nave = navi[naveCorr];
for (int i = 0; i < nave->lung; i++)
{
int x = verticale ? joystick_x : joystick_x + i;
int y = verticale ? joystick_y + i : joystick_y;
if (x >= NUM_COL || y >= NUM_RIGHE || celle[y][x]) break; // Evita di uscire dai limiti della matrice e sovrapposizioni
int indiceLED = y * NUM_COL + x;
striscia.setPixelColor(indiceLED, striscia.Color(139, 69, 19)); // Colore marrone per la nave corrente
}
striscia.show(); // Aggiorna la striscia per mostrare la nave
}
void confermo()
{
// Verifica se la posizione corrente è libera
Nave* nave = navi[naveCorr];
bool posLibera = true;
for (int i = 0; i < nave->lung; i++)
{
int x = verticale ? joystick_x : joystick_x + i;
int y = verticale ? joystick_y + i : joystick_y;
if (x >= NUM_COL || y >= NUM_RIGHE || celle[y][x])
{
posLibera = false;
break;
}
}
// Se la posizione è libera, salva la posizione della nave corrente
if (posLibera) {
for (int i = 0; i < nave->lung; i++)
{
int x = verticale ? joystick_x : joystick_x + i;
int y = verticale ? joystick_y + i : joystick_y;
nave->pos[i][0] = x;
nave->pos[i][1] = y;
celle[y][x] = true; // Segna la cella come occupata
}
naveCorr++; // Passa alla nave successiva
if (naveCorr >= sizeof(navi) / sizeof(navi[0]))
{
naveCorr = 0; // Ricomincia dall'inizio se tutte le navi sono state posizionate
}
posizione_libera(); // Trova la prossima posizione libera
}
}
void posizione_libera() {
// Trova la prima posizione libera nella matrice
for (int y = 0; y < NUM_RIGHE; y++)
{
for (int x = 0; x < NUM_COL; x++)
{
if (!celle[y][x])
{
joystick_x = x;
joystick_y = y;
return;
}
}
}
}