Compare commits

...

2 Commits

2 changed files with 99 additions and 35 deletions

View File

@ -42,6 +42,44 @@
(check-true (out-of-bounds? (point -2 0)))
(check-true (out-of-bounds? (point 0 -2))))
(test-case
"boxes-for"
(check-equal? (boxes-for (line (point 0 0) (point 0 1) 1)) (list (point 0 0)))
(check-equal? (boxes-for (line (point 2 1) (point 2 2) 1)) (list (point 2 1) (point 1 1)))
(check-equal? (boxes-for (line (point 0 0) (point 1 0) 1)) (list (point 0 0)))
(check-equal? (boxes-for (line (point 1 1) (point 2 1) 1)) (list (point 1 1) (point 1 0)))
(check-equal? (boxes-for (line (point 0 5) (point 1 5) 1)) (list (point 0 4)))
(check-equal? (boxes-for (line (point 5 0) (point 5 1) 0)) (list (point 4 0))))
(test-case
"completes-boxes"
(define grid
(list
(line (point 0 0) (point 0 1) 1)
(line (point 0 1) (point 1 1) 0)
(line (point 1 0) (point 1 1) 1)
(line (point 0 2) (point 0 3) 1)
(line (point 0 3) (point 1 3) 1)
(line (point 0 2) (point 1 2) 1)
(line (point 0 4) (point 0 5) 0)
(line (point 0 4) (point 1 4) 1)
(line (point 1 4) (point 1 5) 0)
(line (point 3 0) (point 4 0) 0)
(line (point 3 0) (point 3 1) 1)
(line (point 4 0) (point 4 1) 0)
(line (point 3 5) (point 4 5) 1)
(line (point 3 4) (point 3 5) 0)
(line (point 3 4) (point 4 4) 1)
(line (point 4 5) (point 5 5) 1)
(line (point 4 4) (point 5 4) 0)
(line (point 5 4) (point 5 5) 1))) ; all possible unfinished boxes (plus an unfinished double)
(check-equal? (completes-boxes grid (line (point 0 0) (point 1 0) 0)) 1)
(check-equal? (completes-boxes grid (line (point 1 2) (point 1 3) 0)) 1)
(check-equal? (completes-boxes grid (line (point 3 1) (point 4 1) 0)) 1)
(check-equal? (completes-boxes grid (line (point 0 5) (point 1 5) 0)) 1)
(check-equal? (completes-boxes grid (line (point 4 4) (point 4 5) 0)) 2)
(check-equal? (completes-boxes grid (line (point 1 0) (point 2 0) 1)) 0))
(test-case
"valid-move?"
(define grid (list
@ -88,12 +126,6 @@
(check-equal? (append-move grid (line (point 2 2) (point 2 3) 0)) (append grid (list (line (point 2 2) (point 2 3) 0))))
(check-equal? (append-move grid (line (point 0 0) (point 0 1) 0)) grid))
(test-case
"boxes-for"
(check-equal? (boxes-for (line (point 0 0) (point 0 1) 1)) (list (point 0 0)))
(check-equal? (boxes-for (line (point 2 1) (point 2 2) 1)) (list (point 2 1) (point 1 1)))
(check-equal? (boxes-for (line (point 0 0) (point 1 0) 1)) (list (point 0 0)))
(check-equal? (boxes-for (line (point 1 1) (point 2 1) 1)) (list (point 1 1) (point 1 0))))
(test-case
"valid-moves"

View File

@ -2,7 +2,7 @@
(provide (all-defined-out)) ; for testing module
(require racket/draw racket/random racket/gui)
(require racket/draw racket/random)
; a Grid is a list of lines. All lines in a grid must be specified as moving left to right, top to bottom ("to" coordinate higher than "from" coordinate")
@ -12,6 +12,12 @@
; represents a line drawn from one point to another and which player drew it.
(struct line (from to player) #:transparent)
; represents the state of a game in play
; grid is the grid
; player is the current player
; scores is a list of numbers for the score of each player.
(struct GameState (grid player scores))
; width and height of the playing grid.
(define GRID-WIDTH 6)
(define GRID-HEIGHT 6)
@ -127,43 +133,69 @@
(define (boxes-for line)
(filter (lambda (x) (not (eq? x 0)))
(list
(line-from line)
(if (and
(not (= (- GRID-WIDTH 1) (point-x (line-from line))))
(not (= (- GRID-HEIGHT 1) (point-y (line-from line))))) (line-from line) 0)
(if (and
(< (point-x (line-from line)) (point-x (line-to line))) ; horizontal line
(> (point-y (line-from line)) 0)
(< (point-y (line-from line)) (- GRID-HEIGHT 1)))
(point (point-x (line-from line)) (- (point-y (line-from line)) 1)) 0)
(> (point-y (line-from line)) 0))
(point (point-x (line-from line)) (- (point-y (line-from line)) 1)) 0)
(if (and
(< (point-y (line-from line)) (point-y (line-to line))) ; vertical line
(> (point-x (line-from line)) 0)
(< (point-y (line-from line)) (- GRID-WIDTH 1)))
(> (point-x (line-from line)) 0))
(point (- (point-x (line-from line)) 1) (point-y (line-from line))) 0))))
; Grid Line -> bool
; returns true if this line in grid has completed a box.
(define (completed-box? g l)
; Grid Line -> bool or Number
; returns the number of boxes this completes
(define (completes-boxes grid l)
(let
([boxes (boxes-for l)])
(or
(= (count-square (first boxes) g) 4)
(= (count-square (first boxes) g) 4))))
([boxes (boxes-for l)]
[g (append-move grid l)])
(length (filter (lambda (b) (= (count-square b g) 4)) boxes))))
; GameState, List of 2 Players -> GameState
; runs the game.
; If the game is over, returns the final game state
; else, lets a player play a move. If they complete a box, they stay on and earn a point. Else, the other player has a turn.
; TODO score 2 points for creating 2 boxes at once
(define (play-game s players)
(let ([g (GameState-grid s)]
[p (GameState-player s)])
(print (render-grid-bitmap g))
(cond
[(= (length g) (length ALL-LINES)) s] ; end of the game
[else
(let* ([move ((list-ref players p) g p)]
[new-grid (append-move g move)]
[boxes (completes-boxes g move)]
[box (not (= 0 boxes))]
[scores (GameState-scores s)])
(play-game (GameState
new-grid
(if box p (abs (- p 1)))
(if box (list-set scores p (+ boxes (list-ref scores p))) scores)) players))])))
; Grid -> Image
; renders grid to an image for showing humans the game.
(define (render-grid grid)
(let* ([bitmap (make-bitmap (* GRID-WIDTH GRID-SCALE) (* GRID-HEIGHT GRID-SCALE))]
(define (render-grid-bitmap grid)
(let* ([bitmap (make-bitmap (+ 10 (* GRID-WIDTH GRID-SCALE)) (+ 10 (* GRID-HEIGHT GRID-SCALE)))] ; add border for printing
[dc (new bitmap-dc% [bitmap bitmap])])
(for ([l grid])
(cond
[(= (line-player l) 0) (send dc set-pen "red" 4 'solid)] ; player 1 draws in red
[(= (line-player l) 1) (send dc set-pen "blue" 4 'solid)]) ; player 2 draws in blue
(send dc draw-line
(+ 4 (* GRID-SCALE (point-x (line-from l))))
(+ 4 (* GRID-SCALE (point-y (line-from l))))
(+ 4 (* GRID-SCALE (point-x (line-to l))))
(+ 4 (* GRID-SCALE (point-y (line-to l)))))) ; draw the line
(send dc draw-bitmap EMPTY-GRID 0 0) ; overlay dot grid
bitmap))
(render-grid grid dc)
bitmap))
; Grid dc !
; renders grid on the given drawing context.
; TODO color in squares
(define (render-grid grid dc)
(for ([l (reverse grid)])
(cond
[(= (line-player l) 0) (send dc set-pen "red" 4 'solid) (send dc set-brush "red" 'bdiagonal-hatch)] ; player 1 draws in red
[(= (line-player l) 1) (send dc set-pen "blue" 4 'solid) (send dc set-brush "blue" 'fdiagonal-hatch)]) ; player 2 draws in blue
(send dc draw-line
(+ 4 (* GRID-SCALE (point-x (line-from l))))
(+ 4 (* GRID-SCALE (point-y (line-from l))))
(+ 4 (* GRID-SCALE (point-x (line-to l))))
(+ 4 (* GRID-SCALE (point-y (line-to l)))))) ; draw the line
(send dc draw-bitmap EMPTY-GRID 0 0)) ; overlay dot grid
(play-game (GameState '() 0 '(0 0)) (list random-player random-player))