Browse Source

Tetris basic model

master 0.1.0
Julian Noble 2 years ago
commit
cf00dc57ba
  1. 4
      .formatter.exs
  2. 26
      .gitignore
  3. 21
      README.md
  4. 19
      git.exe.stackdump
  5. 152
      lib/brick.ex
  6. 68
      lib/points.ex
  7. 6
      lib/tetris.ex
  8. 28
      mix.exs
  9. 98
      test/brick_test.exs
  10. 1
      test/test_helper.exs
  11. 7
      test/tetris_test.exs

4
.formatter.exs

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

26
.gitignore vendored

@ -0,0 +1,26 @@
# The directory Mix will write compiled artifacts to.
/_build/
# If you run "mix test --cover", coverage assets end up here.
/cover/
# The directory Mix downloads your dependencies sources to.
/deps/
# Where third-party dependencies like ExDoc output generated docs.
/doc/
# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch
# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump
# Also ignore archive artifacts (built via "mix archive.build").
*.ez
# Ignore package tarball (built via "mix hex.build").
tetris-*.tar
# Temporary files, for example, from tests.
/tmp/

21
README.md

@ -0,0 +1,21 @@
# Tetris
**TODO: Add description**
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `tetris` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:tetris, "~> 0.1.0"}
]
end
```
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at <https://hexdocs.pm/tetris>.

19
git.exe.stackdump

@ -0,0 +1,19 @@
Stack trace:
Frame Function Args
000FFFFBBF0 00180062DF7 (000FFFFBDF8, 00000000002, 00000000002, 000FFFFDE50)
00000000000 00180064EE5 (00000000064, 00000000000, 00000000420, 00000000000)
000FFFFC300 00180136238 (00100000000, 000FFFFC708, 000FFFFC770, 000FFFFC798)
00000000041 0018013186B (00100640281, 00000000000, 00000000000, 000FFFFC770)
000FFFFC798 00180131C75 (000FFFFC770, 000FFFFC798, 001006F6B40, 000FFFFC750)
000FFFFC798 00180218948 (00180111A72, 000FFFFC750, 00180194D3B, 000FFFFC6D8)
000FFFFC798 00100668785 (00180249BA0, 001006E0C1D, 001006EB201, 0018027FF30)
000FFFFC798 001005EF056 (00000000002, 0010068C902, 000000000AC, 00000323731)
00100747200 001005A21A2 (000FFFFCC58, 00000000000, 0010061F260, 0010068D3B0)
00100747200 0010042D381 (0018005DAE7, 008000628B5, 0010060E7D0, 001007477C0)
00100747200 0010040203B (00180249BA0, 00000000000, 001800DB27E, 00000000030)
000FFFFCC58 001004025A3 (000FFFFCC58, 04949435341, 000FFFFCC70, 00180328FE0)
000FFFFCD30 001006686E4 (00000000020, 00000000000, 00180049B25, 000FFFFCC70)
000FFFFCD30 00180049B91 (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFFFF0 00180047716 (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFFFF0 001800477C4 (00000000000, 00000000000, 00000000000, 00000000000)
End of stack trace

152
lib/brick.ex

@ -0,0 +1,152 @@
defmodule Tetris.Brick do
alias Tetris.Points
@x_centre 40
defstruct [
name: :i,
location: {40,0},
rotation: 0,
reflection: false
]
def new(attributes \\ []), do: __struct__(attributes)
def new_random() do
%__MODULE__{
name: random_name(),
location: {40,0},
rotation: random_rotation(),
reflection: random_reflection()
}
end
def random_name() do
~w(i l z o t)a
|> Enum.random()
end
def random_rotation() do
[0, 90, 180, 270]
|> Enum.random()
end
def random_reflection() do
[true, false]
|> Enum.random
end
def left(brick) do
%{brick| location: point_left(brick.location)}
end
def right(brick) do
%{brick| location: point_right(brick.location)}
end
def down(brick) do
%{brick| location: point_down(brick.location)}
end
def point_down({x,y}) do
{x,y+1}
end
def point_left({x,y}) do
{x-1,y}
end
def point_right({x,y}) do
{x+1,y}
end
def spin_90(brick) do
%{brick| rotation: rotate(brick.rotation)}
end
def rotate(270), do: 0
def rotate(degrees), do: degrees + 90
def shape(%{name: :l}) do
[
{2,1},
{2,2},
{2,3}, {3,3}
]
end
def shape(%{name: :i}) do
[
{2,1},
{2,2},
{2,3},
{2,4}
]
end
def shape(%{name: :o}) do
[
{2,2}, {3,2},
{2,3}, {3,3}
]
end
def shape(%{name: :z}) do
[
{2,2},
{2,3}, {3,3},
{3,4}
]
end
def shape(%{name: :t}) do
[
{2,1},
{2,2}, {3,2} ,
{2,3}
]
end
def prepare(brick) do
brick
|> shape
|> Points.rotate(brick.rotation)
|> Points.mirror(brick.reflection)
end
def to_string(brick) do
brick
|> prepare
|> Points.to_string
end
def print(brick) do
brick
|> prepare
|> Points.print
brick
end
def colour(%{name: :i}), do: :blue
def colour(%{name: :l}), do: :green
def colour(%{name: :z}), do: :orange
def colour(%{name: :o}), do: :red
def colour(%{name: :t}), do: :yellow
def x_centre(), do: @x_centre
defimpl Inspect do
import Inspect.Algebra
def inspect(brick, _opts) do
concat([
"\n",
Tetris.Brick.to_string(brick),
"\n",
"location : #{inspect(brick.location)}",
"\n",
"reflection: #{inspect(brick.reflection)}",
"\n",
"rotation : #{inspect(brick.rotation)}"
])
end
end
end

68
lib/points.ex

@ -0,0 +1,68 @@
defmodule Tetris.Points do
def move_to_location(points, {x,y}=_location) do
Enum.map(points,fn {dx, dy} -> {dx + x, dy + y} end )
end
def transpose(points) do
points
|> Enum.map( fn {x,y} -> {y,x} end )
end
def mirror(points) do
points
|> Enum.map( fn{x,y} -> {5-x,y} end )
end
def mirror(points, false), do: points
def mirror(points, true), do: mirror points
def flip(points) do
points
|> Enum.map( fn{x,y} -> {x,5-y} end )
end
def rotate_90(points) do
#by 90 degrees clockwise
points
|> transpose
|> mirror
end
def rotate(points, 0), do: points
def rotate(points, degrees) do
rotate(
rotate_90(points),
degrees - 90
)
end
def with_colour(points, colour) do
Enum.map(points,fn point -> add_colour(point, colour) end)
end
defp add_colour({_x, _y, _c} = point, _colour), do: point
defp add_colour({x,y}, colour), do: {x,y,colour}
#🔴
#⬜
#🟥
def to_string(points) do
map =
points
|> Enum.map(fn key -> {key, "🟥"} end)
|> Map.new()
for y <- (1 .. 4), x <- (1 .. 4) do
Map.get(map,{x,y},"")
end
|> Enum.chunk_every(4)
|> Enum.map(&Enum.join/1)
|> Enum.join("\n")
end
def print(points) do
IO.puts __MODULE__.to_string(points)
points
end
end

6
lib/tetris.ex

@ -0,0 +1,6 @@
defmodule Tetris do
def hello do
:world
end
end

28
mix.exs

@ -0,0 +1,28 @@
defmodule Tetris.MixProject do
use Mix.Project
def project do
[
app: :tetris,
version: "0.1.0",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
]
end
end

98
test/brick_test.exs

@ -0,0 +1,98 @@
defmodule BrickTest do
use ExUnit.Case
import Tetris.Brick
alias Tetris.Points
def new_brick(attributes \\[]), do: new(attributes)
test "Creates a new brick" do
assert new_brick().name == :i
end
test "Create a new random brick" do
actual = new_random()
assert actual.name in [:i, :l, :z, :t, :o]
assert actual.rotation in [0, 90, 180, 270]
assert actual.reflection in [true, false]
end
test "should manipulate brick" do
actual =
new_brick()
|> left
|> right
|> right
|> down
|> spin_90
|> spin_90
assert actual.location == {x_centre() + 1,1}
assert actual.rotation == 180
end
test "should return points for o shape" do
points =
new_brick(name: :o)
|> shape()
assert {3,3} in points
end
test "should translate a list of points" do
actual_points =
new_brick()
|> shape
|> Points.move_to_location({1,1})
|> Points.move_to_location({0,1})
assert actual_points == [{3, 3}, {3, 4}, {3, 5}, {3, 6}]
end
test "should mirror flip rotate and rotate" do
[{1,1}]
|> Points.mirror
|> assert_point({4,1})
|> Points. flip
|> assert_point({4,4})
|> Points.rotate_90
|> assert_point({1,4})
|> Points.rotate_90
|> assert_point({1,1})
end
def assert_point([actual],expected) do
assert actual == expected
[actual]
end
test "should convert brick to string" do
actual = new_brick() |> Tetris.Brick.to_string
expected = "⬜🟥⬜⬜\n⬜🟥⬜⬜\n⬜🟥⬜⬜\n⬜🟥⬜⬜"
assert actual == expected
end
test "should inspect bricks" do
actual = new_brick() |> inspect
expected =
"""
🟥
🟥
🟥
🟥
location : {#{x_centre()}, 0}
reflection: false
rotation : 0
"""
assert "#{actual}\n" == expected
end
end

1
test/test_helper.exs

@ -0,0 +1 @@
ExUnit.start()

7
test/tetris_test.exs

@ -0,0 +1,7 @@
defmodule TetrisTest do
use ExUnit.Case
test "greets the world" do
assert Tetris.hello() == :world
end
end
Loading…
Cancel
Save