-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTicTacToe.elm
92 lines (77 loc) · 2.71 KB
/
TicTacToe.elm
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
module TicTacToe exposing (..)
import TicTacToe.Model exposing (..)
import TicTacToe.VictoryConditions exposing (..)
import Debug
import Array exposing(Array)
import String
import Char
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick)
-- Msg
type Msg = Reset | Play Position
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Reset ->
(newModel, Cmd.none)
Play position ->
case model.state of
Won p -> (model, Cmd.none)
Stalled -> (model, Cmd.none)
GameOn ->
(play model position, Cmd.none)
play : Model -> Position -> Model
play model position =
case get model.board position of
Nothing -> model
Just Empty ->
let --TODO: change functions to use Model instead and pipe through them all
boardAfterPlay = set position model.turn model.board
(stateAfterPlay, winningMove) = detectState model.turn boardAfterPlay
newTurn = switchTurns model.turn
in
{model | board = boardAfterPlay, turn = newTurn, state = stateAfterPlay, winningMove = winningMove}
Just _ ->
model
-- VIEW
view : Model -> Html Msg
view model =
div [] [
h1 [] [text (stateDescription model), resetButton model.state],
table [] (Array.indexedMap (toTableRow model) model.board |> Array.toList)
]
toTableRow : Model -> Int -> Array Slot -> Html Msg
toTableRow model rowIdx row =
tr [] (Array.indexedMap (toTableCell model rowIdx) row |> Array.toList)
toTableCell : Model -> Int -> Int -> Slot -> Html Msg
toTableCell model rowIdx colIdx slot =
td [class (cellClasses (rowIdx, colIdx) model slot), onClick (Play (rowIdx, colIdx))] []
cellClasses : Position -> Model -> Slot -> String
cellClasses pos model slot =
let
winClass = pos |> isWinningMove model.winningMove |> cellColor
playerClass = cellPlayer slot
in
if winClass /= "" then playerClass ++ " " ++ winClass else playerClass
cellColor : Bool -> String
cellColor b =
case b of
False -> ""
True -> "winning-move"
cellPlayer : Slot -> String
cellPlayer s =
case s of
Empty -> ""
PlayedBy p -> toString p
stateDescription : Model -> String
stateDescription model =
case model.state of
GameOn ->
(toString model.turn) ++ "'s turn"
Stalled -> "It's a Draw"
Won p ->
(toString p) ++ " Won"
resetButton : BoardState -> Html Msg
resetButton state =
a [href "javascript:void(0)", onClick Reset, hidden (state == GameOn)] [text (0x27f2 |> Char.fromCode |> String.fromChar)]