(module snake lang/htdp-beginner-abbr
(require 2htdp/image)
(require 2htdp/universe)
(define BOARD-SIZE 10)
(define CELL-PIXELS 14) (define BOARD-WIDTH (* BOARD-SIZE CELL-PIXELS)) (define BOARD-HEIGHT BOARD-WIDTH)
(define HEAD (circle (/ CELL-PIXELS 2) "solid" "green"))
(define BODY (circle (/ CELL-PIXELS 2) "solid" "red"))
(define FOOD (circle (/ CELL-PIXELS 2) "solid" "blue"))
(define MTS (empty-scene BOARD-WIDTH BOARD-HEIGHT))
(define (fn-for-dir dir)
(cond [(string=? "U" dir) (...)]
[(string=? "D" dir) (...)]
[(string=? "L" dir) (...)]
[(string=? "R" dir) (...)]))
(define-struct cell (c r)) (define C1 (make-cell 0 0))
(define C2 (make-cell (- BOARD-SIZE 1) 0))
(define C3 (make-cell (/ BOARD-SIZE 2) (/ BOARD-SIZE 2)))
(define (fn-for-cell c)
(... (cell-c c)
(cell-r c)))
(define B1 (cons (make-cell 1 1) empty))
(define B2 (cons (make-cell 1 1)
(cons (make-cell 1 2)
(cons (make-cell 1 3) empty))))
(define (fn-for-body b)
(cond [(empty? (rest b)) (... (fn-for-cell (first b)))]
[else
(... (fn-for-cell (first b))
(fn-for-cell (first (rest b)))
(fn-for-body (rest b)))]))
(define-struct snake (dir head body))
(define S1 (make-snake "U" C1 B1))
(define S2 (make-snake "L" C2 B2))
(define S3 (make-snake "D" C3 B2))
(define (fn-for-snake s)
(... (fn-for-dir (snake-dir s))
(fn-for-cell (snake-head s))
(fn-for-body (snake-body s))))
(define-struct game (snake)) (define G1 (make-game S1))
(define G2 (make-game S2))
(define G3 (make-game S3))
(define (fn-for-game g)
(... (fn-for-snake (game-snake g))))
(define (main g)
(big-bang g
(on-tick tock-game .6)
(to-draw render-game)
(on-key handle-key)))
(check-expect (tock-game (make-game (make-snake "D" (make-cell 0 0) (cons (make-cell 1 0) empty))))
(make-game (make-snake "D" (make-cell 0 1) (cons (make-cell 0 0) empty))))
(define (tock-game g)
(make-game (next-snake (game-snake g))))
(check-expect (next-snake (make-snake "D" (make-cell 0 0) (cons (make-cell 1 0) empty)))
(make-snake "D" (make-cell 0 1) (cons (make-cell 0 0) empty)))
(check-expect (next-snake (make-snake "D" (make-cell 1 2) (cons (make-cell 1 1) empty)))
(make-snake "D" (make-cell 1 3) (cons (make-cell 1 2) empty)))
(check-expect (next-snake (make-snake "R" (make-cell 1 2) (cons (make-cell 1 1)
(cons (make-cell 1 0) empty))))
(make-snake "R" (make-cell 2 2) (cons (make-cell 1 2)
(cons (make-cell 1 1) empty))))
(define (next-snake s)
(make-snake (snake-dir s)
(next-cell (snake-dir s) (snake-head s))
(next-body (snake-head s) (snake-body s))))
(check-expect (next-body (make-cell 0 0) (cons (make-cell 1 0) empty))
(cons (make-cell 0 0) empty))
(check-expect (next-body (make-cell 1 2) (cons (make-cell 1 1) (cons (make-cell 1 0) empty)))
(cons (make-cell 1 2) (cons (make-cell 1 1) empty)))
(define (next-body h b)
(cons h (remove-last b)))
(check-expect (remove-last (cons (make-cell 0 0) empty)) empty)
(check-expect (remove-last (cons (make-cell 1 1)
(cons (make-cell 1 2)
(cons (make-cell 1 3) empty))))
(cons (make-cell 1 1)
(cons (make-cell 1 2) empty)))
(define (remove-last b)
(cond [(empty? (rest b)) empty]
[else
(cons (first b)
(remove-last (rest b)))]))
(check-expect (next-cell "U" (make-cell 1 2))
(make-cell 1 1))
(check-expect (next-cell "U" (make-cell 1 -1))
(make-cell 1 -1))
(check-expect (next-cell "D" (make-cell 1 2))
(make-cell 1 3))
(check-expect (next-cell "D" (make-cell 1 BOARD-SIZE))
(make-cell 1 BOARD-SIZE))
(check-expect (next-cell "L" (make-cell -1 2))
(make-cell -1 2))
(check-expect (next-cell "L" (make-cell 1 2))
(make-cell 0 2))
(check-expect (next-cell "R" (make-cell 1 2))
(make-cell 2 2))
(check-expect (next-cell "R" (make-cell BOARD-SIZE 2))
(make-cell BOARD-SIZE 2))
(define (fn-for-dir dir c)
(cond [(string=? "U" dir) (... (cell-c c)
(cell-r c))]
[(string=? "D" dir) (... (cell-c c)
(cell-r c))]
[(string=? "L" dir) (... (cell-c c)
(cell-r c))]
[(string=? "R" dir) (... (cell-c c)
(cell-r c))]))
(define (next-cell dir c)
(cond [(string=? dir "U") (make-cell (cell-c c) (max -1 (sub1 (cell-r c))))]
[(string=? dir "D") (make-cell (cell-c c) (min BOARD-SIZE (add1 (cell-r c))))]
[(string=? dir "L") (make-cell (max -1 (sub1 (cell-c c))) (cell-r c))]
[(string=? dir "R") (make-cell (min BOARD-SIZE (add1 (cell-c c))) (cell-r c))]))
(check-expect (render-game (make-game (make-snake "D" (make-cell 0 0) (cons (make-cell 0 1) empty))))
(place-in-cell HEAD (make-cell 0 0)
(place-in-cell BODY (make-cell 0 1) MTS)))
(define (render-game g)
(place-snake (game-snake g) MTS))
(check-expect (place-snake (make-snake "D" (make-cell 0 0) (cons (make-cell 0 1) empty)) MTS)
(place-in-cell HEAD (make-cell 0 0)
(place-in-cell BODY (make-cell 0 1) MTS)))
(define (place-snake s i)
(place-head (snake-head s)
(place-body (snake-body s) i)))
(check-expect (place-head (make-cell 0 0) MTS)
(place-in-cell HEAD (make-cell 0 0) MTS))
(define (place-head c i)
(place-in-cell HEAD c i))
(check-expect (place-body (cons (make-cell 0 1) empty) MTS)
(place-in-cell BODY (make-cell 0 1) MTS))
(check-expect (place-body (cons (make-cell 0 1)
(cons (make-cell 1 1)
(cons (make-cell 1 2) empty)))
MTS)
(place-in-cell BODY (make-cell 0 1)
(place-in-cell BODY (make-cell 1 1)
(place-in-cell BODY (make-cell 1 2) MTS))))
(define (place-body b i)
(cond [(empty? (rest b)) (place-in-cell BODY (first b) i)]
[else
(place-in-cell BODY
(first b)
(place-body (rest b) i))]))
(check-expect (place-in-cell HEAD (make-cell 5 6) MTS)
(place-image HEAD
(* 5.5 CELL-PIXELS)
(* 6.5 CELL-PIXELS)
MTS))
(define (place-in-cell img c scn)
(place-image img
(+ (* (cell-c c) CELL-PIXELS) (/ CELL-PIXELS 2))
(+ (* (cell-r c) CELL-PIXELS) (/ CELL-PIXELS 2))
scn))
(define THEAD (make-cell 4 5))
(define TBODY (cons (make-cell 5 5) (cons (make-cell 6 5) empty)))
(check-expect (handle-key (make-game (make-snake "L" THEAD TBODY)) "up")
(make-game (make-snake "U" THEAD TBODY)))
(check-expect (handle-key (make-game (make-snake "L" THEAD TBODY)) "down")
(make-game (make-snake "D" THEAD TBODY)))
(check-expect (handle-key (make-game (make-snake "R" THEAD TBODY)) "left")
(make-game (make-snake "L" THEAD TBODY)))
(check-expect (handle-key (make-game (make-snake "L" THEAD TBODY)) "right")
(make-game (make-snake "R" THEAD TBODY)))
(check-expect (handle-key (make-game (make-snake "L" THEAD TBODY)) "1")
(make-game (make-snake "L" THEAD TBODY)))
(define (handle-key g ke)
(cond [(key=? ke "up") (make-game (snake-up (game-snake g)))]
[(key=? ke "down") (make-game (snake-down (game-snake g)))]
[(key=? ke "left") (make-game (snake-left (game-snake g)))]
[(key=? ke "right") (make-game (snake-right (game-snake g)))]
[else g]))
(check-expect (snake-left (make-snake "U" THEAD TBODY)) (make-snake "L" THEAD TBODY))
(check-expect (snake-right (make-snake "U" THEAD TBODY)) (make-snake "R" THEAD TBODY))
(check-expect (snake-up (make-snake "D" THEAD TBODY)) (make-snake "U" THEAD TBODY))
(check-expect (snake-down (make-snake "U" THEAD TBODY)) (make-snake "D" THEAD TBODY))
(define (snake-left s) (make-snake "L" (snake-head s) (snake-body s)))
(define (snake-right s) (make-snake "R" (snake-head s) (snake-body s)))
(define (snake-up s) (make-snake "U" (snake-head s) (snake-body s)))
(define (snake-down s) (make-snake "D" (snake-head s) (snake-body s)))
(main (make-game (make-snake "R"
(make-cell 5 5)
(cons (make-cell 4 5)
(cons (make-cell 3 5)
empty)))))
)