-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTicTacToe.hs
104 lines (88 loc) · 3.5 KB
/
TicTacToe.hs
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
module TicTacToe where
import Board
-- | let the player make a choice
mkChoice :: Choice -> Board -> BoardOrMsg
mkChoice c@(col, row, m) b
| validChoice = Right $ replaceRow r row b
| otherwise = Left $ "Choice " ++ show c ++ " is not allowed."
where validChoice = isValidIndex (col, row) && isEmpty (col, row) b
r = newRow (col, m) (rowAtIndex row b)
currentPlayer :: Board -> Marker
currentPlayer b
| numberOfMarkers b Cross <= numberOfMarkers b Circle = Cross
| otherwise = Circle
checkWinner' :: BoardOrMsg -> Maybe Marker
checkWinner' (Right b) = checkWinnerPure b
checkWinner' (Left msg) = Nothing
checkWinnerPure :: Board -> Maybe Marker
checkWinnerPure b = let res0 = checkRows b in
case res0 of
Just _ -> res0
Nothing -> let res1 = checkCols b in
case res1 of
Just _ -> res1
Nothing -> let res2 = checkDiagonals b in
case res2 of
Just _ -> res2
Nothing -> Nothing
checkRows :: Board -> Maybe Marker
checkRows (BoardCons r0 r1 r2) = let res0 = checkRow r0 in
case res0 of
Just _ -> res0
Nothing -> let res1 = checkRow r1 in
case res1 of
Just _ -> res1
Nothing -> let res2 = checkRow r2 in
case res2 of
Just _ -> res2
Nothing -> Nothing
checkRow :: Row -> Maybe Marker
checkRow (RowCons f0 f1 f2)
| f0 == f1 && f1 == f2 = case f0 of
Empty -> Nothing
(FieldCons Cross) -> Just Cross
(FieldCons Circle) -> Just Circle
| otherwise = Nothing
checkCols :: Board -> Maybe Marker
checkCols b = let res0 = checkFirstCol b in
case res0 of
Just _ -> res0
Nothing -> let res1 = checkSecondCol b in
case res1 of
Just _ -> res1
Nothing -> let res2 = checkThirdCol b in
case res2 of
Just _ -> res2
Nothing -> Nothing
checkFirstCol :: Board -> Maybe Marker
checkFirstCol (BoardCons (RowCons f0 _ _) (RowCons f1 _ _) (RowCons f2 _ _))
| f0 == f1 && f1 == f2 = case f0 of
Empty -> Nothing
(FieldCons Cross) -> Just Cross
(FieldCons Circle) -> Just Circle
| otherwise = Nothing
checkSecondCol :: Board -> Maybe Marker
checkSecondCol (BoardCons (RowCons _ f0 _) (RowCons _ f1 _) (RowCons _ f2 _))
| f0 == f1 && f1 == f2 = case f0 of
Empty -> Nothing
(FieldCons Cross) -> Just Cross
(FieldCons Circle) -> Just Circle
| otherwise = Nothing
checkThirdCol :: Board -> Maybe Marker
checkThirdCol (BoardCons (RowCons _ _ f0) (RowCons _ _ f1) (RowCons _ _ f2))
| f0 == f1 && f1 == f2 = case f0 of
Empty -> Nothing
(FieldCons Cross) -> Just Cross
(FieldCons Circle) -> Just Circle
| otherwise = Nothing
checkDiagonals :: Board -> Maybe Marker
checkDiagonals (BoardCons (RowCons f00 _ f10) (RowCons _ f1 _) (RowCons f12 _ f02))
| f00 == f1 && f1 == f02 = case f00 of
Empty -> Nothing
(FieldCons Cross) -> Just Cross
(FieldCons Circle) -> Just Circle
| f10 == f1 && f1 == f12 = case f10 of
Empty -> Nothing
(FieldCons Cross) -> Just Cross
(FieldCons Circle) -> Just Circle
| otherwise = Nothing