rendered paste body; Main:
; Connect 4 game
; Game board is 7 tall and 8 high
; Players are 'red and 'blue
(define done 'okay)
;board related
;a row-col pair
(define lm cons) ;loc-make
(define lr car) ;loc-row
(define lc cdr) ;loc-col
(define (board-ref board loc)
(vector-ref (vector-ref board (lr loc))
(lc loc)))
(define (board-set! board loc value)
(vector-set! (vector-ref board (lr loc))
(lc loc)
value))
(define BOARD_ROWS 7)
(define BOARD_COLS 8)
(define (make-board)
(let ((ret (make-vector 7)))
(define (loop i)
(if (< i BOARD_ROWS)
(begin
(vector-set! ret i (make-vector 8 'empty))
(loop (+ i 1)))
ret))
(loop 0)))
(define dummy-board (make-board))
;generic iterator
;cell-proc called for every cell
;(λ (board loc) (stuff))
;row-proc called for every row
;(λ (loc) (stuff))
;knowing board is not important as
;loc does not refer to an actual cell
(define (board-loop board cell-proc row-proc)
(define (loop i j)
(cond ((>= i BOARD_ROWS) done)
((>= j BOARD_COLS)
(row-proc (lm i j))
(loop (+ i 1) 0))
(else
(cell-proc board (lm i j))
(loop i (+ j 1)))))
(loop 0 0))
;specialized iterator that only cares for values
;cellproc is (λ (value) (stuff))
;rowproc is (λ () (stuff))
(define (board-iter board cell-proc row-proc)
(board-loop (λ (board loc) (cell-proc (board-get board loc)))
(λ (loc) (row-proc))))
; GUI STUFF
(define current-game #f) ;board that gets painted
(define main-window #f)
(define cursor-col #f)
(define (update-window)
(if main-canvas
(send main-canvas refresh)))
(define canvas-w-offset 0) ;ugly hacks
(define canvas-cell-size 0)
(define main-canvas #f)
(define turn-display #f)
(define game-canvas%
(class canvas%
(override on-event)
(define on-event
(λ (event)
(let ((col (floor (/ (- (send event get-x)
canvas-w-offset)
canvas-cell-size))))
(cond ((or (>= col BOARD_COLS)
(< col 0))
(set! cursor-col #f)
(update-window))
((not (eqv? cursor-col col))
(set! cursor-col col)
(update-window))
((send event leaving?)
(set! cursor-col #f))
(else done)))))
(super-instantiate ())))
;row=height
;col=width
(define (painter canvas dc)
(let* ((width (send canvas get-width))
(height (- (send canvas get-height) 20))
(col-size (/ width BOARD_COLS))
(row-size (/ height BOARD_ROWS))
(cellsize (min col-size row-size))
(w-offset (/ (- width (* BOARD_COLS cellsize)) 2))
(h-offset (/ (- height (* BOARD_ROWS cellsize)) 2)))
(define (paint-grid)
(define (draw-col i)
(if (> i BOARD_COLS)
done
(begin
(send dc draw-line
(+ (* i cellsize) w-offset) h-offset
(+ (* i cellsize) w-offset) (- height h-offset))
(draw-col (+ i 1)))))
(define (draw-row i)
(if (> i BOARD_ROWS)
done
(begin
(send dc draw-line
w-offset (+ (* i cellsize) h-offset)
(- width w-offset) (+ (* i cellsize) h-offset))
(draw-row (+ i 1)))))
(send dc set-pen "black" 3 'solid)
(draw-row 0)
(draw-col 0))
(define (paint-cells size)
(if (not current-game)
done
(begin
(send dc set-pen "black" 0 'transparent)
(board-loop (current-game 'board)
(λ (board loc)
(define draw #t)
(cons ((eq? (board-get board loc) 'red)
(send dc set-brush "red" solid))
((eq? (board-get board loc) 'blue)
(send dc set-brush "blue" solid))
(else #f))
(send dc draw-ellipse
(+ w-offset (lc loc))
(+ h-offset (lr loc))
size
size))
(λ (loc) done)))))
(define (paint-cursor-mark)
(if (not cursor-col)
done
(begin
(send dc set-pen "black" 0 'transparent)
(send dc set-brush "green" 'solid)
(send dc draw-rectangle
(+ w-offset (* cellsize cursor-col))
(- height h-offset)
cellsize
20))))
(set! canvas-w-offset w-offset)
(set! canvas-cell-size cellsize)
(paint-cursor-mark)
(paint-grid)
(paint-cells cellsize)))
(define (button-new-game button event)
(set! current-game (make-game))
(update-window))
(define (button-quit-game button event) done)
(define (build-gui)
(set! main-window (instantiate frame% ("Connect 4")))
(let* ((main-panel
(instantiate horizontal-pane%
(main-window)
(alignment '(center center))))
(ctrl-panel
(instantiate vertical-pane%
(main-panel)
(alignment '(center top))
(stretchable-height #t)
(stretchable-width #f)
(min-width 100)))
(game-panel
(instantiate game-canvas%
(main-panel)
(paint-callback painter)
(min-width 400)
(min-height 400))))
(instantiate button% () (parent ctrl-panel) (label "New")
(callback button-new-game))
(instantiate button% () (parent ctrl-panel) (label "Quit")
(callback button-quit-game))
(instantiate pane% () (parent ctrl-panel) (min-height 20)
(stretchable-height #f))
(let ((turn-pane (instantiate horizontal-pane% ()
(parent ctrl-panel)
(alignment '(left top))
(stretchable-height #f)
(border 4))))
(instantiate message% () (parent turn-pane) (label "Turn:"))
(set! turn-display (instantiate message% ()
(parent turn-pane)
(label "Unknown"))))
(set! main-canvas game-panel))
(send main-window show #t))
(build-gui)
; Game
;returns a new game
(define (make-game)
(let ((board (make-board))
(turn 'red)
(winner #f))
(λ (cmd . args)
(cond ((eq? cmd 'move!)
(make-move (lm (car args) (cadr args)))
(update-window))
((eq? cmd 'board) board)
((eq? cmd 'winner) winner)
((eq? cmd 'turn) turn)
(else (error 'game-unknown-cmd))))))