Skip to main content
fixed grammar & added beginner tag
Source Link
Stephen Rauch
  • 4.3k
  • 12
  • 24
  • 36

Thank you and apologises for any typos as I'm not a native English speaker.

Thank you and apologises for any typos as I'm not a native English speaker.

I'm a Clojure beginner and I implmenetedimplemented Game of life to learn how I should code things in Clojure.

I used ref to learn how to mangemanage state. Using ref although it seems to belike an overkill for this tiny program.

I already checked this answer, but I think I did this in a quite different way and need a different advisesadvice.

Thank you. (and I'm sorry and apologises for any typos as I'm not a goodnative English speaker if you have any inconveniences).

I'm a Clojure beginner and I implmeneted Game of life to learn how I should code things in Clojure.

I used ref to learn how to mange state. Using ref seems to be overkill for this tiny program.

I already checked this answer, but I think I did this in a quite different way and need different advises.

Thank you. (and I'm sorry I'm not a good English speaker if you have any inconveniences)

I'm a Clojure beginner and I implemented Game of life to learn how I should code things in Clojure.

I used ref to learn how to manage state although it seems like an overkill for this tiny program.

I already checked this answer, but I think I did this in a quite different way and need a different advice.

Thank you and apologises for any typos as I'm not a native English speaker.

Source Link

Clojure "Game of Life"

I'm a Clojure beginner and I implmeneted Game of life to learn how I should code things in Clojure.

(def state (ref [
    [false false false false false]
    [false false true  false false]
    [false false true  false false]
    [false false true  false false]
    [false false false false false]]))

(defn get-state [state x y]
  (nth (nth state y) x))

(defn count-true-neighbours [state x y]
  (let [size (count state)]
    (->>
      (for [p (range (- x 1) (+ x 2))
            q (range (- y 1) (+ y 2))
            :when (not (and (= x p) (= y q)))]
        [p q])
      (map (fn [coord]
        (let [[p q] coord]
          (if (or (< p 0) (>= p size) (< q 0) (>= q size))
            false
            (get-state state p q)))))
      (filter true?)
      (count))))

(defn next-state-of [state x y]
  (let [alive (get-state state x y)
        alive-neighbours (count-true-neighbours state x y)]
    (cond
      (and (not alive) (= alive-neighbours 3)) true
      (and alive (or (= alive-neighbours 2) (= alive-neighbours 3))) true
      :else false)))

(defn next-state [state]
  (let [size (count state)]
    (mapv
      (fn [row]
        (mapv
          #(next-state-of state %1 row)
          (range 0 size)))
      (range 0 size))))

(defn pretty-print [state]
  (let [size (count state)]
    (loop [i 0]
      (if (< i size)
        (do
          (println
            (->>
              (nth state i)
              (mapv #(if %1 "■ " "□ "))
              (reduce str)))
          (recur (inc i)))))))

(defn tick
  ([times] (tick 0 times))
  ([i times]
    (if (< i times)
      (do
        (dosync
          (println (str i ":"))
          (pretty-print @state)
          (ref-set state (next-state @state)))
        (recur (inc i) times))
      nil)))

(defn -main [& args]
  (tick 5))

I used ref to learn how to mange state. Using ref seems to be overkill for this tiny program.

As you see my code is terrible, but I couldn't improve this by myself.

I already checked this answer, but I think I did this in a quite different way and need different advises.

Thank you. (and I'm sorry I'm not a good English speaker if you have any inconveniences)