Esporremo brevemente come creare un’applicazione iOS per il Gioco della Vita, un automa cellulare ideato dal matematico britannico John Horton Conway, utilizzando Swift e SwiftUI.
Struttura del codice
Il codice è suddiviso in tre parti principali:
- La classe
GameOfLife
, che gestisce la logica del gioco. - La vista
GridView
, che visualizza la griglia del gioco. - La vista
ContentView
, che contiene i controlli del gioco e includeGridView
.
1. La Classe GameOfLife
La classe GameOfLife
si occupa della logica e dello stato del gioco. Utilizza l’annotazione @Published
per segnalare a SwiftUI quando determinate proprietà cambiano, provocando il re-rendering dell’interfaccia utente.
- Inizializzazione: Genera una griglia di dimensioni specificate, con ogni cellula settata in modo casuale a vivente o morta.
- toggleCell(x: Int, y: Int): Cambia lo stato di una cellula specifica (viva diventa morta, morta diventa viva).
- startOrStop(): Inizia o ferma l’evoluzione del gioco.
- reset(): Ferma il gioco e genera una nuova griglia casuale.
- nextGeneration(): Calcola la prossima generazione della griglia in base alle regole del Gioco della Vita.
- aliveNeighbours(x: Int, y: Int): Conta i vicini vivi di una determinata cellula.
2. La Vista GridView
Questa vista visualizza la griglia del gioco. Utilizza un VStack
di HStacks
per creare la griglia, con un rettangolo per ogni cellula. Il colore del rettangolo dipende dallo stato della cellula (nero per vivente, bianco per morto). Un tap su un rettangolo inverte lo stato della cellula corrispondente.
3. La Vista ContentView
ContentView
è la vista principale dell’app. Contiene una GridView
e due pulsanti per controllare il gioco: uno per avviare/fermare l’evoluzione del gioco e l’altro per resettare il gioco.
La Logica del Gioco della Vita
La logica del Gioco della Vita è implementata nel metodo nextGeneration()
della classe GameOfLife
. Le regole del gioco sono le seguenti:
- Una cellula viva con meno di due vicini vivi muore.
- Una cellula viva con due o tre vicini vivi sopravvive.
- Una cellula viva con più di tre vicini vivi muore.
- Una cellula morta con esattamente tre vicini vivi diventa una cellula viva.
func nextGeneration() {
var newGrid = grid
for x in 0..<grid.count {
for y in 0..<grid[x].count {
let aliveNeighbours = self.aliveNeighbours(x: x, y: y)
if grid[x][y] {
if aliveNeighbours < 2 || aliveNeighbours > 3 {
newGrid[x][y] = false
}
} else if aliveNeighbours == 3 {
newGrid[x][y] = true
}
}
}
grid = newGrid
}
Queste regole vengono applicate simultaneamente a tutte le cellule della griglia per calcolare la prossima generazione.