第9章 対話プログラム #7

9.9 練習問題

  1. ライフゲームは、世代ごとに画面全体をクリアするので、動かす環境によっては、動きがちらつくかもしれない。それを防止するために、状態が変わったところだけ表示し直すようライフゲームを変更せよ。

うーん。リモートターミナルとかだとちらつくかもしれないかな。

@@ -1,5 +1,6 @@
-module NineSeven where
+module NineNineThree where
 
+import List
 import NineFive
 
 width :: Int
@@ -13,9 +14,12 @@
 glider :: Board
 glider =  [(4,2), (2,3), (4,3), (3,4), (4,4)]
 
-showcells   :: Board -> IO ()
-showcells b =  seqn [writeat p "O" | p <- b]
+clearcells    :: [Pos] -> IO ()
+clearcells xs =  seqn [writeat p " " | p <- xs]
 
+writecells    :: [Pos] -> IO ()
+writecells xs =  seqn [writeat p "O" | p <- xs]
+
 isAlive     :: Board -> Pos -> Bool
 isAlive b p =  elem p b
 
@@ -36,6 +40,9 @@
 survivors   :: Board -> [Pos]
 survivors b =  [p | p <- b, elem (liveneighbs b p) [2,3]]
 
+deaths   :: Board -> [Pos]
+deaths b =  [p | p <- b, not $ elem p (survivors b)]
+
 births   :: Board -> [Pos]
 births b =  [p | p <- rmdups (concat (map neighbs b)),
                  isEmpty b p,
@@ -50,9 +57,14 @@
 
 life   :: Board -> IO ()
 life b =  do cls
-             showcells b
-             wait 5000
-             life (nextgen b)
+             writecells b
+             wait 5000
+             life' b
 
+life'   :: Board -> IO ()
+life' b =  do writecells (births b)
+              clearcells (deaths b)
+              wait 5000
+              life' (nextgen b)
+
 wait   :: Int -> IO ()
 wait n =  seqn [return () | _ <- [1..n]]

というわけで、cls >>= showcells のところを writecells >>= clearcells としてみた。