【Siv3D】オセロ作ってみた

プログラム長いorz
プログラム見にくいorz
AIとかないorz
オブジェクト指向じゃないorz

Siv3D二日目
まだまだ勉強しないとな((o(´∀｀)o))ﾜｸﾜｸ

```Main.cpp
#include <Siv3D.hpp>

namespace rev {
	class Color {
		int color;
	public:
		static const auto EMPTY = 0;
		static const auto WHITE = 1;
		static const auto BLACK = 2;
		static const auto WALL = 3;

		Color() { set(EMPTY); }
		Color(int color) { set(color); }
		int get() { return color; }
		Color& set(int color) { this->color = color;; return *this; }
		Color c(int color) { return Color(color); }
		Color& reversi() { color = 3 - color; return *this; }
		Color getReversi() { return Color(3 - color); }

		auto drawColor() { return drawColor(color); }
		static s3d::Color drawColor(Color color) {
			return color.get() == WHITE ? Palette::White : Palette::Black;
		}
	};

	class Tile {
	public:
		static const auto SIZE = 32;
		Color color;
		void draw(Vec2 pos) {
			if (color.get() == Color::WALL) return;
			Rect(pos.x,pos.y, SIZE).drawFrame(3,0,Palette::Black);
			if (color.get() == Color::EMPTY) return;
			Circle(pos.x + SIZE / 2, pos.y + SIZE / 2, SIZE / 2.7).draw(color.drawColor());
		}
		bool click(Vec2 pos) {
			return Circle(pos.x + SIZE / 2, pos.y + SIZE / 2, SIZE / 2.7).leftPressed;
		}
		bool mouseOver(Vec2 pos) {
			return Circle(pos.x + SIZE / 2, pos.y + SIZE / 2, SIZE / 2.7).mouseOver;
		}
		bool draw(Vec2 pos, s3d::Color color,int size = SIZE) {
			Rect(pos.x, pos.y, size).drawFrame(3, 0, Palette::Black);
			Circle(pos.x + size / 2, pos.y + size / 2, size / 2.7).draw(color);
			return Circle(pos.x + size / 2, pos.y + size / 2, size / 2.7).leftPressed;
			
		}
	};

	class Board {
		Array<Tile> tiles;
	public:
		static const auto SIZE_X = 10;
		static const auto SIZE_Y = 10;
		static const auto SIZE = SIZE_X * SIZE_Y;

		Board() {
			Color c;
			Array<int,SIZE> tmpTiles = {
				3,3,3,3,3,3,3,3,3,3,
				3,0,0,0,0,0,0,0,0,3,
				3,0,0,0,0,0,0,0,0,3,
				3,0,0,0,0,0,0,0,0,3,
				3,0,0,0,1,2,0,0,0,3,
				3,0,0,0,2,1,0,0,0,3,
				3,0,0,0,0,0,0,0,0,3,
				3,0,0,0,0,0,0,0,0,3,
				3,0,0,0,0,0,0,0,0,3,
				3,3,3,3,3,3,3,3,3,3,
			};

			tiles.clear();

			for (int color : tmpTiles) {
				Tile tile;
				tile.color.set(color);
				tiles.push_back(tile);
			}
		}
		Tile &getTile(Vec2 pos) { return tiles[pos.y * SIZE_X + pos.x]; }
		void draw() {
			for (auto y = 0;y < SIZE_Y;y++) {
				for (auto x = 0;x < SIZE_X;x++) {
					getTile(Vec2(x, y)).draw({ x * Tile::SIZE,y * Tile::SIZE });
				}
			}
		}
		void drawMovableTile(Color c) {
			auto mp = getMovablePoints(c);
			for (auto p : mp) {
				getTile(p).draw(p*Tile::SIZE, c.drawColor().setAlpha(128));
				if (getTile(p).mouseOver(p*Tile::SIZE)) getTile(p).draw(p*Tile::SIZE, c.drawColor().setAlpha(64));
			}
		}

		Vec2 clickTile() {
			for (auto y = 0;y < SIZE_Y;y++) {
				for (auto x = 0;x < SIZE_X;x++) {
					if (getTile(Vec2(x, y)).click({ x * Tile::SIZE,y * Tile::SIZE })) return{ x,y };
				}
			}
			return{ -1,-1 };
		}

		bool move(Vec2 pos, Color c, bool back = false) {
			Array<bool> results;
			results.push_back(angleMove(pos, { 1,0 }, c, back));
			results.push_back(angleMove(pos, { -1,0 }, c, back));
			results.push_back(angleMove(pos, { 0,1 }, c, back));
			results.push_back(angleMove(pos, { 0,-1 }, c, back));
			results.push_back(angleMove(pos, { 1,1 }, c, back));
			results.push_back(angleMove(pos, { -1,1 }, c, back));
			results.push_back(angleMove(pos, { 1,-1 }, c, back));
			results.push_back(angleMove(pos, { -1,-1 }, c, back));

			for (auto result : results) { if (result) { back ? getTile(pos).color.set(c.get()) : 0; return true; } }
			return false;
		}

		bool angleMove(Vec2 start, Vec2 angle, Color c, bool back = false) {
			if (back) { if (!angleMove(start, angle, c)) { return false; } }
			if (getTile(start).color.get() != Color::EMPTY) return false;
			if (getTile(start + angle).color.get() != c.getReversi().get()) return false;
			Vec2 pos = start + angle;
			while (getTile(pos).color.get() == c.getReversi().get())
			{
				if (back) getTile(pos).color.reversi();
				pos += angle;
			}
			if (getTile(pos).color.get() != c.get()) return false;
			return true;
		}

		Array<Vec2> getMovablePoints(Color c) {
			Array<Vec2> result;
			for (auto y = 0;y < SIZE_Y;y++) {
				for (auto x = 0;x < SIZE_X;x++) {
					if (move({ x,y }, c)) result.push_back({x,y});
				}
			}
			return result;
		}

		bool tileSearch(Color c) {
			for (auto t : tiles) {
				if (t.color.get() == c.get()) return true;
			}
			return false;
		}

		int tileNum(Color c) {
			auto result = 0;
			for (auto t : tiles) {
				if (t.color.get() == c.get()) result++;
			}
			return result;
		}
	};

	class Reversi {
		Board board;
		GUI pass;
		GUI result;
	public:
		Color turn;

		Reversi() {
			Graphics::SetBackground(Palette::Green);
			Window::SetTitle(L"Reversi");
			turn = turn.BLACK;
			GUIStyle style = GUIStyle::Default;
			style.width = 200;
			pass = GUI(style);
			pass.setTitle(L"あなたは置けません。");
			pass.add(L"OK", GUIButton::Create(L"パスする"));
			pass.setCenter(Window::Center());
			pass.hide();
			result = GUI(GUIStyle::Default);
			result.setTitle(L"ゲーム終了");
			result.add(L"result", GUIText::Create(L"", 300));
			result.add(L"play", GUIButton::Create(L"もう一度プレイ"));
			result.add(L"exit", GUIButton::Create(L"終了"));
			result.hide();
		}
		void main() {
			while (System::Update()) {
				ClearPrint();
				board.draw();
				board.drawMovableTile(turn);
				Vec2 click = board.clickTile();
				click.x != -1 ? board.move(click, turn, true) ? turn.reversi() : 0 : 0 ;
				if (board.getMovablePoints(turn).size() == 0) {
					if (board.getMovablePoints(turn.getReversi()).size() == 0) {
						result.show();
						result.text(L"result").text = Format(L"黒：",board.tileNum(Color::BLACK),L"\n白：",board.tileNum(Color::WHITE),L"\n", board.tileNum(Color::BLACK) == board.tileNum(Color::WHITE) ? L"引き分け" : board.tileNum(Color::BLACK) > board.tileNum(Color::WHITE) ? L"黒の勝ち" : L"白の勝ち");
						if (result.button(L"play").pushed) {
							*this = Reversi();
						}
						if (result.button(L"exit").pushed) {
							System::Exit();
						}
					}else{
						pass.show();
						if (pass.button(L"OK").pushed) {
							turn.reversi();
							pass.hide();
						}
					}
				}
			}
		}
	};
}

void Main() {
	rev::Reversi game;
	game.main();
}
```