;; **************************************** ;; * Csu 211 : 2/7/2008 ;; * Lecture #13.3 Code ;; * Recursive Directions ;; **************************************** ; +-----------------------+ ; v | ;; A Dir is either | ;; -- Stop = (make-stop) * ;; -- Up = (make-up dir) ;; -- Down = (make-down dir) ;; -- Left = (make-left dir) ;; -- Right = (make-right dir) ;; where dir is another Dir ;; Struct Definitions (define-struct stop ()) (define-struct up (dir)) (define-struct down (dir)) (define-struct left (dir)) (define-struct right (dir)) ;; Examples (define Stop (make-stop)) (define Path (make-up (make-right (make-down (make-left Stop))))) ;; Template #;(define (temp dir) (cond [(stop? dir) ... ] [(up? dir) ... (temp (up-dir dir) ... ) ...] [(down? dir) ... (temp (down-dir dir) ... ) ...] [(left? dir) ... (temp (left-dir dir) ... ) ...] [(right? dir) ... (temp (right-dir dir) ... ) ...] [else (error 'temp "Expected a Dir")])) ;; How much to move in each 'step' (define INCR 10) ;; single: Dir Number Number -> Posn ;; Compute the next point, if we were to move in the direction ;; of the given Dir, starting at (x,y) (define (single dir x y) (cond [(stop? dir) (make-posn x y)] [(up? dir) (make-posn x (- y INCR))] [(down? dir) (make-posn x (+ y INCR))] [(left? dir) (make-posn (- x INCR) y)] [(right? dir) (make-posn (+ x INCR) y)])) ;; draw-single: Number Number Posn Scene -> Scene ;; Draw a single line into the given scene based on the ;; starting (x,y) and the point 'p' (define (draw-single x y p scn) (add-line scn x y (posn-x p) (posn-y p) 'magenta)) ;; draw-one: Dir Number Number Scene -> Scene ;; Draw from the point (x,y) in direction given, into the given ;; scene (define (draw-one-direct dir x y scn) (draw-single x y (single dir x y) scn)) ;; draw-dir-help: Dir Posn -> Scene ;; Draw the lines that represent the direction given starting ;; at the point 'p' (define (draw-dir-help dir p) (cond [(stop? dir) (empty-scene 400 400)] [else (draw-one-direct dir (posn-x p) (posn-y p) (draw-dir-help (inner-dir dir) (single dir (posn-x p) (posn-y p))))])) ;; inner-dir: Dir -> Dir ;; Get the next inner Dir inside the given one (define (inner-dir dir) (cond [(stop? dir) (error 'inner-dir "Stop has no Inner Dir")] [(up? dir) (up-dir dir)] [(down? dir) (down-dir dir)] [(left? dir) (left-dir dir)] [(right? dir) (right-dir dir)])) ;; dir-append: Dir Dir -> Dir ;; Put the second Dir at the end of the first. i.e., Replace the ;; 'stop' in the first with the second Dir. (define (dir-append d1 d2) (cond [(stop? d1) d2] [(up? d1) (make-up (dir-append (inner-dir d1) d2))] [(down? d1) (make-down (dir-append (inner-dir d1) d2))] [(left? d1) (make-left (dir-append (inner-dir d1) d2))] [(right? d1) (make-right (dir-append (inner-dir d1) d2))])) ;; key: Dir CharOrSymbol -> Dir ;; Add the given arrow key direction to the given Dir (define (key dir c/s) (cond [(symbol? c/s) (dir-append dir (cond [(symbol=? 'up c/s) (make-up (make-stop))] [(symbol=? 'down c/s) (make-down (make-stop))] [(symbol=? 'left c/s) (make-left (make-stop))] [(symbol=? 'right c/s) (make-right (make-stop))] [else (make-stop)]))] [else dir])) ;; draw-dir: Dir -> Scene ;; Draw the given direction starting at the center (define (draw-dir dir) (draw-dir-help dir (make-posn 200 200))) ;; Usual window/world management (big-bang 400 400 1 (make-stop)) (on-redraw draw-dir) (on-key-event key)