Skip to content

Commit

Permalink
Comments.
Browse files Browse the repository at this point in the history
  • Loading branch information
alexpearce committed Oct 25, 2023
1 parent bd484f6 commit 743c4dd
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 26 deletions.
66 changes: 41 additions & 25 deletions game.exs
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
defmodule Game do
@default_options [
# Number of cells per row and per column.
board_dimensions: {3, 2},
board_dimensions: {4, 4},
# Value of the singular piece present at the beginning of the game.
starting_number: 2,
# Value of the piece randomly inserted into the board at the beginning of
# each turn.
turn_start_number: 1,
# Value of the piece which, when present on the board, results in a win.
winning_number: 4
winning_number: 2048
]
@cell_size 5

def init(opts \\ []) do
opts = Keyword.validate!(opts, @default_options)

# TODO validate that value options are all powers of two and that starting
# and turn start values are both less than winning value.

game = %{
board: starting_board(opts[:board_dimensions], opts[:starting_number]),
score: 0,
Expand Down Expand Up @@ -104,13 +107,11 @@ defmodule Game do
end

defp render_board(%{cells: cells, dimensions: {num_rows, num_cols}}) do
Enum.map(1..num_rows, fn row ->
Enum.map(1..num_cols, fn col ->
Enum.map_join(1..num_rows, "\n", fn row ->
Enum.map_join(1..num_cols, "", fn col ->
render_cell(cells, {row, col})
end)
|> Enum.join("")
end)
|> Enum.join("\n")
end

defp render_cell(cells, coordinate) do
Expand Down Expand Up @@ -151,35 +152,50 @@ defmodule Game do
end

defp merge_values(%{cells: cells} = board, move) do
# For each row, we run a two-pointer algorithm where:
#
# * Pointer #1 iterates through the row.
# * Pointer #2 points to the latest non-empty, non-modified cell behind pointer #1.
#
# As #1 iterates, if its current cell is not empty and:
#
# * Has the same value as the cell of #2: the cell of #1 will be merged into that of #2 (the #2 cell
# value will be doubled and the #1 cell will be emptied) and the #2 pointer will
# be nullified. Or;
# * Does not have the same value as the cell of #2: the #2 pointer
# is updated to point to #1 before #1 continues its iteration.
updates =
rows_for_move(board, move)
|> Enum.map(fn row ->
Enum.map(row, fn coord -> {coord, cells[coord]} end)
end)
|> Enum.flat_map(fn row ->
new_row = Enum.into(row, %{})

{new_row, _} =
Enum.reduce(row, {new_row, nil}, fn {coord, current_value},
{new_row, last_non_empty_coord} ->
if is_nil(current_value) do
{new_row, last_non_empty_coord}
else
if current_value == new_row[last_non_empty_coord] do
{%{new_row | last_non_empty_coord => 2 * current_value, coord => nil}, nil}
else
{new_row, coord}
end
end
end)

Map.to_list(new_row)
end)
|> Enum.flat_map(&merge_row_values(&1))
|> Enum.into(%{})

update_board(board, updates)
end

defp merge_row_values(row) do
# row is a list of {{row, col}, value} elements.
new_row = Enum.into(row, %{})

{new_row, _} =
Enum.reduce(row, {new_row, nil}, fn {coord, current_value},
{new_row, last_non_empty_coord} ->
if is_nil(current_value) do
{new_row, last_non_empty_coord}
else
if current_value == new_row[last_non_empty_coord] do
{%{new_row | last_non_empty_coord => 2 * current_value, coord => nil}, nil}
else
{new_row, coord}
end
end
end)

Map.to_list(new_row)
end

defp move_values(%{cells: cells} = board, move) do
# Conceptually, for each 'row' of values being moved:
# 1. Create a new row with all non-empty cells.
Expand Down
3 changes: 2 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ defmodule TwentyFourtyEight.MixProject do
{:gettext, "~> 0.20"},
{:jason, "~> 1.2"},
{:dns_cluster, "~> 0.1.1"},
{:plug_cowboy, "~> 2.5"}
{:plug_cowboy, "~> 2.5"},
{:credo, "~> 1.7", only: [:dev, :test], runtime: false}
]
end

Expand Down
2 changes: 2 additions & 0 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
%{
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
"castore": {:hex, :castore, "1.0.4", "ff4d0fb2e6411c0479b1d965a814ea6d00e51eb2f58697446e9c41a97d940b28", [:mix], [], "hexpm", "9418c1b8144e11656f0be99943db4caf04612e3eaecefb5dae9a2a87565584f8"},
"cowboy": {:hex, :cowboy, "2.10.0", "ff9ffeff91dae4ae270dd975642997afe2a1179d94b1887863e43f681a203e26", [:make, :rebar3], [{:cowlib, "2.12.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "3afdccb7183cc6f143cb14d3cf51fa00e53db9ec80cdcd525482f5e99bc41d6b"},
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
"cowlib": {:hex, :cowlib, "2.12.1", "a9fa9a625f1d2025fe6b462cb865881329b5caff8f1854d1cbc9f9533f00e1e1", [:make, :rebar3], [], "hexpm", "163b73f6367a7341b33c794c4e88e7dbfe6498ac42dcd69ef44c5bc5507c8db0"},
"credo": {:hex, :credo, "1.7.1", "6e26bbcc9e22eefbff7e43188e69924e78818e2fe6282487d0703652bc20fd62", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "e9871c6095a4c0381c89b6aa98bc6260a8ba6addccf7f6a53da8849c748a58a2"},
"db_connection": {:hex, :db_connection, "2.6.0", "77d835c472b5b67fc4f29556dee74bf511bbafecdcaf98c27d27fa5918152086", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c2f992d15725e721ec7fbc1189d4ecdb8afef76648c746a8e1cad35e3b8a35f3"},
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
"dns_cluster": {:hex, :dns_cluster, "0.1.1", "73b4b2c3ec692f8a64276c43f8c929733a9ab9ac48c34e4c0b3d9d1b5cd69155", [:mix], [], "hexpm", "03a3f6ff16dcbb53e219b99c7af6aab29eb6b88acf80164b4bd76ac18dc890b3"},
Expand Down

0 comments on commit 743c4dd

Please sign in to comment.