-
-
Save jackfirth/cee98a6345db8050b76e556400475c9a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang racket/base | |
(require racket/list | |
racket/match | |
rebellion/base/option | |
rebellion/collection/list | |
rebellion/streaming/reducer | |
rebellion/streaming/transducer | |
rebellion/type/enum | |
fancy-app) | |
; X and O | |
(define empty-board (make-list 9 absent)) | |
(define-enum-type mark (X O)) | |
(define (rows board) | |
(list (take board 3) (take (drop board 3) 3) (drop board 6))) | |
(define (count-player board player) | |
(transduce board (filtering (equal? _ (present player))) #:into into-count)) | |
(define horizontal-lines (list (list 0 1 2) (list 3 4 5) (list 6 7 8))) | |
(define vertical-lines (list (list 0 3 6) (list 1 4 7) (list 2 5 8))) | |
(define diagonal-lines (list (list 0 4 8) (list 2 4 6))) | |
(define lines-list (append horizontal-lines vertical-lines diagonal-lines)) | |
(define (test-line to-test) | |
(match to-test | |
[(list (== X) (== X) (== X)) X] | |
[(list (== O) (== O) (== O)) O] | |
[(list a b c) absent])) | |
(test-line (list X X O)) | |
(define (extract-lines board) | |
(map (map (list-ref board _) _) lines-list)) | |
(define (get-empties board) | |
(transduce (in-range 9) | |
(filtering (λ (x) (absent? (list-ref board x)))) | |
#:into into-list)) | |
(define (count-empties board) (length (get-empties board))) | |
empty-board | |
(define (print-space p) | |
(match p [(== X) "X"] [(== O) "O"] [(== absent) "_"])) | |
(define (print-row row) | |
(transduce row (mapping print-space) #:into (join-into-string " "))) | |
(define (print-board board) | |
(transduce (rows board) | |
(mapping print-row) | |
#:into (join-into-string "\n"))) | |
(display (print-board empty-board)) | |
(display "\n") | |
(display (extract-lines empty-board)) | |
(define (winner-helper board) | |
(filter-not absent? (map test-line (extract-lines board)))) | |
(define (check-winner board) | |
(define winner (winner-helper board)) | |
(if (empty-list? winner) | |
absent | |
(list-first winner))) | |
(define (get-current-turn board) | |
(if (equal? (modulo (count-empties board) 2) 0) O X)) | |
(get-current-turn empty-board) | |
(define (move board index) | |
(if (present? (list-ref board index)) | |
(display "err") | |
(list-set board index (get-current-turn board)))) | |
(define (score-helper board player) | |
(score (move board (choose-move board)) player)) | |
(define (score board player) | |
(define winner (check-winner board)) | |
(cond | |
[(equal? winner player) 1] | |
[(and (absent? winner) (zero? (count-empties board))) 0] | |
[(absent? winner) (* .9 (score-helper board player))] | |
[else -1])) | |
(define (choose-move board) | |
(define (score-move c) | |
(score (move board c) (get-current-turn board))) | |
(present-value | |
(transduce (get-empties board) #:into (into-max #:key score-move)))) | |
(define moves-into-board | |
(make-fold-reducer move empty-board #:name 'moves-into-board)) | |
(define sample-board (transduce (range 9) #:into moves-into-board)) | |
(define sample-board2 (transduce (range 3) #:into moves-into-board)) | |
(display "\n") | |
(display (print-board sample-board)) | |
(display "\n") | |
(extract-lines sample-board) | |
(check-winner sample-board) | |
(display (print-board sample-board2)) | |
(display "\n") | |
(score sample-board2 X) | |
(score sample-board2 O) | |
(choose-move sample-board2) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment