Bene, un paio di idee. Non sono un esperto di FP, ma ...
È abbastanza chiaro che dovremmo avere un tipo Board
che rappresenta uno stato di gioco. La base dell'implementazione dovrebbe essere una funzione evolve
di tipo evolve :: Board -> Board
; nel senso che produce un Board
dall'applicazione delle regole del gioco a un Board
.
Come dovremmo implementare evolve
? Un Board
dovrebbe probabilmente essere una matrice n x m di Cell
s. Potremmo implementare una funzione cellEvolve
di tipo cellEvolve :: Cell -> [Cell] -> Cell
che ha dato un Cell
e il suo vicino Cell
s calcola lo stato Cell
nella successiva iterazione.
Dovremmo anche implementare una funzione getCellNeighbors
che estrae i vicini di Cell
s da un Board
. Non sono completamente sicuro della firma di questo metodo; a seconda di come implementare Cell
e Board
potresti avere per esempio getCellNeighbors :: Board -> CoordElem -> CoordElem -> [Cell]
, che ha dato una tavola e due coordinate ( CoordElem
sarebbe il tipo utilizzato per indicizzare le posizioni in Board
), ti dà un elenco di lunghezza variabile dei vicini (non tutte le celle nella scheda hanno lo stesso numero di vicini di casa- gli angoli hanno 3 vicini, i bordi 5 e tutti gli altri, 8).
evolve
può quindi essere implementato combinando cellEvolve
e getCellNeighbors
per tutte le celle nella scheda, ancora una volta l'implementazione esatta dipenderà da come si implementa Board
e Cell
, ma dovrebbe essere qualcosa di simile a "per tutte le celle nella scheda corrente, prendi i loro vicini e usale per calcolare la cella corrispondente della nuova scheda". Ciò dovrebbe essere possibile fare con un'applicazione generica di quelle funzioni su tutta la scheda usando una "funzione di cella della mappa su scheda" .
Altri pensieri:
-
Dovresti davvero implementare cellEvolve
in modo che assuma come parametro un tipo GameRules
che codifica le regole del gioco, ad esempio un elenco di tuple (State,[(State,NumberOfNeighbors)],State)
che dice per un dato stato e il numero dei vicini in ogni stato, che dovrebbe essere lo stato nella prossima iterazione. La firma di cellEvolve
potrebbe quindi essere cellEvolve :: GameRules -> Cell -> [Cell] -> Cell
-
Questo ti porta logicamente a fare di evolve :: Board -> Board
di trasformarsi in evolve :: GameRules -> Board -> Board
, in modo che tu possa usare evolve
invariato con diverso GameRules
, ma potresti fare un ulteriore passo avanti e rendere cellEvolve
pluggable invece di GameRules
.
-
Giocando con getCellNeighbors
potresti anche rendere evolve
generico rispetto alla topologia di Board
- potresti avere getCellNeighbors
che avvolge i bordi di ciascuna scheda, le schede 3d, ecc.