htdp早期习题中,提到了构造单个红绿灯,那如果构造多个红绿灯
一个红绿灯出了故障,那其他几个红绿灯 不受影响,正常运行。这就类似电路中的并联。
htdp这本书提倡的是abstraction and encapsulation,即抽象与封装
abstraction一般是对数据和功能的抽象,目的是为了处理更多的数据,使程序更简洁。
encapsulation一般是对数据和功能的封装,将功能和数据集合在一个小空间里,racket中的local体现了这一功能
一个红绿灯出了故障,那其他几个红绿灯 不受影响,正常运行。
用多个变量var1,var2,var3,var4....存储多个红绿灯的状态。一个状态出了问题,而另外几个状态不受影响。
这种“并联式”的问题就没有必要对数据抽象,只需要对功能抽象和封装
具体代码
;;data
(define-struct traffic (street x-posn))
(define rice-color 'red)
(define cmu-color 'red)
(define ustc-color 'red)
(define kcl-color 'red)
(define current-color 'red)
(define x-posn 50)
(define width 50)
(define distance 10)
(define radius 20)
;;school-color-selector
(define (school-selector str)
(local ((define para (traffic-street str)))
(cond
[(symbol=? para 'sunrise@rice) rice-color] ;;其他函数调用此函数,已经解析了一遍,得出来的并不是变量
[(symbol=? para 'sunrise@cmu) cmu-color]
[(symbol=? para 'sunrise@ustc) ustc-color]
[(symbol=? para 'sunrise@kcl) kcl-color])))
;;初始化红绿灯
;;先清除之前所有红绿灯
(define (init-traffic str)
(begin
(clear (traffic-x-posn str) (school-selector str)) ;;
(set! (school-selector str) 'red) ;;
(draw-disk (traffic-x-posn str) (school-selector str))));;
;;画红绿灯
(define (draw-disk x-posn current-color)
(draw-solid-disk (make-posn x-posn (location current-color)) radius current-color))
;;清除红绿灯
(define (clear x-posn current-color)
(clear-solid-disk (make-posn x-posn (location current-color)) radius current-color))
;;在x坐标同样的情况下,通过颜色定位y坐标
(define (location current-color)
(cond
[(symbol=? current-color 'red) 30]
[(symbol=? current-color 'yellow) 80]
[(symbol=? current-color 'green) 130]))
;;颜色转换&&画转换后的红绿灯
(define (next str)
(begin (sleep-for-a-while 1)
(clear (traffic-x-posn str) (school-selector str)) ;;
(set! (school-selector str) (next-color (school-selector str)))
(sleep-for-a-while 1)
(draw-disk (traffic-x-posn str) (school-selector str)))) ;;
;;next-color-selector
(define (next-color current-color)
(cond
[(symbol=? current-color 'red) 'yellow]
[(symbol=? current-color 'yellow) 'green]
[(symbol=? current-color 'green) 'red]))
;;不需要知道函数怎么调用,就能调用函数
;;当然更简明的方法是设计一个用户界面
(define (service-message msg str)
(cond
[(symbol=? msg 'next) (next str)]
[(symbol=? msg 'reset) (init-traffic str)]
[else (error "The message can not be understood")]))
;;对于红绿灯数据的处理,还是把它构建成结构比较好
;;对于数据不易泄露,同时也便利
(define lights
(list (make-traffic 'sunrise@rice 50)
(make-traffic 'sunrise@cmu 150)
(make-traffic 'sunrise@ustc 250)
(make-traffic 'sunrise@kcl 350)))
(define op1 (first lights))
(define op2 (second lights))
(define op3 (third lights))
(define op4 (fourth lights))
出现问题
(set! (school-selector str) 'red) 中,(school-selector str)返回的是值并不是一个identifier,所以会出现 错误