80 lines
2.8 KiB
Racket
80 lines
2.8 KiB
Racket
#cs(module guess-gui mzscheme
|
|
(require htdp/error
|
|
mred
|
|
mzlib/class
|
|
mzlib/list
|
|
mzlib/etc
|
|
lang/prim)
|
|
|
|
(provide
|
|
connect ; (button% event% -> true) -> true
|
|
control ; N -> DIGIT
|
|
view ; X -> true
|
|
)
|
|
|
|
(define-primitive control control/proc)
|
|
(define-primitive view view/proc)
|
|
(define-higher-order-primitive connect connect/proc (call-back))
|
|
|
|
;; ------------------------------------------------------------------------
|
|
;; Basic constants:
|
|
(define TITLE "Number Guessing")
|
|
(define WIDTH 100)
|
|
(define HIGHT 80)
|
|
(define GUESS 3)
|
|
|
|
;; DIGIT = (union 0 1 2 3 4 5 6 7 8 9)
|
|
(define DIGITS (build-list 10 (lambda (i) (number->string i))))
|
|
|
|
;; ------------------------------------------------------------------------
|
|
;; GUI LAYOUT
|
|
(define frame (make-object frame% TITLE #f WIDTH HIGHT))
|
|
(define verti (make-object vertical-panel% frame))
|
|
(define panel (make-object horizontal-panel% verti))
|
|
(send panel set-alignment 'center 'center)
|
|
|
|
;; ------------------------------------------------------------------------
|
|
;; guess : handle CONTROL
|
|
(define guess-panel (make-object horizontal-panel% verti '(border)))
|
|
(define (make-choices n)
|
|
(cons (make-object choice% #f DIGITS guess-panel void)
|
|
(cond
|
|
[(= n 0) empty]
|
|
[else (make-choices (sub1 n))])))
|
|
|
|
(define guess-choices (make-choices (sub1 GUESS)))
|
|
|
|
;; control : N -> DIGIT
|
|
;; to read out the i-th guess choice, starting with 0
|
|
(define (control/proc i)
|
|
(check-arg 'control
|
|
(and (number? i) (integer? i) (exact? i) (<= 0 i (sub1 GUESS)))
|
|
(format "number in 0 ...~s" GUESS) "first" i)
|
|
'(if (and (number? i) (integer? i) (exact? i) (<= 0 i (sub1 GUESS)))
|
|
...
|
|
(printf "control: improper index, expected 0 ... ~s~n" GUESS))
|
|
(send (list-ref guess-choices (- GUESS i 1)) get-selection))
|
|
|
|
;; connect : (button% control-event% -> true) -> true
|
|
;; effect: to add a check button with call-back to frame and to show frame
|
|
(define check-button #f)
|
|
(define (connect/proc call-back)
|
|
(check-proc 'connect call-back 2 '1st "2 arguments")
|
|
(if check-button
|
|
(printf "connect: called a second time~n")
|
|
(begin
|
|
(set! check-button
|
|
(make-object button% "Check" guess-panel call-back '(border)))
|
|
(send frame show #t))))
|
|
|
|
;; ------------------------------------------------------------------------
|
|
;; message : display VIEW
|
|
(define VIEW-fmt "View the result: ~a")
|
|
(define VIEW0 (format VIEW-fmt (make-string (* 2 GUESS) #\space)))
|
|
(define message-field (make-object message% VIEW0 verti))
|
|
|
|
;; view : X -> void
|
|
;; effect: to display n in the message panel
|
|
(define (view/proc n) (send message-field set-label (format VIEW-fmt n)))
|
|
)
|