6
code:cpp
# include <Siv3D.hpp> // OpenSiv3D v0.2.8
enum class Direction
{
Up,
Right,
Down,
Left
};
constexpr Point ToPoint(Direction direction)
{
switch (direction)
{
case Direction::Up:
return Point::Up();
case Direction::Right:
return Point::Right();
case Direction::Down:
return Point::Down();
default:
return Point::Left();
}
}
enum class MoveType
{
Move,
Merge,
None
};
constexpr MoveType GetMoveType(int32 my, int32 target)
{
if (target == 0 && my != 0)
{
return MoveType::Move;
}
else if ((my != 0) && (my == target))
{
return MoveType::Merge;
}
else
{
return MoveType::None;
}
}
struct AnimationData
{
AnimationData()
{
indices = Grid<Array<int32>>(4, 4);
for (auto i : step(16))
{
}
}
Grid<Array<int32>> indices;
Array<Point> mergePositions;
};
std::pair<Grid<int32>, AnimationData> AllUp(Grid<int32> grid)
{
AnimationData animation;
//move
for (auto x : step(4))
{
for (auto y : Range(1, 3))
{
for (auto i : step(y))
{
const Point targetPos = Point(x, (y - i) - 1);
const Point myPos = Point(x, (y - i));
int32& myValue = gridmyPos; const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
animation.indicesmyPos.clear(); }
}
}
}
//merge
for (auto x : step(4))
{
for (auto y : Range(1, 3))
{
const Point targetPos = Point(x, y - 1);
const Point myPos = Point(x, y);
int32& myValue = gridmyPos; const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Merge)
{
++valueAtTarget;
myValue = 0;
animation.indicesmyPos.clear(); }
}
}
//move
for (auto x : step(4))
{
for (auto y : Range(1, 3))
{
for (auto i : step(y))
{
const Point targetPos = Point(x, (y - i) - 1);
const Point myPos = Point(x, (y - i));
int32& myValue = gridmyPos; const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
animation.indicesmyPos.clear(); }
}
}
}
return { grid, animation };
}
Grid<int32> AllRight(Grid<int32> grid)
{
//move
for (auto y : step(4))
{
for (auto x : { 2, 1, 0 })
{
for (auto i : step(3 - x))
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
}
}
}
}
//merge
for (auto y : step(4))
{
for (auto x : { 2, 1, 0 })
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Merge)
{
++valueAtTarget;
myValue = 0;
}
}
}
//move
for (auto y : step(4))
{
for (auto x : { 2, 1, 0 })
{
for (auto i : step(3 - x))
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
}
}
}
}
return grid;
}
Grid<int32> AllDown(Grid<int32> grid)
{
//move
for (auto x : step(4))
{
for (auto y : {2, 1, 0})
{
for (auto i : step(3 - y))
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
}
}
}
}
//merge
for (auto x : step(4))
{
for (auto y : { 2, 1, 0 })
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Merge)
{
++valueAtTarget;
myValue = 0;
}
}
}
//move
for (auto x : step(4))
{
for (auto y : { 2, 1, 0 })
{
for (auto i : step(3 - y))
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
}
}
}
}
return grid;
}
Grid<int32> AllLeft(Grid<int32> grid)
{
//move
for (auto y : step(4))
{
for (auto x : Range(1, 3))
{
for (auto i : step(x))
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
}
}
}
}
//merge
for (auto y : step(4))
{
for (auto x : Range(1, 3))
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Merge)
{
++valueAtTarget;
myValue = 0;
}
}
}
//move
for (auto y : step(4))
{
for (auto x : Range(1, 3))
{
for (auto i : step(x))
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
}
}
}
}
return grid;
}
Array<Point> GetEmptyPoints(const Grid<int32>& grid)
{
Array<Point> emptyPoints;
for (auto p : step(grid.size()))
{
{
emptyPoints << p;
}
}
return emptyPoints;
}
constexpr std::pair<Color, Color> GetBlockColors(int32 value)
{
constexpr std::array<Color, 12> blockColors =
{
Color(0),
Color(238, 228, 218), // 2
Color(237, 224, 200), // 4
Color(242, 177, 121), // 8
Color(245, 149, 99), // 16
Color(246, 124, 95), // 32
Color(246, 94, 59), // 64
Color(237, 207, 114), // 128
Color(237, 294, 97), // 256
Color(237, 200, 80), // 512
Color(237, 197, 63), // 1024
Color(237, 194, 46), // 2048
};
const Color blockColor = (value < 12) ? blockColorsvalue : Color(60, 58, 50); const Color textColor = (value <= 2) ? Color(119, 110, 101) : Color(249, 246, 242);
return{ blockColor, textColor };
}
constexpr size_t GetFontIndex(int32 value)
{
return value <= 6 ? 0 : value <= 9 ? 1 : value <= 11 ? 2 : 3;
}
void Main()
{
Graphics::SetBackground(ColorF(0.8, 0.9, 1.0));
constexpr double CellSize = 100.0;
const std::array<Font, 4> fonts =
{
Font(46, Typeface::Heavy),
Font(38, Typeface::Heavy),
Font(30, Typeface::Heavy),
Font(28, Typeface::Heavy),
};
Grid<int32> grid(4, 4);
{
Array<Point> initialSpawnPoints = Range(0, 15).asArray().choice(2).map([](int32 n) { return Point(n%4, n/4); });
for (auto& spawnPoint : initialSpawnPoints)
{
}
}
bool isGameOver = false;
while (System::Update())
{
Optional<Direction> direction;
if (KeyUp.down())
{
direction = Direction::Up;
}
else if (KeyRight.down())
{
direction = Direction::Right;
}
else if (KeyDown.down())
{
direction = Direction::Down;
}
else if (KeyLeft.down())
{
direction = Direction::Left;
}
if (direction)
{
Grid<int32> oldGrid = grid;
AnimationData animation;
Print << animation.indices;
if (direction == Direction::Up)
{
std::tie(grid, animation) = AllUp(grid);
}
else if (direction == Direction::Right)
{
//grid = AllRight(grid);
}
else if (direction == Direction::Down)
{
//grid = AllDown(grid);
}
else if (direction == Direction::Left)
{
//grid = AllLeft(grid);
}
Print << animation.indices;
if(grid != oldGrid)
{
const Array<Point> emptyPoints = GetEmptyPoints(grid);
if (!emptyPoints)
{
isGameOver = true;
}
else
{
const Point spawnPoint = emptyPoints.choice();
}
}
}
{
Transformer2D t(Mat3x2::Translate(120, 40));
RectF(400).stretched(5).rounded(3).draw(ColorF(0.5));
for (auto p : step(Size(4, 4)))
{
const int32 value = gridp; const RectF rect(p * CellSize, CellSize);
if (value)
{
rect.stretched(-5).rounded(3).draw(blockColor);
}
else
{
rect.stretched(-5).rounded(3).draw(ColorF(0.6));
}
}
}
if (isGameOver)
{
Window::ClientRect().draw(ColorF(1.0, 0.5));
}
}
}
https://gyazo.com/689ef77136d84d6039e8dcabf1d05748