Created
November 26, 2011 11:57
-
-
Save rickardlindberg/1395519 to your computer and use it in GitHub Desktop.
My first complete implementation of game of life
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Control.Concurrent | |
import System.Console.ANSI | |
-- Logic | |
data Cell = Alive | Dead | |
deriving (Eq, Show) | |
type Neighbours = [Cell] | |
evolveCell :: (Cell, Int) -> Cell | |
evolveCell (Alive, 2) = Alive | |
evolveCell (Alive, 3) = Alive | |
evolveCell (Dead, 3) = Alive | |
evolveCell _ = Dead | |
evolveCells :: [(Cell, Neighbours)] -> [Cell] | |
evolveCells l = map evolveCell lCount | |
where | |
lCount = zip cells count | |
(cells, neighbours) = unzip l | |
count = map countAliveCells neighbours | |
countAliveCells = length . filter (== Alive) | |
-- Representation | |
data Board = Board { | |
boardWidth :: Int, | |
boardHeight :: Int, | |
boardCells :: [Cell] | |
} deriving (Show) | |
printBoard :: Board -> String | |
printBoard (Board width height cells) = printRows cells | |
where | |
printRows [] = "" | |
printRows xs = map cellChar (take width xs) ++ "\n" ++ printRows (drop width xs) | |
cellChar Alive = '0' | |
cellChar Dead = '~' | |
boardToCellNeighbourList :: Board -> [(Cell, Neighbours)] | |
boardToCellNeighbourList b = map getCellAndNeighbours [(x, y) | y <- [0..(boardHeight b)-1], x <- [0..(boardWidth b)-1]] | |
where | |
getCellAndNeighbours pos = (cellAt b pos, neighboursTo pos b) | |
cellAt (Board width height cells) (x, y) | |
| x < 0 = cellAt (Board width height cells) (width+x, y) | |
| x >= width = cellAt (Board width height cells) (x-width, y) | |
| y < 0 = cellAt (Board width height cells) (x, height+y) | |
| y >= height = cellAt (Board width height cells) (x, y-height) | |
| otherwise = head $ drop (width * y + x) cells | |
neighboursTo pos b = map (cellAt b) (neighboursPos pos) | |
neighboursPos (x, y) = map (\(x', y') -> (x+x', y+y')) [ | |
(-1, -1), (0, -1), (1, -1), | |
(-1, 0), (1, 0), | |
(-1, 1), (0, 1), (1, 1) | |
] | |
evolveBoard :: Board -> Board | |
evolveBoard (Board width height cells) = Board width height newCells | |
where | |
newCells = evolveCells $ boardToCellNeighbourList (Board width height cells) | |
boardFromString :: [String] -> Board | |
boardFromString lines = Board width height cells | |
where | |
width = length $ head lines | |
height = length lines | |
cells = map toCell (concat lines) | |
toCell '-' = Dead | |
toCell '0' = Alive | |
-- Glue | |
main = loop $ boardFromString [ | |
"------------------------------", | |
"---00-----------------0-------", | |
"---000---------------000------", | |
"----------------------0-------", | |
"------------------------------", | |
"--------------00--------------", | |
"--------------0-0-------------", | |
"--------------0---------------", | |
"---------------------000------", | |
"------------------------------", | |
"------------------------------", | |
"----0-------------------------" | |
] | |
where loop board = do | |
putStr (printBoard board) | |
threadDelay 100000 | |
scrollPageDown (boardHeight board) | |
loop (evolveBoard board) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment