writings/5/15/2023

(Building Tic Tac Toe with Middle Out Design)

Introduction

In the middle out programming article I explained how a small language can describe your problem space. Here we apply that idea to Tic‑Tac‑Toe using Elm. The DSL expresses a game as data, separating the rules from any interface.

Primitives

The language starts with simple data types. They model only the states that can actually occur so impossible boards are impossible to represent.

`elm type Player = X | O

type Cell = Empty | Mark Player

type alias Position =

-- Exactly three rows and three columns type alias Board = Array (Array Cell)

`

Cell can only be Empty or contain a player mark. Board is always three‑by‑three, ensuring we never hold illegal sizes.

Operations

Operations describe how a board evolves.

`elm emptyBoard : ( Board, Player ) emptyBoard = ( Array.repeat 3 (Array.repeat 3 Empty), X )

place : Position -> ( Board, Player ) -> ( Board, Player ) place pos ( board, current ) = case Array.get pos.row board |> Maybe.andThen (Array.get pos.col) of Just Empty -> let updatedRow = Array.get pos.row board |> Maybe.map (Array.set pos.col (Mark current)) |> Maybe.withDefault (Array.empty)

            newBoard = Array.set pos.row updatedRow board  
            next = if current == X then O else X  
        in  
        ( newBoard, next )  
 
    _ ->  
        ( board, current )  
``` 

These operations guarantee we never overwrite a filled cell and always alternate players.

Evaluator

An evaluator interprets a list of moves.

elm play : List Position -> ( Board, Player ) -> ( Board, Player ) play moves game = List.foldl place game moves

This DSL lets us describe an entire match purely as data.

Playing a Game

`elm exampleMoves : List Position exampleMoves = [ , , , , ]

finalBoard : ( Board, Player ) finalBoard = play exampleMoves emptyBoard `

In an Elm application you could call play from the update function and render the result in the view. Because the game logic lives in a small language, any interface—from command line to web UI—can reuse it.

Conclusion

By designing a language that expresses Tic‑Tac‑Toe, we separate game rules from presentation. Elm's types remove impossible states and the evaluator interprets a sequence of moves. The same middle‑out approach scales to more complex domains.