racket/collects/games/pousse/utils.ss
Eli Barzilay 16f01a1109 {quick,merge}sort -> sort
svn: r2569
2006-04-01 12:24:15 +00:00

107 lines
3.9 KiB
Scheme

(module utils mzscheme
; See boardsig.ss for the core utilities.
(require "board-size.ss"
"board.ss")
(provide
n-times ; call a procedure with each number in [0, n]
n-map ; call a procedure with each number in [0, n] to make a list
print-board ; pretty-prints a board
find-winner ; checks a board to see if there's a winner
other-player ; x -> o or o -> x
pick-best ; takes a list of (cons <num> <val>) and returns pair
; with the biggest <num>, randomly chossing among
; equals
)
; Call f with each number in [0, n]
(define (n-times n f)
(let loop ([i 0])
(unless (= i n)
(f i)
(loop (add1 i)))))
; Call f with each number in [0, n] to make a list
(define (n-map n f)
(let loop ([i 0])
(if (= i n)
null
(cons (f i)
(loop (add1 i))))))
; Pretty-prints the board
(define print-board
(case-lambda
[(b) (print-board b (current-output-port))]
[(b port)
(let ([n (current-board-size)])
(n-times n (lambda (j)
(n-times n (lambda (i)
(fprintf port "~a " (let ([v (board-cell b i j)])
(cond
[(eq? v none) '-]
[(eq? v x) 'x]
[(eq? v o) 'o])))))
(newline port))))]))
; Given a player (board cell value), get the other one
(define (other-player as-player)
(if (eq? as-player x)
o
x))
; See if the board has a winner; returns o, x, or #f
(define (find-winner board)
(let ([n (current-board-size)])
(let ([row-wins-x (make-vector n 1)]
[row-wins-o (make-vector n 1)]
[col-wins-x (make-vector n 1)]
[col-wins-o (make-vector n 1)])
(n-map n (lambda (i)
(n-map n (lambda (j)
(let ([v (board-cell board i j)])
(cond
[(eq? v x) (vector-set! col-wins-o i 0)
(vector-set! row-wins-o j 0)]
[(eq? v o) (vector-set! col-wins-x i 0)
(vector-set! row-wins-x j 0)]
[else (vector-set! col-wins-o i 0)
(vector-set! row-wins-o j 0)
(vector-set! col-wins-x i 0)
(vector-set! row-wins-x j 0)]))))))
(let ([o-wins (+ (apply + (vector->list row-wins-o))
(apply + (vector->list col-wins-o)))]
[x-wins (+ (apply + (vector->list row-wins-x))
(apply + (vector->list col-wins-x)))])
(cond
[(= o-wins x-wins) #f]
[(> o-wins x-wins) o]
[else x])))))
; Compare the values in goodness and pick the biggest element.
; Takes a non-empty list of (cons <goodness> <choice>)
; If <goodness> is a pair, look at the car.
; Return (cons <goodness> <choice>).
(define (pick-best choices)
(let loop ([l (cdr choices)]
[goodness (let ([g (caar choices)])
(if (pair? g)
(car g)
g))]
[result (car choices)])
(if (null? l)
result
(let ([v (let ([v (caar l)])
(if (pair? v)
(car v)
v))])
(cond
[(> v goodness) (loop (cdr l) v (car l))]
[(and (= v goodness)
; pick randomly
(zero? (random 2)))
(loop (cdr l) v (car l))]
[else (loop (cdr l) goodness result)]))))))