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.