#Modelling tic-tac-toe board state?

1 messages · Page 1 of 1 (latest)

stoic bolt
#

Wondering what the 'best' or most idiomatic way of modelling a tic-tac-toe board would be.

As of right now I'm using nested tuples to represent a 3x3 grid:

pub type Board {
  Board(rows: #(Row, Row, Row))
}

pub type Row {
  Row(tiles: #(Tile, Tile, Tile))
}

pub type Tile {
  Taken(Player)
  Empty
}

pub type Player {
  PlayerX
  PlayerO
}

pub type Coordinate {
  Coordinate(row: Int, col: Int)
}

But when interacting with the board I found that indexing into specific tiles is a little verbose:


pub fn mark_tile_as_taken(
  board: Board,
  coord: Coordinate,
  player: Player,
) -> Board {
  case coord.row {
    0 -> {
      let old_row = board.rows.0
      let new_row = mark_tile_as_taken_in_row(old_row, coord.col, player)
      Board(#(new_row, board.rows.1, board.rows.2))
    }
    1 -> {
      let old_row = board.rows.1
      let new_row = mark_tile_as_taken_in_row(old_row, coord.col, player)
      Board(#(board.rows.0, new_row, board.rows.2))
    }
    2 -> {
      let old_row = board.rows.2
      let new_row = mark_tile_as_taken_in_row(old_row, coord.col, player)
      Board(#(board.rows.0, board.rows.1, new_row))
    }
    _ -> panic
  }
}

fn mark_tile_as_taken_in_row(row: Row, col: Int, player: Player) -> Row {
  case col {
    0 -> Row(#(Taken(player), row.tiles.1, row.tiles.2))
    1 -> Row(#(row.tiles.0, Taken(player), row.tiles.2))
    2 -> Row(#(row.tiles.0, row.tiles.1, Taken(player)))
    _ -> panic
  }
}

I can't help but feel that including more features, such as proper error-handling, or checking if a player has won will be quite verbose and difficult.

Are there any other tips on modelling my game state? Maybe I'm missing something obvious. Not especially an FP wizard.

Ty!

wind vault
#

I’d probably have a record with 9 fields

#

Or a tuple

#

Maybe have tile have Empty, X, and O variants

#

Basically try and simplify it a bit

stoic bolt
wind vault
#

Yeah seeing as the rules are so simple

stoic bolt
#

It turns out, determining win/tie-condition and adding error-handling was quite easy!

#

I got so scared after the mark_tile_as_taken function, but everything else is mostly smooth sailing with a really neat syntax

#

tyvm!

zenith yacht
#

To wrap board, and player, and whatever else