LoginSignup
4
1

More than 5 years have passed since last update.

【Siv3D】オセロ作ってみた

Posted at

プログラム長い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();
}
4
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1