Game of Life

生命游戏

游戏规则:

The game of life is a cellular automaton devised by mathematician John Conway.

The 'board' consists of both live (#) and dead ( ) cells. Each cell interacts with its eight neighbours (horizontal, vertical, > diagonal), and its next state is dependent on the following rules:

1) Any live cell with fewer than two live neighbours dies, as if caused by under-population.
2) Any live cell with two or three live neighbours lives on to the next generation.
3) Any live cell with more than three live neighbours dies, as if by overcrowding.
4) Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

代码


(defn test [chessboard]
    (let [nrow (count chessboard)
          ncol (count (nth chessboard 0))
          ; 根据下标获取元素
          get-coord (fn [x y] (nth (nth chessboard x) y))
          ; 相邻生命的坐标
          coords (fn [x y] (filter 
                              #(let [row-num (first %)
                                     col-num (last %)] 
                                ; 过滤越界的坐标
                                (and (>= row-num 0) 
                                     (>= col-num 0)
                                     (< row-num nrow) 
                                     (< col-num ncol)))
                              ; 当前坐标周围的八个坐标(笛卡尔积)
                              (for [xx [(dec x) x (inc x)]
                                    yy [(dec y) y (inc y)] 
                                        :when (not (and (= xx x) (= yy y)))]
                                    [xx yy])))
          ; 相邻的生命
          neighbors (fn [x y] (map (partial apply get-coord) (coords x y)))
          ; 相邻生命状态是live(#)的个数
          nlive (fn [x y] (count (filter #(= \# %) (neighbors x y))))
          ; 下一轮的状态(一维数组)
          result (for [x (range 0 nrow)
                       y (range 0 ncol)] 
                    (let [element (get-coord x y)
                          live-num (nlive x y)]
                        (if (= \# element)
                            ; live状态的生命周围如果有2个或3个生命是live的,则下轮继续存活,否则死亡
                            (if (or (< live-num 2) (> live-num 3)) \space \#)
                            ; die状态的生命周围如果有刚好3个生命是live的,则下轮复活,否则死亡
                            (if (= live-num 3) \# \space))))]
          ; 把结果转成4Clojure需要的形式
          (map (partial apply str) (partition ncol result))))

(defn print-chessboard [chessboard]
    (println "-----------------------")
    (print (str (clojure.string/join "|\n" chessboard) "|\n")
    (println "-----------------------")))

(def a ["           "  
        "   #####   "
        "           "
        "   ######  "
        "           "
        "           "])
; 迭代多次,并打印每次的生命状态
(defn run [n chessboard sleep-time]
    (loop [i 0
           tmp chessboard]
        (if (> i n)
            (println "over")
            (do
                (println "第" i "次进化")
                ; 防止打印过快
                (Thread/sleep sleep-time)
                (print-chessboard tmp)
                (recur (inc i) (test tmp))))))
; 迭代40次,间隔300ms
(run 40 a 300)

你可能感兴趣的:(life,clojure,game,of,生命游戏)