I've incorporated everyone's suggestions and thought I would post the
resulting smaller code. I refactored init-cells away and just pass in
an init or new function to calc-state to reuse the for loop. I made
determine-next-state a little more verbose than technically necessary
to make conway's rules more obvious to me. The refs "cells" and
"running" don't feel very functional but I don't know how to get rid
of them.

(import '(javax.swing JFrame JPanel JButton)
        '(java.awt BorderLayout Dimension Color)
        '(java.awt.event ActionListener))

(def cells (ref {}))

(def running (ref false))

(defn determine-initial-state [x y]
  (= 0 (rand-int 5)))

(defn determine-new-state [x y]
  (let [neighbor-count
         (count (for [dx [-1 0 1] dy [-1 0 1]
                  :when (and (not (= 0 dx dy))
                             (cells [(+ x dx) (+ y dy)]))]
                  :alive))]
    (if (cells [x y])
        (< 1 neighbor-count 4)
        (= neighbor-count 3))))

(defn calc-state [cell-state]
  (dosync
    (ref-set cells
      (reduce conj {}
        (for [x (range 32) y (range 48)]
          [[x y] (cell-state x y)])))))

(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))))

(defn toggle-thread [panel button]
    (if @running

      (do (dosync (ref-set running false))
          (. button (setText "Start")))

      (do (dosync (ref-set running true))
          (. button (setText "Stop"))
          (. (Thread.
                 #(loop []
                    (calc-state determine-new-state)
                    (. panel repaint)
                    (Thread/sleep 100)
                    (if @running (recur))))
                 start))))

(defn main[]

    (calc-state determine-initial-state)

    (let [f (JFrame.)
          b (JButton. "Start")
          panel (proxy [JPanel] [] (paint [graphics] (paint-cells
graphics)))]

        (doto f
            (. setLayout (BorderLayout.))
            (. setLocation 100 100)
            (. setPreferredSize (Dimension. 320 540))
            (. add b BorderLayout/SOUTH)
            (. add panel BorderLayout/CENTER)
            (. setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
            (. pack)
            (. setVisible true))

        (. b addActionListener
           (proxy [ActionListener] []
                (actionPerformed [evt] (toggle-thread panel b))))))

(main)


Thanks for everyone. Very good learning experience.
Larry
http://lpsherrill.blogspot.com


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to