Skip to content

Instantly share code, notes, and snippets.

@prasincs
Created July 4, 2010 20:31
Show Gist options
  • Save prasincs/463729 to your computer and use it in GitHub Desktop.
Save prasincs/463729 to your computer and use it in GitHub Desktop.
; A snake program adapted from Stewart Halloway's Programming Clojure
; Author: Prasanna Gautam
(ns reader.snake
(:import (java.awt Color Dimension)
(javax.swing JPanel JFrame Timer JOptionPane JLabel)
(java.awt.event ActionListener KeyListener))
(:use clojure.contrib.import-static [clojure.contrib.seq-utils :only (includes?)]))
(import-static java.awt.event.KeyEvent VK_LEFT VK_RIGHT VK_UP VK_DOWN)
(def width 75)
(def height 50)
(def point-size 10)
(def board-width (* width point-size))
(def board-height (* height point-size))
(def turn-millis 100)
(def board-color (Color. 0 0 0))
(def win-length 12)
(def dirs {VK_LEFT [-1 0]
VK_RIGHT [1 0]
VK_UP [0 -1]
VK_DOWN [0 1]})
(defn add-points [& pts]
(vec (apply map + pts)))
(defn point-to-screen-rect [pt]
(map #(* point-size %)
[(pt 0) (pt 1) 1 1]))
(defn create-apple [] {
:location [(rand-int width) (rand-int height)]
:color (Color. 210 50 90)
:type :apple})
(defn create-board [] {:width board-width :height board-height :type :board})
(defn init-score [] {:win 0 :loss 0 :eaten 0 :type :score})
(defn inc-loss [score] (dosync ( alter score #(assoc % :loss (inc (:loss %))))))
(defn inc-eaten [score] (dosync ( alter score #(assoc % :eaten (inc (:eaten %))))))
(defn inc-win [score] (dosync ( alter score #(assoc % :win (inc (:win %))))))
(defn create-snake [] {:body (list [1 1])
:dir [1 0]
:type :snake
:color (Color. 15 160 70)})
(defn move [{:keys [body dir]
:as snake} & grow]
(assoc snake :body (cons (add-points (first body) dir)
(if grow body (butlast body)))))
(defn win? [{body :body}]
(>= (count body) win-length))
;(defn outside? [{[head & body] :body}] (let [x (head 0) y (head 1)] (println head x y) (or (>= x width) (<= x 0) (>= y height) (<= y 0))))
(defn outside? [{[head & body] :body}] (def x (head 0)) (def y (head 1)) (true? (or (> x width) (< x 0) (> y height) (< y 0))) )
(defn head-overlaps-body? [{[head & body] :body}]
(includes? body head))
(defn lose? [snake] (or ( head-overlaps-body? snake) ( outside? snake)))
(defn eats? [{[snake-head] :body} {apple :location}]
(= snake-head apple))
(defn turn [snake newdir]
(assoc snake :dir newdir))
(defn reset-game [snake apple]
(dosync (ref-set apple (create-apple))
(ref-set snake (create-snake)))
nil)
(defn update-direction [snake newdir]
(when newdir (dosync (alter snake turn newdir))))
(defn update-positions [snake apple]
(dosync
(if ( eats? @snake @apple)
(do (ref-set apple (create-apple))
(alter snake move :grow)
)
(alter snake move)))
nil)
(defn label-text [text] (JLabel. text))
(defn fill-point [g pt color]
(let [[x y width height] (point-to-screen-rect pt)]
(.setColor g color)
(.fillRect g x y width height)))
(defmulti paint (fn [g object & _] (:type object)))
(defmethod paint :apple [g {:keys [location color]}]
(fill-point g location color))
(defmethod paint :snake [g {:keys [body color]}]
(doseq [point body]
(fill-point g point color)))
(defmethod paint :score [g {:keys [win loss eaten]}]
(.drawString g (format "win: %d loss:%d eaten: %d" win loss eaten) 600 10)
)
(defmethod paint :board [g {:keys [width height]}]
(.setColor g board-color)
(.fillRect g 0 0 width height)
)
(defn game-panel [frame snake apple score]
(let [board (ref (create-board))]
(proxy [JPanel ActionListener KeyListener] []
(paintComponent [g]
(proxy-super paintComponent g)
(paint g @board)
(paint g @snake)
(paint g @apple)
(paint g @score)
)
(actionPerformed [e]
(update-positions snake apple)
(outside? @snake)
(when (lose? @snake )
(reset-game snake apple)
(inc-loss score)
(JOptionPane/showMessageDialog frame "You lose!"))
(when (win? @snake)
(reset-game snake apple)
(inc-win score)
(JOptionPane/showMessageDialog frame "You win!"))
(when (eats? @snake @apple)
(inc-eaten score))
(.repaint this))
(keyPressed [e]
(update-direction snake (dirs (.getKeyCode e))))
(getPreferredSize []
(Dimension. (* (inc width) point-size)
(* (inc height) point-size)))
(keyReleased [e])
(keyTyped [e]))))
(defn game []
(let [snake (ref (create-snake))
apple (ref (create-apple))
score (ref (init-score))
frame (JFrame. "Snake")
panel (game-panel frame snake apple score)
timer (Timer. turn-millis panel)]
(doto panel
(.setFocusable true)
(.addKeyListener panel))
(doto frame
(.add panel)
(.pack)
(.setVisible true))
(.start timer)
[snake, apple, timer]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment