Thanks Peter for your help! I could go further but now, there's another
issue. I would like to display the current player's shape when he clicks on
a cell. The thing is I don't know how to interact with the DOM in this
case. I know how to define an onClick event on each cell (displayed as a
div), but I don't know how to interact with a cell to display a shape in
its div).
Here's my code. Hope you can help me!
import Html.App as App
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
main =
App.program { init = init, update = update, view = view, subscriptions
= \_ -> Sub.none}
type alias Player =
{
id: Int
,name: String
,shape: String
,score: Int
}
type alias Model =
{
player1: Player
,player2: Player
,current: Player
,boxClicked: Maybe Int
}
type alias Box =
{
id: Int
,player: Maybe Player
}
player1: Player
player1 =
{id = 1, name = "Player 1", shape = "X", score = 0 }
player2: Player
player2 =
{id = 2, name = "Player 2", shape = "O", score = 0}
area: List (List Box)
area =
[
[Box 1 Nothing, Box 2 Nothing, Box 3 Nothing]
,[Box 4 Nothing, Box 5 Nothing, Box 6 Nothing]
,[Box 7 Nothing, Box 8 Nothing, Box 9 Nothing]
]
init: (Model, Cmd Msg)
init =
(Model player1 player2 player1 Nothing, Cmd.none)
type Msg = None | ClickBox Int
changePlayer: Player -> Player
changePlayer player =
case player.id of
1 ->
player2
_ ->
player1
filterRow: Int -> List Box -> Maybe Box
filterRow boxId row =
row
|> List.filter (\box -> box.id == boxId)
|> List.head
renderClickedBox: Maybe Int -> String
renderClickedBox boxId =
case boxId of
Nothing -> "No box clicked yet"
Just b -> "Box " ++ (toString b) ++ " clicked"
update: Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
None ->
(model, Cmd.none)
ClickBox boxId ->
let
currentBox = area
|> List.map (filterRow boxId)
currentPlayer = changePlayer model.current
in
(Model model.player1 model.player2 currentPlayer (Just boxId),
Cmd.none)
view: Model -> Html Msg
view model =
div []
[
span[style [("font-weight", "bold")]][text model.player1.name]
,span[style [("text-decoration", "underline")]] [text
(toString(model.player1.score))]
,span[style [("margin-right", "15px")]][]
,span[style [("text-decoration", "underline")]] [text
(toString(model.player2.score))]
,span[style [("font-weight", "bold")]][text model.player2.name]
,div[]
[
area
|> List.map (viewRow model)
|> div[]
]
,div[][text (renderClickedBox model.boxClicked)]
,div[][text model.current.name]
]
viewRow: Model -> List Box -> Html Msg
viewRow model row =
row
|> List.map (\box -> div [id (toString box.id), style (boxStyle
box.player), onClick (ClickBox box.id)][])
|> div[]
boxStyle shape =
[
("border", "1px solid black")
,("width", "64px")
,("height", "64px")
,("display", "inline-block")
]
Le lundi 24 octobre 2016 14:36:48 UTC+2, Peter Damoc a écrit :
>
> You almost got it right. Here is your program with the view altered a
> little bit (I've extracted the row display and the style of the cell)
>
> import Html.App as App
> import Html exposing (..)
> import Html.Attributes exposing(..)
>
> main =
> App.program { init = init, update = update, view = view, subscriptions
> = \_ -> Sub.none}
>
> type alias Player =
> {
> name: String
> ,shape: String
> ,score: Int
> }
>
> type alias Model =
> {
> player1: Player
> ,player2: Player
> }
>
>
> type alias Box =
> {
> id: Int
> ,shape: Maybe Player
> }
>
> area: List (List Box)
> area =
> [
> [Box 1 Nothing, Box 2 Nothing, Box 3 Nothing]
> ,[Box 4 Nothing, Box 5 Nothing, Box 6 Nothing]
> ,[Box 7 Nothing, Box 8 Nothing, Box 9 Nothing]
> ]
>
> init: (Model, Cmd Msg)
> init =
> (Model {name = "Player 1", shape = "X", score = 0 } {name = "Player
> 2", shape = "O", score = 0}, Cmd.none)
>
> type Msg = None
>
> update: Msg -> Model -> (Model, Cmd Msg)
> update msg model =
> case msg of
> None ->
> (model, Cmd.none)
>
> view: Model -> Html Msg
> view model =
> div []
> [
> span[style [("font-weight", "bold")]][text model.player1.name]
> ,span[style [("text-decoration", "underline")]] [text
> (toString(model.player1.score))]
> ,span[style [("margin-right", "15px")]][]
> ,span[style [("text-decoration", "underline")]] [text
> (toString(model.player2.score))]
> ,span[style [("font-weight", "bold")]][text model.player2.name]
> ,div[]
> [
> area
> |> List.map viewRow
> |> div[style [("border", "1px solid black")]]
> ]
> ]
>
>
>
> viewRow : List Box -> Html Msg
> viewRow row =
> div []
> (List.map (\box -> div [id (toString box.id), style (boxStyle
> box.shape)][]) row)
>
>
> boxStyle shape =
> [ ("border", "1px solid black")
> , ("width", "64px")
> , ("height", "64px")
> , ("display", "inline-block")
> ]
>
> On Mon, Oct 24, 2016 at 3:01 PM, Did <[email protected] <javascript:>>
> wrote:
>
>> Hello there!
>>
>> As a newbie, and in order to learn elm, I started to write a tic tac toe
>> game. I wanted to start by drawing the game area but I'm stuck with one
>> thing. I decided that my area was a list of list of Box : List (List Box).
>> A box is defined by an id and maybe a player (so that I can track if a box
>> was filled by a player or not). With procedural languages, I can do
>> something like this:
>>
>> for(var i = 0; i < 3; i++ {
>> for (var j = 0; j < 3,; j++) {
>> drawBox(area[i][j]);
>> }
>> }
>>
>> But I can't figure out how to do this in elm... It does not even compile,
>> but that's because I don't fully understand List.map...
>>
>> Here is the code I started writing. If someone can help me, I would
>> really appreciate!
>>
>> import Html.App as App
>> import Html exposing (..)
>> import Html.Attributes exposing(..)
>>
>> main =
>> App.program { init = init, update = update, view = view,
>> subscriptions = \_ -> Sub.none}
>>
>> type alias Player =
>> {
>> name: String
>> ,shape: String
>> ,score: Int
>> }
>>
>> type alias Model =
>> {
>> player1: Player
>> ,player2: Player
>> }
>>
>>
>> type alias Box =
>> {
>> id: Int
>> ,shape: Maybe Player
>> }
>>
>> area: List (List Box)
>> area =
>> [
>> [Box 1 Nothing, Box 2 Nothing, Box 3 Nothing]
>> ,[Box 4 Nothing, Box 5 Nothing, Box 6 Nothing]
>> ,[Box 7 Nothing, Box 8 Nothing, Box 9 Nothing]
>> ]
>>
>> init: (Model, Cmd Msg)
>> init =
>> (Model {name = "Player 1", shape = "X", score = 0 } {name = "Player
>> 2", shape = "O", score = 0}, Cmd.none)
>>
>> type Msg = None
>>
>> update: Msg -> Model -> (Model, Cmd Msg)
>> update msg model =
>> case msg of
>> None ->
>> (model, Cmd.none)
>>
>> view: Model -> Html Msg
>> view model =
>> div []
>> [
>> span[style [("font-weight", "bold")]][text model.player1.name]
>> ,span[style [("text-decoration", "underline")]] [text
>> (toString(model.player1.score))]
>> ,span[style [("margin-right", "15px")]][]
>> ,span[style [("text-decoration", "underline")]] [text
>> (toString(model.player2.score))]
>> ,span[style [("font-weight", "bold")]][text model.player2.name]
>> ,div[]
>> [
>> area
>> |> List.map
>> |> List.map (\box -> span[id box.id, style [("border", "1px solid
>> black")]][])
>> |> div[style [("border", "1px solid black")]]
>> ]
>> ]
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Elm Discuss" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected] <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
>
> --
> There is NO FATE, we are the creators.
> blog: http://damoc.ro/
>
--
You received this message because you are subscribed to the Google Groups "Elm
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.