-
Notifications
You must be signed in to change notification settings - Fork 0
/
tictactoe.rkt
130 lines (121 loc) · 5.43 KB
/
tictactoe.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#! /usr/bin/env racket
#lang racket
(require net/url)
(require (planet dmac/spin))
(define comp #\O)
(define human #\X)
(get "/playFirst"
(lambda () (play (state->string (map string->list (string-split (ai-move test comp human) ","))))))
(get "/playSecond"
(lambda () (play (state->string test))))
(get "/move/:state"
(lambda (req)
(local [(define currstate (map string->list (string-split (params req 'state) ",")))]
(cond [(and (string=? "first" (params req 'pos)) (equal? currstate test))
(ai-move currstate human comp)]
[else (local [(define newmove (ai-move currstate human comp))]
(string-append newmove ))]))))
(define test '((#\. #\. #\.)(#\. #\. #\.)(#\. #\. #\.)))
(define test1 '((#\. #\. #\.)(#\. #\X #\.)(#\. #\. #\.)))
(define (make-move board coords player)
(local[(define x (first coords))
(define y (second coords))
]
(foldr (lambda (a b c) (cons (cond
[(= b y)
(foldr (lambda (i j k)
(cons (cond
[(= j x) player]
[else i])
k))
empty
a
(build-list (length (first board)) identity))]
[else a])
c))
empty
board
(build-list (length board) identity))))
(define (ai-move board p1 p2)
(local
[(define moves (neighbours board p1 p2 p1 p2))
(define result
(cond
[(= 1 (length moves)) (first moves)]
[else (foldl (lambda (a b)
(cond
[(> (first a) (first b)) a]
[else b]))
(first moves)
(rest moves))]))
(define new-board (rest (rest (rest (rest result)))))]
(cond [(winner? new-board p2) (state->string new-board)]
[(winner? new-board p1) (state->string new-board)]
[(= 0 (length (empty-poss new-board)))(state->string new-board)]
[else (state->string new-board)])))
(define (state->string state)
(string-join (foldr (lambda (a b) (cons (list->string a) b)) empty state) ","))
(define (empty-poss board)
(foldl (lambda (a b c)
(append (foldl (lambda (x y z)
(cond
[(char=? x #\.) (cons (list y b) z)]
[else z]))
empty
a
(build-list (length a) identity))
c))
empty
board
(build-list (length board) identity)))
(define (sum-rating lor)
(list (foldl + 0 (map first lor))
(foldl + 0 (map second lor))
(foldl + 0 (map third lor))))
(define (neighbours board currplayer nextplayer p1 p2)
(local [(define empty-list (empty-poss board))]
(cond
[(winner? board p1) (list (append (list 1 0 0 '()) board))]
[(winner? board p2) (list (append (list 0 1 0 '()) board))]
[(= 0 (length empty-list)) (list (append (list 0 0 1 '()) board))]
[else (map (lambda (x) (append (sum-rating (neighbours (make-move board x nextplayer)
nextplayer
currplayer
p1 p2))
(list x)
(make-move board x nextplayer)))
empty-list) ])))
(define (rotate board)
(foldl (lambda (a b)
(foldr (lambda (x y z)
(cons (cons x y) z))
empty
a
b))
(map list (first board))
(rest board)))
(define (diag? board off player)
(or (empty? board)
(= off (length (first board)))
(and (char=? (list-ref (first board) off) player)
(diag? (rest board) (+ off 1) player))))
(define (winner? board player)
(or (ormap (lambda (x)
(andmap (lambda (y) (char=? y player)) x))
board)
(ormap (lambda (x)
(andmap (lambda (y) (char=? y player)) x))
(rotate board))
(diag? board 0 player)
(diag? (rotate board) 0 player)))
(define (play state)
(cond
[(winner? (map string->list (string-split state ",")) comp)
(string-join (cons (string-append (list->string (list comp)) " win <br>") (map (lambda (x) (list->string(append x (list #\newline)))) (map string->list (string-split state ",")))) "<br>")]
[(winner? (map string->list (string-split state ",")) human)
(string-join (cons (string-append (list->string (list human)) " win <br>") (map (lambda (x) (list->string(append x (list #\newline)))) (map string->list (string-split state ",")))) "<br>")]
[(= 0 (length (empty-poss (map string->list (string-split state ",")))))
(string-join (cons "Tie <br>" (map (lambda (x) (list->string(append x (list #\newline)))) (map string->list (string-split state ",")))) "<br>")]
[else (local [(define resp (port->string (get-pure-port (string->url (string-append "http://localhost:8000/move/" state)))))]
(play (ai-move (map string->list (string-split resp ",")) comp human)))]))
(run)