Incredibly n00b question by a 2 days elm learner

So,
here I am, after years of procedural and oop programming, trying to learn Elm.

I started yesterday, so please be kind with my absolute beginner question.
After reading the guide until the “Command and subscriptions” section, I decided to try and implement a very simple tic tac toe.
What could go wrong, I tought… but now I am stuck, so a feedback would be greatly appreciated (again, please be kind :))

I am at the point where I have to set the turn, after the user clicks a cell.
Here is the code:

https://ellie-app.com/6PNgcHjWVMta1

I may be on a completely wrong path to elm… I would like to know what are your thoughts, and what should I levereage better of the guide.

Best,
Carlo

4 Likes

Hi @carloratm,

now you are in the position where upon message Turn n you will want to set the nth board cell to either X or O. I think that you are on the wrong path with handling Turn 0 to Turn 8 in your update function seperately. Rather I think you will want to handle Turn n and update the n-th list element of model.board. You will also want to toggle board.currentCell whenever you are receiving a Turn n message.

So you are faced with updating the nth element of a list. I suggest mapping over all elements of the list, and only really changing the nth element. Since you do not have access to the element’s index when using List.map, you should be using List.indexedMap which gives you the element as well as the element’s index.

Here is an updated version of your program: https://ellie-app.com/6PPkRN4ZYFWa1

Feel free to ask if you are having any trouble understand my changes. I think you are doing very well!

Thanks a lot!

Got your changes, makes a lot of sense

Simplified to not use List https://ellie-app.com/6PWxDFKYPqra1

And here with Just Value https://ellie-app.com/6PWMXj3Fpppa1

Thanks! really interesting!

I added a check to see if the move is actually possible, otherwise you could overwrite the cell value,
the check I added (during a coffee break):

update : Msg -> Model -> Model
update msg model =
    case msg of
        Turn n ->
            if cellByIndex model.board n == Just Empty then
                { model
                    | board =
                        List.indexedMap
                            (\i prev ->
                                if n == i then
                                    model.currentCell

                                else
                                    prev
                            )
                            model.board
                    , currentCell =
                        if model.currentCell == X then
                            O

                        else
                            X
                }

            else
                model

Got a followup question.
I would now like to write the function to check for a winner.

What is the way to do that? Given that there is no user interaction to call it.

Best,
Carlo

Hi @carloratm,

you could check for a winner after every Turn n message. Suppose you have a function isGameWon : Board -> Bool, you could add a field isWon : Bool to your model and you could update that field every tiem your process a Turn n. You will have to be careful to call isGameWon on updatedBoard instead of model.board so that your change to the board is reflected. The following code illustrates how you can use a let statement to do that:

case msg of
    Turn n ->
        let
            updatedBoard = … -- List.indexedMap etc. like before
        in
        { model | board = updatedBoard, isWon = isGameWon updatedBoard }

If model.isWon is True, you could display a “Game over” label in your UI somewhere.

To check if a game is won, you will probably want to implement that using a long boolean expression, since there are only so many combinations of cell1 == cell2 && cell2 == cell 3 for you to check.

Thanks @aforemny, the

let ... in

was the missing piece for me (I don’t think I have encountered that in the guide :thinking: )

@carloratm I would have expected to find it in the Core Language section of the guide, but I am having trouble finding an introduction to the let statement in the guide either.

Maybe you are willing to bring that up in Github Issues here: https://github.com/evancz/guide.elm-lang.org/issues?

Quickly checking through the guide, first time it’s shown seems to be in Commands and Subscriptions > Time. Most examples in the guide are probably just so simple that they don’t really need to use let ... in.

I have added gameState function.
Also I am generating html cells with List.map.

Version with Maybe Value https://ellie-app.com/6Qw34t8LXzba1

I tried to use list destructuring

gameState board c =
    case Array.toList board of
        c0 :: c1 :: c2 :: c3 :: c4 :: c5 :: c6 :: c7 :: c8 ->
            if c0 == c && c1 == c && c2 == c || c3 == c && c4 == c && c5 == c || c6 == c && c7 == c && c8 == c || c0 == c && c4 == c && c8 == c || c2 == c && c4 == c && c6 == c || c0 == c && c3 == c && c6 == c || c1 == c && c4 == c && c7 == c || c2 == c && c5 == c && c8 == c then
                c
            else
                Nothing
        _ ->
            Nothing

but I was getting error

I am inferring a weird self-referential type for `c0`

BTW. There you have more Tic-Tac-Toe games in Elm https://github.com/rofrol/elm-games#tic-tac-toe or on github https://github.com/search?q=tic-tac-toe+language%3Aelm&type=Code

I just did a tic tac toe in elm last week.
I used a Dict instead of a list or array.
https://ellie-app.com/6Qtkw8k9JM9a1

1 Like

Ah nice video @pianomanfrazier

Thank you all!
Hope to find time to finish my version soon, will share as well

1 Like

Here is my version: https://gitlab.com/2pxsolidblack/elm-tac-toe

Deployed here: https://2pxsolidblack.gitlab.io/elm-tac-toe/
I have done that not looking at your (surely amazing) implementations, so please forgive any elm heresy I might have written.

Best,
Carlo

2 Likes

I have tested it on iphone but had trouble clicking nuttons on the right. Also there is something wrong with layout.

Link to screen record

Yes. I know. I need to fix the css. It is not mobile friendly at all. It works on a desktop. It’s a simple fix I just need to do it. Like a 10 min redo of the layout.

It’s broken on my android as well.

The cells on the right are wrapping to the next line.

@rofrol Fixed it over lunch. https://ellie-app.com/6RCQmKnTq27a1

1 Like

Nice. I like the svg drawn stuff.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.