Blockr
alias Blockr.Game.{Canvas, Group, Point, Tetromino, Board}
single point
alias Blockr.Game
p =
Point.new(1, 5)
|> Point.move_down()
|> Point.move_down()
|> Point.move_left()
Canvas.new(p)
multiple points
points =
[
Point.new(2, 5),
Point.new(2, 6),
Point.new(3, 4),
Point.new(3, 5)
]
Canvas.new(points)
Big Tetromino
points =
[
Point.new(2, 2),
Point.new(3, 2),
Point.new(4, 2),
Point.new(4, 3)
]
Canvas.tetromino(points)
:s Shape
Tetromino.new(:s)
|> Tetromino.to_group()
|> Canvas.tetromino()
# |> IO.inspect(pretty: true)
:z shape
#CRC = constructor, reducer, converter
Tetromino.new(:z) # constructor
|> Tetromino.rotate_right_90() # reducer
|> Tetromino.left()
|> Tetromino.right()
|> Tetromino.right() # reducer
|> Tetromino.to_group() # converter
|> Group.paint(:z)
# |> Canvas.new()
|> Canvas.tetromino()
Tetromino.new(:t)
|> Tetromino.to_group()
|> Canvas.tetromino()
Canvas with color
Tetromino.new(:z)
|> Tetromino.to_group()
|> Group.paint("green")
|> Canvas.tetromino()
Canvas.draw({1, 1}, 10)
Canvas.draw({{1, 1}, "green"}, 10)
Canvas.draw([{{1, 1}, "green"}, {{1, 2}, "green"}], 10)
Group.paint([{1, 1}, {2, 2}], :l)
Group.paint([{1, 1}, {2, 2}], :l) |> Canvas.draw(10)
Point
Complete through part 1
Next in our implementation:
-
Add a game
Board
-
Add walls to our
Board
-
Add walls to our
-
Enhance
Canvas
dimensions to show walls -
Enhance
Canvas
to show background color -
Add score to our
Board
-
Add
Game.move
,Game.right
and check overlaps when tetromino moves -
Add
Game.fall
and check overlaps when tetromino moves -
Detach
Tetromino
isfall
fails -
Score
Tetromino
iffall
fails -
Remove scored rows on
score
Show-Board
game = Board.new().walls
game = Board.new()
game
|> Game.left()
|> Game.left()
|> Game.left()
|> Game.left()
|> Game.left()
|> Game.left()
|> Board.show()
|> Canvas.new()
game
|> Game.right()
|> Game.right()
|> Game.right()
|> Game.right()
|> Game.right()
|> Game.right()
|> Game.right()
|> Game.right()
|> Board.show()
|> Canvas.new()
game2 =
Enum.reduce(1..74, game, fn _i, acc -> Game.fall(acc) end)
# Enum.reduce(1..15, game2, fn _i, acc -> Game.fall(acc) end)
|> Board.show()
|> Canvas.new()
Within LiveBook, build a board with a junkyard by setting points directly onto the board. This will be important for test purposes.
board = Board.new()
points = for r <- 18..20, c <- 1..10, do: {r, c}
colors = for r <- 18..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(&length(&1) == 10)
completed_rows =
board.junkyard
|> Map.new()
|> Map.keys()
|> Enum.group_by(fn {r, _c} -> r end)
|> Enum.to_list()
|> Enum.filter(fn {_row_num, row_cells} -> length(row_cells) == 10 end)
|> Enum.into(%{})
|> Map.values()
|> List.flatten()
|> Enum.map(fn point -> {point, "white"} end)
board =
%{board| junkyard: completed_rows}
|> Board.show()
|> Canvas.new()
# board.junkyard
~c"\n\n\n\n" == [10, 10, 10, 10]
Score and doubling
- 1 row: 100 2 1 -> 2. 50 * 21 = 100
- 2 row: 200 2 2 -> 4. 50 * 22 = 200
- 3 row: 400 2 3 -> 8. 50 * 23 = 400
- 4 row: 800 2 4 -> 4. 50 * 24 = 800
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() do
Stream.unfold(100, fn n ->
{n, n * 2}
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, &Double.power/1),
Enum.map(1..8, &Double.reduce/1),
Enum.map(1..4, &Double.unfold/1),
Double.unfold() |> Enum.take(4)
# Double.unfold(4)
]
# :math.pow(2, 3)
Double.power(3)
Stream.unfold(5, fn
0 -> nil |> IO.inspect(label: "nil")
n -> {n, n - 1}
end) |> Enum.to_list()
Stream.unfold(1, fn
n -> {n, n * 2}
end) |> Enum.take(10)
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, &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 {{row, col}, color} ->
{{row + 1, col}, color}
end)
end
end
Pacman.eat_completed(board1)
|> Board.show()
|> Canvas.new()