还是那句话,经典不妨一看再看
compound这章的视频可以在edx上看,也可以点开youtube的公开课链接看
这里的总结是假设你都看过视频了( ̄<  ̄)>

我们目标是一头牛跑来跑去,而且按空格会掉头...

跑题了, 老规矩,先画domain analysis

如果只是跑来跑去,不掉头的话, 那就跟htdw那只喵是一样的,可以用simple atomic data 来表示。
但这里牛会掉头, 只是x轴的pixel坐标还不够用, 还需要一个表示表示方向的信息。
到现在为止,atomic,interval, enum和itemaization都是一对一的定义。
(enum和itemaization看起来有几种情况,但是也是one of,其实还是一对一的)

这时候, 引入了一个叫compound 的数据类型
compound 并不是一对一的,而是包括了两个或以上数据的组合
可以想成是一个盒子,里面装了两种或以上的东西

;; Data definitions:
(define-struct cow (x dx))


当racket见到(define-struct cow (x dx)), 它自动生成关于cow这个struct 的一些function:
make-cow: 创建一个cow
cow? ; 检查是否是一个cow 的struct
cow-x : 读取cow x的信息
cow-dx: 读取cow dx的信息

有了这些function, 就可以写下compound的htdd了

;; Data definitions:
(define-struct cow (x dx))
;; Cow is (make-cow Naturla[0, WIDTH], Integer)
;; interp. (make-cow x dx) is a cow with x coordinates a and velocity dx
;;     the x is the center of the cow
;;     x is in secreen coordinates (pixels)
;;     dx is in pixels per tick
(define C1 (make-cow 10 3))  ;; at 10, moving left -> right
(define C2 (make-cow 20 -4)) ;; at 20, moving right -> left

(@dd-template-rules compound)  ;2 fields

(define (fn-for-cow c)
  (... (cow-x c)    ;; Naturla[0, WIDTH]
       (cow-dx c))) ;; Integer

完整的code,点击这里javaIsTheBest
关于compound 的 function, 可以想成一个人收到一个盒子以后,先打开,
然后根据里面的内容做一些事情(例如,创建一个新的盒子, 一个image。。。)
以next-cow 的一个check-expect为例,

(check-expect (next-cow (make-cow 20 -3)) (make-cow (- 20 3) -3))
....
(define (next-cow c)
  (cond [(> (+ (cow-x c) (cow-dx c)) WIDTH) 
         (make-cow WIDTH (- (cow-dx c)))]
        [(< (+ (cow-x c) (cow-dx c)) 0) 
         (make-cow 0 (- (cow-dx c)))]
        [else
         (make-cow (+ (cow-x c) (cow-dx c))
                   (cow-dx c))]))

    javaIsTheBest 完整的code,点这里

    (require spd/tags)
    (require 2htdp/image)
    (require 2htdp/universe)
    (define WIDTH 400)
    (define HEIGHT 200)
    
    (define CTR-Y (/ HEIGHT 2))
    
    (define RCOW  (bitmap/url "https://i.imgur.com/akBZSOA.png"))
    
    (define LCOW  (bitmap/url "https://i.imgur.com/rG9Uf7i.png"))
    
    (define MTS (empty-scene WIDTH HEIGHT))
    
    ;; Data definitions:
    (@htdd Cow)
    (define-struct cow (x dx))
    ;; Cow is (make-cow Natural[0, WIDTH], Integer)
    ;; interp. (make-cow x dx) is a cow with x coordinate x and velocity dx
    ;;         the x is the center of the cow
    ;;         x is in screen coordinates (pixels)
    ;;         dx is in pixels per tick
    ;;
    (define C1 (make-cow 10 3))  ; at 10, moving left -> right
    (define C2 (make-cow 20 -4)) ; at 20, moving left <- right
    #;
    (define (fn-for-cow c)
      (... (cow-x c)      ;Natural[0, WIDTH]
           (cow-dx c)))   ;Integer
    
    (@dd-template-rules compound) ;2 fields
    
    ;; Functions:
    
    (@signature Cow -> Cow)
    ;; called to make the cow go for a walk; start with (main (make-cow 0 3))
    ;; no tests for main function
    (define (main c)
      (big-bang c
                (on-tick next-cow)      ; Cow -> Cow
                (to-draw render-cow)    ; Cow -> Image
                (on-key handle-key)))   ; Cow KeyEvent -> Cow 
    
    (@htdf next-cow)
    (@signature Cow -> Cow)
    ;; increase cow x by dx; bounce off edges
    (check-expect (next-cow (make-cow 20 3)) (make-cow (+ 20 3) 3))  ;middle
    (check-expect (next-cow (make-cow 20 -3)) (make-cow (- 20 3) -3))
                  
    (check-expect (next-cow (make-cow (- WIDTH 3) 3)) (make-cow WIDTH 3)) ;reaches edge (check-expect (next-cow (make-cow 3 -3)) (make-cow 0 -3)) (check-expect (next-cow (make-cow (- WIDTH 2) 3)) (make-cow WIDTH -3)) ;tries to pass edge (check-expect (next-cow (make-cow 2 -3)) (make-cow 0 3)) ;(define (next-cow c) c) ;stub (@template-origin Cow) (@template (define (next-cow c) (... (cow-x c) ;Natural[0, WIDTH] (cow-dx c)))) (define (next-cow c) (cond [(> (+ (cow-x c) (cow-dx c)) WIDTH) (make-cow WIDTH (- (cow-dx c)))] [(< (+ (cow-x c) (cow-dx c)) 0) (make-cow 0 (- (cow-dx c)))] [else (make-cow (+ (cow-x c) (cow-dx c)) (cow-dx c))]))
    (@signature Cow -> Image) ;; place appropriate cow image on MTS at (cow-x c) and CTR-Y (check-expect (render-cow (make-cow 99 3)) (place-image RCOW 99 CTR-Y MTS)) (check-expect (render-cow (make-cow 33 -3)) (place-image LCOW 33 CTR-Y MTS)) ;(define (render-cow c) MTS) ;stub (@template-origin Cow) (@template (define (render-cow c) (... (cow-x c) ;Natural[0, WIDTH] (cow-dx c)))) (define (render-cow c) (place-image (choose-image c) (cow-x c) CTR-Y MTS))
    (@signature Cow -> Image) ;; produce RCOW or LCOW depending on direction cow is going; LCOW if dx = 0 (check-expect (choose-image (make-cow 10 3)) RCOW) (check-expect (choose-image (make-cow 11 -3)) LCOW) (check-expect (choose-image (make-cow 11 -0)) LCOW) ;(define (choose-image c) RCOW) (@template-origin Cow) (@template (define (choose-image c) (... (cow-x c) ;Natural[0, WIDTH] (cow-dx c)))) (define (choose-image c) (if (> (cow-dx c) 0) RCOW LCOW))
    (@signature Cow KeyEvent -> Cow) ;; reverse direction of cow travel when space bar is pressed (check-expect (handle-key C1 " ") (make-cow 10 -3)) (check-expect (handle-key C1 "a") C1) ;(define (handle-key c ke) c) ;stub (@template-origin KeyEvent) (@template
    (define (handle-key c ke) (cond [(key=? ke " ") (... c)] [else (... c)]))) (define (handle-key c ke) (cond [(key=? ke " ") (make-cow (cow-x c) (- 0 (cow-dx c)))] [else c]))
    5 months later
    Write a Reply...