-
Notifications
You must be signed in to change notification settings - Fork 0
/
game.idr
150 lines (119 loc) · 5.7 KB
/
game.idr
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import Data.Vect
import Debug.Trace
%default total
data Position = X | O | E
Eq Position where
(==) X X = True
(==) O O = True
(==) E E = True
(==) _ _ = False
data Player = Cross | Zero
Show Player where
show Cross = "crosses"
show Zero = "zeroes"
Eq Player where
(==) Cross Cross = True
(==) Zero Zero = True
(==) _ _ = False
Show Position where
show X = "X"
show O = "O"
show E = " "
data Grid : Type where
MkGrid : Vect 9 (Int, Position) -> Grid
sp : String
sp = " "
vt : String
vt = " | "
showSquare : (Int, Position) -> String
showSquare (a,p) = case a of 1 => show p ++ vt
2 => show p ++ vt
4 => show p ++ vt
5 => show p ++ vt
7 => show p ++ vt
8 => show p ++ vt
3 => show p ++ "\n" ++ "----" ++ "----" ++ "-" ++ "\n"
6 => show p ++ "\n" ++ "----" ++ "----" ++ "-" ++ "\n"
9 => show p
_ => "nothing"
Show Grid where
show (MkGrid xs) = concat (map showSquare xs)
EmptyGrid : Grid
EmptyGrid = MkGrid [(1,E),(2,E),(3,E),(4,E),(5,E),(6,E),(7,E),(8,E),(9,E)]
-- Vect empty_squares_remaining Int - List of numbers of Empty Squares
record GameState where
constructor MkGameState
grid : Grid
player : Player
data Finished = CrossesLost | CrossesWon | Draw
isValidMove : (str : String) -> Bool
isValidMove str = if (all isDigit (unpack str)) then True else False
partial
readMove : GameState -> IO (Int)
readMove st@(MkGameState grid pl) = do putStr (show pl ++ ", your move: ")
inpStr <- getLine
case isValidMove inpStr of
True => pure (cast inpStr)
False => do putStrLn "Invalid input"
readMove st
addMove : Grid -> Int -> Player -> Grid
addMove (MkGrid xs) move pl = MkGrid (map (recordMove move pl) xs) where
recordMove : Int -> Player -> (Int, Position) -> (Int, Position)
recordMove m p (a,b) = if m /= a then (a,b)
else case p of Cross => (a, X)
Zero => (a, O)
processMove : (move : Int) -> GameState -> GameState
processMove move (MkGameState grid pl) = let newGrid = addMove grid move pl
newPl = if pl == Cross then Zero
else Cross in
MkGameState newGrid newPl
makeVerTriples : List (Int, Position) ->
List (Int, Position) ->
List (Int, Position) ->
List (List (Int, Position))
makeVerTriples [] [] [] = []
makeVerTriples (x :: xs) (y :: ys) (z :: zs)
= (x :: y :: z :: Nil) :: ( makeVerTriples xs ys zs)
makeVerTriples _ _ _ = []
makeDiags : List (Int,Position) -> List (List (Int, Position))
makeDiags xs = (filter check1 xs) :: (filter check2 xs) :: Nil where
check1 : (Int,Position) -> Bool
check1 (num, p) = if (num == 1 || num == 5 || num == 9) then True else False
check2 : (Int,Position) -> Bool
check2 (num, p) = if (num == 3 || num == 5 || num == 7) then True else False
makeTriples : Vect 9 (Int, Position) -> List (List (Int, Position))
makeTriples xs
= let (threeVert1, six) = splitAt 3 xs
(threeVert2, threeVert3) = splitAt 3 six in
[toList threeVert1, toList threeVert2, toList threeVert3] ++
makeVerTriples (toList threeVert1) (toList threeVert2) (toList threeVert3) ++
makeDiags (toList xs)
checkTriple : List (List (Int, Position)) -> Maybe Finished
checkTriple xs = if (any chkCross xs) then Just CrossesWon
else if (any chkZero xs) then Just CrossesLost
else if all chkFreePos xs then Just Draw
else Nothing where
chkCross : List (Int, Position) -> Bool
chkCross xs = all (\(int,p) => if p == X then True else False) xs
chkZero : List (Int, Position) -> Bool
chkZero xs = all (\(int,p) => if p == O then True else False) xs
chkFreePos : List (Int, Position) -> Bool
chkFreePos xs = all (\(int,p) => if p /= E then True else False) xs
checkGrid : Grid -> Maybe Finished
checkGrid (MkGrid xs) = checkTriple $ makeTriples xs
checkFinish : GameState -> Maybe Finished
checkFinish (MkGameState grid pl) = checkGrid grid
partial
game : GameState -> IO Finished
game st@(MkGameState gr pl) = do putStrLn (show gr ++ "\n")
mv <- readMove st
let newSt = processMove mv st
case checkFinish newSt of Just a => do putStrLn (show (grid newSt) ++ "\n")
pure a
Nothing => game newSt
partial
main : IO ()
main = do result <- game (MkGameState EmptyGrid Cross)
case result of CrossesLost => putStrLn "Crosses Lost, Zeroes Win!"
CrossesWon => putStrLn "Crosses Win, Zeroes Lost!"
Draw => putStrLn "It's a draw!"