patternModerate
Game of Life in Haskell
Viewed 0 times
lifegamehaskell
Problem
I wondering what people think of this game of life. I don't think it is working properly, but I am interesting in what people think of the general design.
module GameOfLife where
import Data.List
--Our types
type Coord = (Int, Int)
origin = (0, 0)
--Think of an image more like an infinite manifold
type DiscreteImage a = (Coord -> a)
--Cat is our "out of bounds"
data GamePiece = Alive | Dead | Cat
deriving(Show, Eq)
type GameBoard = DiscreteImage GamePiece
type TransitionRule = (GameBoard -> GamePiece)
under_population = make_population_transition Alive Dead (3)
birth = make_population_transition Dead Alive (==3)
--Order is not important. Only one transition applies per peice,
--the others operate like id
transition_rule :: TransitionRule
transition_rule image = foldl (\image f -> f image) image
[
under_population,
overcrowding,
birth
] origin
--return a new gameboard that applies the transition rule to every
--spot on the gameboard
step :: TransitionRule -> GameBoard -> GameBoard
step trans gb = trans . offset gb
--apply the tranisition rule n number of times
simulate :: Int -> TransitionRule -> GameBoard -> GameBoard
simulate count trans gb = foldl apply_step gb steps where
steps = replicate count (step trans)
apply_step gb s = s gb
--translate the image
offset :: DiscreteImage a -> Coord -> Coord -> a
offset image (offsetX, offsetY) (x, y) = image (offsetX + x, offsetY + y)
--make a square of coords
square_coords :: Int -> [Coord]
square_coords radius = [(x, y) | x DiscreteImage a -> [a]
punctured_neighborhood size image = map image $ filter (not . (==origin)) $ square_coords size
--a little test
main = do
let (width, height) = get_bounds test_list
let board1 = simulate 1 transition_rule test_board
putStr $ unlines [ unwords [ ppr_peice $ board1 (x, y) | x -1) && (x -1)
ppr_peice Dead = "O"
ppr_peice Alive = "X"
ppr_peice Cat = "C"Solution
Refactor's answer is excellent and captures most points. One thing in your code which sticks out is the overuse of
I think
is much clearer. Or this, which looks really strange:
You should write
if. E.g. considerget_bounds xs = if null xs
then (0, 0)
else (length xs, length $ head xs)I think
getBounds [] = (0,0)
getBounds xs = (length xs, length $ head xs)is much clearer. Or this, which looks really strange:
make_population_transition from to condition image | image origin == from =
if (condition . population_count) image
then replace image origin to
else image
make_population_transition from to test image | otherwise = imageYou should write
make_population_transition from to condition image
| image origin == from &&
(condition . population_count) image = replace image origin to
| otherwise = imageCode Snippets
get_bounds xs = if null xs
then (0, 0)
else (length xs, length $ head xs)getBounds [] = (0,0)
getBounds xs = (length xs, length $ head xs)make_population_transition from to condition image | image origin == from =
if (condition . population_count) image
then replace image origin to
else image
make_population_transition from to test image | otherwise = imagemake_population_transition from to condition image
| image origin == from &&
(condition . population_count) image = replace image origin to
| otherwise = imageContext
StackExchange Code Review Q#1204, answer score: 11
Revisions (0)
No revisions yet.