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 <didier...@gmail.com <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 elm-discuss...@googlegroups.com <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 elm-discuss+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.