Skip to content

Instantly share code, notes, and snippets.

@chobby

chobby/Main.cpp Secret

Last active October 20, 2018 19:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chobby/ac1808b920f348693e3d022ff14c57a9 to your computer and use it in GitHub Desktop.
Save chobby/ac1808b920f348693e3d022ff14c57a9 to your computer and use it in GitHub Desktop.
# include <Siv3D.hpp> // OpenSiv3D v0.3.0
enum class State
{
None,
Black,
White
};
State GetOpposite(const State& state)
{
if (state == State::Black)
{
return State::White;
}
else if (state == State::White)
{
return State::Black;
}
else
{
return State::None;
}
}
bool IsIn(const Point& pos)
{
return pos.x >= 0 && pos.x < 8 && pos.y >= 0 && pos.y < 8;
}
Array<Point> GetPlacablePositions(const Grid<State>& data, const State& state)
{
Array<Point> result;
const Array<Point> directions = { {-1, -1},{0, -1},{1, -1},{-1, 0},{1, 0},{-1, 1},{0, 1},{1, 1} };
Grid<bool> placable(8, 8);
placable.fill(false);
for (auto i : step(Size(8, 8)))
{
if (data[i] == state)
{
for (const auto& direction : directions)
{
const auto pos = i + direction;
if (IsIn(pos))
{
if (data[pos] == GetOpposite(state))
{
Point nextPos = pos;
for (int k = 0; k < 8; ++k)
{
nextPos += direction;
if (!IsIn(nextPos))
{
break;
}
if (data[nextPos] == State::None)
{
placable[nextPos] = true;
break;
}
else if(data[nextPos] == state)
{
break;
}
}
}
}
}
}
}
for (auto i : step(Size(8, 8)))
{
if (placable[i])
result.push_back(i);
}
return result;
}
Array<Point> GetTurnPositions(const Grid<State>& data, const State& state, const Point& tPos)
{
Array<Point> result;
const Array<Point> directions = { {-1, -1},{0, -1},{1, -1},{-1, 0},{1, 0},{-1, 1},{0, 1},{1, 1} };
Grid<bool> turnable(8, 8);
turnable.fill(false);
for (const auto& direction : directions)
{
const auto pos = tPos + direction;
if (IsIn(pos))
{
if (data[pos] == GetOpposite(state))
{
Array<Point> buffer;
Point nextPos = pos;
for (int k = 0; k < 8; ++k)
{
if (!IsIn(nextPos))
{
break;
}
if (data[nextPos] == GetOpposite(state))
{
buffer.push_back(nextPos);
}
else if (data[nextPos] == state)
{
for (const auto& a : buffer)
{
turnable[a] = true;
}
break;
}
else
{
break;
}
nextPos += direction;
}
}
}
}
for (auto i : step(Size(8, 8)))
{
if (turnable[i])
result.push_back(i);
}
return result;
}
void Main()
{
Graphics::SetBackground(Color(34, 42, 44));
const Font font(60);
const Size cellSize(70, 70);
Grid<State> data(8, 8);
data[3][3] = State::White;
data[3][4] = State::Black;
data[4][3] = State::Black;
data[4][4] = State::White;
State currentTurn = State::Black;
State playerState = State::None;
Grid<int32> evaluationBoard =
{
{500, -10, 5, 3, 3, 5, -10, 500},
{-10, -100, 3, 1, 1, 3, -100, -10},
{5, 3, 10, 3, 3, 10, 3, 5},
{3, 1, 3, 30, 30, 3, 1, 3},
{3, 1, 3, 30, 30, 3, 1, 3},
{5, 3, 10, 3, 3, 10, 3, 5},
{-10, -100, 3, 1, 1, 3, -100, -10},
{500, -10, 5, 3, 3, 5, -10, 500}
};
bool opening = true;
Stopwatch t;
while (System::Update())
{
for (auto i : step(Size(8, 8)))
{
const Vec2 pos = Window::Center() - cellSize * 4 + i * cellSize;
const RectF rect = RectF(pos, cellSize);
rect.stretched(-2.0).draw(Color(8, 159, 44));
}
if (opening)
{
font(U"オセロ!").drawAt(Window::Center() + Vec2(0.0, -100));
if (SimpleGUI::ButtonAt(U"黒(先手)", Window::Center() + Vec2(-100.0, 0.0)))
{
playerState = State::Black;
t.restart();
opening = false;
}
if (SimpleGUI::ButtonAt(U"白(後手)", Window::Center() + Vec2(100.0, 0.0)))
{
playerState = State::White;
t.restart();
opening = false;
}
}
else
{
Array<Point> placable = GetPlacablePositions(data, currentTurn);
if (placable.size() == 0)
{
const auto nextTurn = GetOpposite(currentTurn);
if (GetPlacablePositions(data, nextTurn).size() == 0)
{
currentTurn = State::None;
}
else
{
currentTurn = nextTurn;
}
}
else
{
if (currentTurn == playerState)
{
for (auto i : placable)
{
const Vec2 pos = Window::Center() - cellSize * 4 + i * cellSize;
const RectF rect = RectF(pos, cellSize);
if (rect.leftClicked())
{
data[i] = currentTurn;
const auto turnable = GetTurnPositions(data, currentTurn, i);
for (const auto pos : turnable)
{
data[pos] = currentTurn;
}
currentTurn = GetOpposite(currentTurn);
t.restart();
}
}
}
else
{
if (t.ms() > 1000)
{
Array<std::pair<Point, int32>> values;
for (const auto& p : placable)
{
const auto turnables = GetTurnPositions(data, currentTurn, p);
int32 sum = 0;
for (const auto& t : turnables)
{
sum += evaluationBoard[t];
}
values.emplace_back(p, sum);
}
values.shuffle();
std::sort(values.begin(), values.end(), [](const std::pair<Point, int32>& a, const std::pair<Point, int32>& b) {return a.second < b.second; });
data[values[0].first] = currentTurn;
const auto turnable = GetTurnPositions(data, currentTurn, values[0].first);
for (const auto pos : turnable)
{
data[pos] = currentTurn;
}
currentTurn = GetOpposite(currentTurn);
t.restart();
}
}
}
for (auto i : step(Size(8, 8)))
{
const Vec2 pos = Window::Center() - cellSize * 4 + i * cellSize;
if (data[i] == State::Black)
{
Circle(pos + cellSize / 2.0, 30).draw(Palette::Black);
}
else if (data[i] == State::White)
{
Circle(pos + cellSize / 2.0, 30).draw(Palette::White);
}
}
if (currentTurn == playerState)
{
for (const auto& p : placable)
{
const Vec2 pos = Window::Center() - cellSize * 4 + p * cellSize;
Circle(pos + cellSize / 2.0, 20).drawFrame(5.0, ColorF(1.0, 0.5));
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment