Come primo esperimento per l' Arduino UNO R3 con display LCD TFT da 2.4" Touch Screen che ho acquistato qualche settimana fa, ho deciso di provare a realizzare una versione del famoso "gioco della vita" sviluppato dal matematico inglese John Conway sul finire degli anni '60.
Il tutto si sviluppa in un "mondo" bidimensionale formato da celle con le seguenti regole:
- ogni cella viva con meno di due vicini muore, per isolamento
- una cella vive se ha due o tre vicini vivi attorno
- ogni cella viva muore se ha più di tre vicini attorno, per sovraffollamento
- ogni cella vuota genera una cella viva se ci sono tre celle vive attorno
Su queste regole matematiche ho sviluppato un programma "didattico" che simula il mondo in un array bidimensionale, su celle di 10×10 pixel cadauna che partono con una vita massima di 100:
#define CELLSIZE 10 #define CELL_LIFE 100 #define WORLD_X MAX_X/CELLSIZE #define WORLD_Y MAX_Y/CELLSIZE uint8_t worldArray[WORLD_X][WORLD_Y];
Su questo "mondo" virtuale eseguo un controllo cella per cella per calcolare il numero di vicini:
int8_t checkMatrix[16] { 1,1, 1,0, 0,1, -1,-1, -1,0, 0,-1, 1,-1, -1,1, }; uint8_t cellNeighbours(uint16_t x, uint16_t y) { // Return the number of neighbours for the cell @ x,y uint8_t c,r=0; int16_t rx,ry; for(c=0;c<16;c+=2) { rx = x + checkMatrix[c]; ry = y + checkMatrix[c+1]; if(rx < 0) rx = MAX_X; if(ry < 0) ry = MAX_Y; if(rx > MAX_X) rx=0; if(ry > MAX_Y) ry=0; if(worldArray[rx][ry] > 0) r++; } return r; } void updateWorld() { uint8_t x,y,c; for(x=0;x<WORLD_X;x++) { for(y=0;y<WORLD_Y;y++) { c = cellNeighbours(x,y); if(c == 3) worldArray[x][y] = CELL_LIFE; // Born == 3 if(worldArray[x][y] > 0) { worldArray[x][y]--; if(worldArray[x][y] > 20) { if((c > 1)&(c < 4)) worldArray[x][y]++; // Remain alive // Live cells are WHITE drawCell(x,y,WHITE); } else if(worldArray[x][y] < 20) { // When cell is going to die, change color to RED drawCell(x,y,RED); } } } } }
La funzione updateWorld() viene eseguita ad ogni ciclo di vita (ogni nuova cellula nasce con 100 cicli di vita, ovviamente modificabile a piacere, per rendere comunque più "movimentato" il gioco).
Il mondo è rappresentato da una griglia ed ho implementato un controllo per renderlo "rotondo": le celle che debordano sono reimpostate sul lato opposto della griglia, come se fosse una sfera.
Tutte le funzioni grafiche, dal disegno del mondo alle celle, sono state realizzare sfruttando la libreria GFX sviluppata da Adafruit. La sintassi delle primitive la trovate qui: https://learn.adafruit.com/adafruit-gfx-graphics-library/graphics-primitives
Inoltre, in questo caso, posso sfruttare il vantaggio di avere uno schermo touchscreen per inizializzare il "mondo" con le celle desiderate.
Potete trovare il codice e le librerie necessarie alla sua compilazione a questo link: Arduino_Life.tar.gz