Haskell生命游戏在发布时崩溃了

时间:2014-07-05 06:27:03

标签: haskell sdl frp conways-game-of-life elerea

我目前正试图在Haskell开发一个小小的Conway的生命游戏。我写了一个库 lifegame ,它可以管理单元格网格并计算其代数 (见github.com/qleguennec/lifegame.git)。 Generations是一个无限的列表。到目前为止,该库工作得很好,但缺乏文档。这是一个小型图书馆,它不应该如此难以进入。

现在,我在这里的目的是,我尝试使用 lifegame helm 一起实际向屏幕显示世代。这是我写的:

import FRP.Helm
import FRP.Helm.Graphics (Element(..))
import qualified FRP.Helm.Window as Window
import FRP.Helm.Animation (Frame, AnimationStatus(..), animate, absolute)
import FRP.Helm.Time (second, running, delta)
import FRP.Elerea.Simple

import Cell.Display (allGenFrames)
import LifeGame.Data.CellGrid (CellGrid(..), randCellGrid)

render :: Form -> (Int, Int) -> Element
render form (x, y) = collage x y $ [form]

main :: IO ()
main = do
  cg <- randCellGrid 50 50
  anim <- return . absolute $ allGenFrames cg (1 * second) 10
  engine <- startup defaultConfig

  run engine $ render <~ (animate anim running status) ~~ Window.dimensions engine

  where
    config = defaultConfig { windowTitle = "bats"
                           , windowDimensions = (500, 500)}
    status = effectful $ getLine >>= \i -> return $
      case i of
        "Pause" -> Pause
        "Stop" -> Stop
        "Cycle" -> Cycle

(来自:github.com/qleguennec/bats.git

计算的艰苦工作存在于animate running status&#34;,第20行。我真的不明白动画的第二个论点是什么。此外,我不确定提供无限的帧列表是合法的。

当我启动代码时,游戏冻结并在5分钟后停止。它似乎消耗所有内存和崩溃。现在,我明白所有这些都缺乏文档。我正在研究它。但是,作为婴儿Haskeller和婴儿FRP / SDL开发人员,我需要知道我是否以错误的方式做这件事(我可能会这样做)。 任何评论被接受和推荐。感谢。

1 个答案:

答案 0 :(得分:0)

我不知道我是否可以帮助你使用FRP - 我有很多图书馆并且我没有玩过很多图书馆 - 但是因为它的价值(因为你说你对Haskell很新), Conway的Life可以在没有FRP的情况下轻松编写,使用SDL渲染它很简单。

我发现最好将游戏表示为一组坐标对,而不是数组 - 这样,你就没有边界条件或世界包装问题。 (您可以从hashmapunordered-containers包中获得有效的严格或惰性集。

CA逻辑看起来像这样:

next cs = [i | (i,n) <- M.toList neighbors,
           n == 3 || (n == 2 && S.member i cs')]
 where
  cs'         = S.fromList cs
  moore (x,y) = tail $ liftM2 (,) [x, x+1, x-1] [y, y+1, y-1]
  neighbors   = M.fromListWith (+) $ map (,1) $ moore =<< cs

主程序循环如下所示:

run w cs = do
  drawCells w cs
  e <- pollEvent
  case e of
   KeyUp (Keysym SDLK_ESCAPE _ _) -> return ()
   KeyUp (Keysym SDLK_SPACE  _ _) -> pause w cs
   _                              -> run w $ next cs

drawCells w cs = do
  fillRect w (Just $ Rect 0 0 xres yres) (Pixel 0)
  c <- createRGBSurface [SWSurface] cellSz cellSz 32 0 0 0 0
  mapM_ (draw c . scale) cs
  SDL.flip w
 where
  rect (x,y) = Just $ Rect x y cellSz cellSz
  scale      = join (***) (* cellSz)
  draw c p   = do fillRect c Nothing $ Pixel 0xFFFFFF
                  blitSurface c Nothing w $ rect p

要查看完整的实施,大部分FRP会为您提供(通过鼠标编辑网格)等等,take a look at this.