;; A rank is a number in [MIN-RANK,MAX-RANK+1). (define MIN-RANK 2) (define MAX-RANK 14) ; 11 = jack; ... 13=king, 14=ace. ;; nums-upthrough: int int --> list-of-num ;; Return a list of integers [start,stop] ;; (Note that "stop" *is* in the returned list.) ;; (define (nums-upthrough start stop) (cond [(> start stop) empty] [else (cons start (nums-upthrough (add1 start) stop))])) (define suitranks (nums-upthrough MIN-RANK MAX-RANK)) (define deck (append suitranks suitranks suitranks suitranks)) ;; shuffle: list-of-ANY --> list-of-ANY ;; Return a list with the original's contents, but ;; in a scrambled order. ;; (define (shuffle stuff) (cond [(empty? stuff) empty] [(cons? stuff) (local [(define rand-elt (list-ref stuff (random (length stuff))))] (cons rand-elt (shuffle (remove-once rand-elt stuff))))])) ;; remove-once: alpha, list-of-alpha --> list-of-alpha ;; Remove one occurrence of targ, from elts. ;; Signal an error if targ does not occur. ;; Note: comparisons done with "equal?", so ;; actual contract is any, list-of-any --> list-of-any. ;; (define (remove-once targ elts) (cond [(empty? elts) (error 'remove-once "~s not found.~n" targ)] [(cons? elts) (if (equal? targ (first elts)) (rest elts) (cons (first elts) (remove-once targ (rest elts))))])) (remove-once 8 '(i 8 ny 8)) = '(i ny 8) (remove-once 'mohican '(mohican)) = empty (shuffle empty) (shuffle (list 'a 'b 'c)) (shuffle (list 'a 'b 'c)) ;; unzip: list-of-alpha --> (list list-of-alpha list-of-alpha) ;; Return two lists, each with alternating items from "stuff". ;; (define (unzip stuff) (local [(define (unzip-help remaining bin-a bin-b) (cond [(empty? remaining) (list bin-a bin-b)] [(cons? remaining) (unzip-help (rest remaining) bin-b (cons (first remaining) bin-a))]))] (unzip-help stuff empty empty))) ;; beats?: rank, rank --> boolean ;; (define (beats? rank-a rank-b) (cond [(and (= rank-a MIN-RANK) (= rank-b MAX-RANK)) true] [(and (= rank-a MAX-RANK) (= rank-b MIN-RANK)) false] [(= rank-a rank-b) (zero? (random 2))] [else (> rank-a rank-b)])) ;; battle: list-of-two-hands --> list-of-two-hands ;; Flip top card of each hand, ;; and put them on top of the winner's deck. ;; (define (battle players) (local [(define a (first players)) (define b (second players)) (define a-card (first a)) (define b-card (first b)) (define stake (list a-card b-card))] (if (beats? a-card b-card) (list (append (rest a) stake) (rest b)) (list (rest a) (append (rest b) stake))))) ;; war: list-of-two-hands --> {'a, 'b} ;; Battle until somebody loses. ;; Return 'a if first player wins, or 'b if second player wins. ;; NOTE: May not terminate??? ;; A student pointed out: ;; (war '((2 10) (10 2))) = (war '((10) (2 10 2))) = (war '((2 10) (10 2))) ;; (This presumes than when capturing, a player always ;; puts player a's card above player b's, regardless of ;; who the winner is.) ;; (define (war players) (local [(define a (first players)) (define b (second players))] (cond [(empty? a) 'b] [(empty? b) 'a] [else (war (battle (list a b)))]))) (battle (unzip (shuffle deck))) (battle (battle (battle (battle (unzip (shuffle deck)))))) (define (go) (war (unzip (shuffle deck))))