Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Blockr Part 2: Board

4_blockr_eat_rows.livemd

Blockr Part 2: Board

import IEx.Helpers
alias Blockr.Game.{Board, Tetromino, Canvas}
alias Blockr.Game

Confirm Canvas

Canvas.new([{0, 0}, {21, 11}])
# [for row <- 0..21 do
#   [{row, 0}, {row, 11}]
# end,
# for col <- 1..10 do
#   [{0, col}, {21, col}]
# end]

for row <- 0..21, col <- 0..11, row in [0, 21] or col in [0, 11] do
  {row, col}
end
[
  {0, 0},
  {0, 1},
  {0, 2},
  {0, 3},
  {0, 4},
  {0, 5},
  {0, 6},
  {0, 7},
  {0, 8},
  {0, 9},
  {0, 10},
  {0, 11},
  {1, 0},
  {1, 11},
  {2, 0},
  {2, 11},
  {3, 0},
  {3, 11},
  {4, 0},
  {4, 11},
  {5, 0},
  {5, 11},
  {6, 0},
  {6, 11},
  {7, 0},
  {7, 11},
  {8, 0},
  {8, 11},
  {9, 0},
  {9, 11},
  {10, 0},
  {10, 11},
  {11, 0},
  {11, 11},
  {12, 0},
  {12, 11},
  {13, 0},
  {13, 11},
  {14, 0},
  {14, 11},
  {15, 0},
  {15, 11},
  {16, 0},
  {16, 11},
  {17, 0},
  {17, 11},
  {18, 0},
  {18, 11},
  {19, ...},
  {...},
  ...
]
Board.new().walls
|> Canvas.new()

Show board

game = Board.new()
%Blockr.Game.Board{
  score: 0,
  tetro: %Blockr.Game.Tetromino{name: :z, location: {0, 3}, rotation: 0, color: :green},
  walls: [
    {0, 0},
    {0, 1},
    {0, 2},
    {0, 3},
    {0, 4},
    {0, 5},
    {0, 6},
    {0, 7},
    {0, 8},
    {0, 9},
    {0, 10},
    {0, 11},
    {1, 0},
    {1, 11},
    {2, 0},
    {2, 11},
    {3, 0},
    {3, 11},
    {4, 0},
    {4, 11},
    {5, 0},
    {5, 11},
    {6, 0},
    {6, 11},
    {7, 0},
    {7, 11},
    {8, 0},
    {8, 11},
    {9, 0},
    {9, 11},
    {10, 0},
    {10, 11},
    {11, 0},
    {11, 11},
    {12, 0},
    {12, 11},
    {13, 0},
    {13, 11},
    {14, 0},
    {14, 11},
    {15, 0},
    {15, 11},
    {16, 0},
    {16, 11},
    {17, 0},
    {17, ...},
    {...},
    ...
  ],
  points: MapSet.new([
    {21, 5},
    {0, 10},
    {2, 11},
    {7, 11},
    {21, 9},
    {13, 11},
    {21, 7},
    {0, 7},
    {15, 11},
    {20, 0},
    {3, 11},
    {16, 0},
    {19, 11},
    {15, 0},
    {21, 3},
    {0, 8},
    {21, 11},
    {11, 0},
    {4, 0},
    {0, 1},
    {8, 0},
    {3, 0},
    {0, 4},
    {6, 0},
    {13, 0},
    {1, 11},
    {21, 4},
    {0, 3},
    {9, 11},
    {21, 10},
    {6, 11},
    {2, 0},
    {12, 11},
    {17, 11},
    {7, 0},
    {16, 11},
    {0, 6},
    {21, 6},
    {0, 5},
    {0, 9},
    {0, 11},
    {0, 0},
    {18, 11},
    {8, 11},
    {4, ...},
    {...},
    ...
  ]),
  junkyard: []
}
game
|> Game.left()
|> Game.left()
|> Game.left()
|> Game.right()
|> Game.fall()
|> Board.show()
|> Canvas.new()
Enum.reduce(1..17, game, fn _i, acc -> Game.fall(acc) end)
|> Game.fall()
|> Board.show()
|> Canvas.new()
game2 =
  Enum.reduce(1..50, game, fn _i, acc -> Game.fall(acc) end)
  |> Board.show()
  |> Canvas.new()

Board With Data

board = Board.new()

points = for r <- 17..20, c <- 1..10, do: {r, c}
colors = for r <- 17..20, c <- 1..10, do: {{r, c}, "green"}

board = %{board | points: MapSet.new(points ++ board.walls), junkyard: colors}

board
|> Board.show()
|> Canvas.new()
board.junkyard
|> Map.new()
|> Map.keys()
|> Enum.group_by(fn {r, _c} -> r end)
|> Map.values()
|> Enum.count(fn list -> length(list) == 10 end)
4

Score and doubling

  • 0 row: 0
  • 1 row: 100 2 1 -> 2. 50 * 2
  • 2 rows: 200 2 2 -> 4. 50 * 2 2
  • 3 rows: 400 2 3 -> 8. 50 * 2 3
  • 4 rows: 800 2 4 -> 16. 50 * 2 4
defmodule Double do
  def power(exp) do
    :math.pow(2, exp)
    |> round()
    |> Kernel.*(50)
  end

  def reduce(exp) do
    Enum.reduce(1..exp, 50, fn _i, acc -> acc + acc end)
  end

  def unfold(exp) do
    Stream.unfold(100, fn n -> {n, n * 2} end)
    |> Stream.drop(exp - 1)
    |> Enum.take(1)
    |> hd
  end
end

[
  Enum.map(1..4, &amp;Double.power/1),
  Enum.map(1..4, &amp;Double.reduce/1),
  Enum.map(1..4, &amp;Double.unfold/1)
]
[[100, 200, 400, 800], [100, 200, 400, 800], [100, 200, 400, 800]]

Eat-rows

exclude = [
  {{14, 5}, "green"},
  {{15, 5}, "green"},
  {{18, 5}, "green"}
]

colored_points =
  for(
    row <- 14..19,
    col <- 1..10,
    do: {{row, col}, "green"}
  ) -- exclude

board1 = Board.new(junkyard: colored_points)

board1
|> Board.show()
|> Canvas.new()
defmodule Pacman do
  def eat_completed(board) do
    rows = Enum.group_by(board.junkyard, fn {{row, _col}, _color} -> row end)

    completed =
      rows
      |> Enum.filter(fn {row, list} -> length(list) == 10 end)
      |> Map.new()
      |> Map.keys()

    junkyard =
      Enum.reduce(completed, rows, &amp;eat_row/2)
      |> Map.values()
      |> List.flatten()

    %{board | junkyard: junkyard}
  end

  defp eat_row(row_number, rows) do
    rows
    |> Map.delete(row_number)
    |> Enum.map(fn {rn, list} ->
      if row_number > rn do
        {rn + 1, move_all_down(list)}
      else
        {rn, list}
      end
    end)
    |> Map.new()
  end

  defp move_all_down(points) do
    Enum.map(points, fn {{r, c}, color} -> {{r + 1, c}, color} end)
  end
end

Pacman.eat_completed(board1)
|> Board.show()
|> Canvas.new()
warning: variable "row" is unused (if the variable is not meant to be used, prefix it with an underscore)
  #cell:rmv7mn6l7bwom74b:6: Pacman.eat_completed/1