> I've written a small example of Conway's Game of Life using Clojure
> and Swing. Comments/critiques are welcome.
Interesting program!
(for [x (range 32) y (range 48)]
(ref-set cells
(assoc (deref cells) [x y] (= 0 (rand-int 5)))))
While you can use ref-set this way, it's much more concise to use alter:
(for [x (range 32) y (range 48)]
(alter cells assoc [x y] (= 0 (rand-int 5))))
You should use this in calc-state as well.
Also, the paint-cells function is called only for side-effects. Instead
of using dorun+map, you should use doseq:
(defn paint-cells [graphics]
(doseq [cell @cells]
(let [x (first (first cell))
y (second (first cell))
state (second cell)]
(doto graphics
(. setColor (if state Color/RED Color/WHITE))
(. fillRect (* 10 x) (* 10 y) 10 10)))))
I'm not sure if making "running" a ref makes sense here. Do you need to
coordinate change in it across threads, or will the change only happen
in one thread? If it's the former, using a thread-local var with
"binding" is probably a better choice.
Also, instead of calling (deref cells), you can use @cells for short.
-Phil
The paint-cells function can be shorted by using doseq and destructuring.
(defn paint-cells [graphics]
(doseq [[[x, y] state] @cells]
(doto graphics
(.setColor (if state Color/RED Color/WHITE))
(.fillRect (* 10 x) (* 10 y) 10 10))))
--
R. Mark Volkmann
Object Computing, Inc.
Instead of all the uses of (- x 1), (- y 1), (+ x 1) and (+ y 1), I
think it's more idiomatic to use (dec x), (dec y), (inc x) and (inc
y).
> I've written a small example of Conway's Game of Life using Clojure
> and Swing. Comments/critiques are welcome.
Very nice example!
Here's a more compact determine-new-state:
(defn determine-new-state [x y]
(let [count (reduce + (for [dx [-1 0 1] dy [-1 0 1]]
(if (cells [(+ x dx) (+ y dy)]) 1 0)))]
(or (and (cells [x y]) (> count 2) (< count 5))
(= count 3))))
I'm guessing someone can make the reduce even tighter.
I considered using :when (not (and (zero? dx) (zero? dy))) in the for
expression, but it seemed simpler to account for the extra count when
(cells [x y]) is true in the new state expression down below.
--Steve
Thanks everyone for the suggestions. Very helpful.
- Afficher le texte des messages précédents -
> smime.p7s
> 3KViewDownload
- Afficher le texte des messages précédents -
> (defn determine-new-state [x y]
> (let [count (reduce + (for [dx [-1 0 1] dy [-1 0 1]]
> (if (cells [(+ x dx) (+ y dy)]) 1 0)))]
> (or (and (cells [x y]) (> count 2) (< count 5))
> (= count 3))))
>
> I'm guessing someone can make the reduce even tighter.
Here's another shot at it:
(defn determine-new-state [x y]
(let [nearby [-1 0 1]
neighborhood (for [dx nearby dy nearby]
(cells [(+ x dx) (+ y dy)]))
alive (count (filter identity neighborhood))]
(if (cells [x y])
(< 2 alive 5)
(= alive 3))))
--Steve
Nice!
And for more golfing fun:
(defn calc-state []
(dosync
(ref-set cells
(reduce conj {}
(for [x (range 32) y (range 48)]
[[x y] (determine-new-state x y)])))))
--Steve