-
Notifications
You must be signed in to change notification settings - Fork 1
/
Board.elm
156 lines (105 loc) · 3.02 KB
/
Board.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
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
147
148
149
150
151
152
153
154
155
156
module Board exposing (..)
import Html
import Html exposing (Html, div, table, tr, td, text)
import Html.Events exposing (onClick)
import Html.Attributes exposing (style)
import Light
import List
import Random
-- MODEL
type alias Coords =
( Int, Int )
type alias Board =
List (List Light.Model)
type alias Model =
{ board : Board, moves : Int }
type alias DifficultyLevel =
Int
init : DifficultyLevel -> ( Model, Cmd Msg )
init difficulty =
let
randomStartCmd =
Random.generate NewBoard (randomStart difficulty)
model =
{ board = emptyBoard, moves = 0 }
in
( model, randomStartCmd )
emptyBoard =
Light.init
|> List.repeat 5
|> List.repeat 5
randomCoords : Random.Generator Coords
randomCoords =
let
randomCoord =
Random.int 0 4
in
Random.pair randomCoord randomCoord
randomStart : DifficultyLevel -> Random.Generator Board
randomStart difficulty =
randomCoords
|> Random.list difficulty
|> Random.map (List.foldl toggleAt emptyBoard)
neighbors : Coords -> List Coords
neighbors ( i, j ) =
[ ( i, j ), ( i - 1, j ), ( i + 1, j ), ( i, j - 1 ), ( i, j + 1 ) ]
isWon : Board -> Bool
isWon board =
not (List.member Light.On (List.concat board))
indexedMap : (Coords -> a -> b) -> List (List a) -> List (List b)
indexedMap f board =
board
|> List.indexedMap (\i row -> row |> List.indexedMap (\j cellModel -> f ( i, j ) cellModel))
toggleAt : Coords -> Board -> Board
toggleAt coords board =
indexedMap
(\( i, j ) cellModel ->
if (List.member ( i, j ) (neighbors coords)) then
(Light.update Light.Toggle cellModel)
else
cellModel
)
board
-- Update
type Msg
= ToggleAt Coords Light.Msg
| NewBoard Board
update : Msg -> Model -> ( Model, Cmd Msg )
update message ({ board, moves } as model) =
let
newModel =
case message of
NewBoard newBoard ->
{ model | board = newBoard }
ToggleAt coords _ ->
{ model | board = toggleAt coords board, moves = moves + 1 }
in
newModel ! []
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
-- VIEW
view : Float -> Model -> Html Msg
view cellSize model =
let
lightCellSize =
toString cellSize
cellStyle =
style
[ ( "width", lightCellSize ++ "px" )
, ( "height", lightCellSize ++ "px" )
]
rows =
List.indexedMap
(\i row -> tr [] (row |> List.indexedMap (\j cellModel -> td [ cellStyle ] [ (renderLight ( i, j ) cellModel) ])))
model.board
lightsTable =
table [] rows
in
table [] rows
renderLight : Coords -> Light.Model -> Html Msg
renderLight ( i, j ) cellModel =
cellModel
|> Light.view
|> Html.map (ToggleAt ( i, j ))