Current section
Files
Jump to
Current section
Files
lib/board.ex
defmodule Board do
@moduledoc false
def init() do
:empty
|> List.duplicate(3)
|> List.duplicate(3)
end
def move(board, player, x, y) do
new_row_x =
board
|> row(x)
|> List.replace_at(y, player)
List.replace_at(board, x, new_row_x)
end
def winner(board) do
rows_winner = rows_winner(board)
cols_winner = cols_winner(board)
diagonal_winner = diagonals_winner(board)
[rows_winner, cols_winner, diagonal_winner]
|> Enum.sort()
|> Enum.dedup()
|> Enum.at(0)
end
def empty_at?(board, x, y) do
cell =
board
|> Enum.at(x)
|> Enum.at(y)
cell == :empty
end
defp diagonals_winner(board) do
forward_diagonal = forward_diagonal(board)
backward_diagonal = backward_diagonal(board)
rows_winner([forward_diagonal, backward_diagonal])
end
defp forward_diagonal(board) do
length = Enum.count(board)
Enum.map(0..(length - 1), fn i -> cell(board, i, length - 1 - i) end)
end
defp backward_diagonal(board) do
length = Enum.count(board)
Enum.map(0..(length - 1), fn i -> cell(board, i, i) end)
end
defp cols_winner(board) do
board
|> List.zip()
|> Enum.map(&Tuple.to_list/1)
|> rows_winner()
end
defp rows_winner(board) do
board
|> Enum.map(&row_winner/1)
|> Enum.drop_while(fn i -> i == :no_winner end)
|> board_winner()
end
defp board_winner([]), do: :no_winner
defp board_winner(winners), do: List.first(winners)
defp row_winner([:cross, :cross, :cross]), do: :cross
defp row_winner([:circle, :circle, :circle]), do: :circle
defp row_winner(_), do: :no_winner
defp row(board, x), do: Enum.at(board, x)
defp cell(board, x, y) do
board
|> Enum.at(x)
|> Enum.at(y)
end
end