Created
January 28, 2020 16:18
-
-
Save MikuroXina/84b564be382457152b47380362bfd78a to your computer and use it in GitHub Desktop.
Tic tac toe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "Board.hpp" | |
| void defaultEndGame(Judge) {} | |
| Board make() { | |
| Board made{}; | |
| for (int y = 0; y < 3; ++y) { | |
| for (int x = 0; x < 3; ++x) { | |
| made.cells[x][y] = Cell::Empty; // マスめの なかみは カラッポ! | |
| } | |
| } | |
| made.next = Stone::X; // 先手はバツ | |
| made.endGame = &defaultEndGame; // 上に書いたデフォルト | |
| return made; | |
| } | |
| std::vector<std::vector<Cell>> cells(Board const *b) { | |
| using std::vector; | |
| vector<vector<Cell>> cells(3, vector<Cell>(3)); | |
| for (int y = 0; y < 3; ++y) { | |
| for (int x = 0; x < 3; ++x) { | |
| cells[x][y] = b->cells[x][y]; | |
| } | |
| } | |
| return cells; | |
| } | |
| Stone next(Board const *b) { return b->next; } | |
| void onEndGame(Board *b, EndGameHandler handler) { b->endGame = handler; } | |
| void judge(Board const *b) { | |
| // 斜め方向 | |
| if ((b->cells[1][1] != Cell::Empty && b->cells[0][0] == b->cells[1][1] && | |
| b->cells[1][1] == b->cells[2][2]) || | |
| (b->cells[1][1] != Cell::Empty && b->cells[0][2] == b->cells[1][1] && | |
| b->cells[1][1] == b->cells[2][0])) { | |
| b->endGame(b->cells[1][1] == Cell::X ? Judge::X : Judge::O); | |
| return; | |
| } | |
| // 水平方向を縦に 3 回 | |
| for (int y = 0; y < 3; ++y) { | |
| if (b->cells[1][y] != Cell::Empty && b->cells[0][y] == b->cells[1][y] && | |
| b->cells[1][y] == b->cells[2][y]) { | |
| b->endGame(b->cells[1][y] == Cell::X ? Judge::X : Judge::O); | |
| return; | |
| } | |
| } | |
| // 垂直方向を横に 3 回 | |
| for (int x = 0; x < 3; ++x) { | |
| if (b->cells[x][1] != Cell::Empty && b->cells[x][0] == b->cells[x][1] && | |
| b->cells[x][1] == b->cells[x][2]) { | |
| b->endGame(b->cells[x][1] == Cell::X ? Judge::X : Judge::O); | |
| return; | |
| } | |
| } | |
| for (int y = 0; y < 3; ++y) { | |
| for (int x = 0; x < 3; ++x) { | |
| if (b->cells[x][y] == Cell::Empty) { // 空のマスがあれば | |
| return; | |
| } | |
| } | |
| } | |
| // 空のマスが無いとここに来る | |
| b->endGame(Judge::Draw); | |
| } | |
| void place(Board *b, int x, int y) { | |
| if (!(0 <= x && x < 3 && 0 <= y && y < 3)) { // x や y が範囲外なら | |
| return; | |
| } | |
| if (b->cells[x][y] != Cell::Empty) { // そのマス目が埋まっているなら | |
| return; | |
| } | |
| if (next(b) == Stone::X) { | |
| b->cells[x][y] = Cell::X; | |
| b->next = Stone::O; | |
| } else { | |
| b->cells[x][y] = Cell::O; | |
| b->next = Stone::X; | |
| } | |
| judge(b); // これは上の勝敗判定の関数 | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #ifndef TTT_BOARD_HPP | |
| #define TTT_BOARD_HPP | |
| // 石 | |
| enum struct Stone { | |
| O, | |
| X, | |
| }; | |
| // マス目 | |
| enum struct Cell { | |
| Empty, | |
| O, | |
| X, | |
| }; | |
| // 勝敗結果 | |
| enum struct Judge { | |
| O, | |
| X, | |
| Draw, | |
| }; | |
| #include <functional> | |
| using EndGameHandler = std::function<void(Judge)>; | |
| struct Board { | |
| Cell cells[3][3]; // 3 x 3 のマス目 | |
| Stone next; // 次に置く石 | |
| EndGameHandler endGame; | |
| }; | |
| // make() は新しい Board のオブジェクトを作って返す | |
| Board make(); | |
| #include <vector> | |
| // cells(b) は b の盤面の二次元 vector を返す | |
| std::vector<std::vector<Cell>> cells(Board const *b); | |
| // next(b) は b へ次に置ける石を返す | |
| Stone next(Board const *b); | |
| // place(b, x, y) は (x, y) へ石を置く | |
| void place(Board *b, int x, int y); | |
| // onEndGame(b, func) は b にゲーム終了時のイベントハンドラ func を登録する | |
| void onEndGame(Board *b, EndGameHandler handler); | |
| #endif // TTT_BOARD_HPP |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <iostream> | |
| #include "Board.hpp" | |
| // Show(b) は b の盤面をコンソールに出力する | |
| void Show(Board const *b) { | |
| auto c = cells(b); | |
| for (int y = 0; y < 3; ++y) { | |
| for (int x = 0; x < 3; ++x) { | |
| switch (c[x][y]) { | |
| case Cell::Empty: | |
| std::cout << " "; | |
| break; | |
| case Cell::O: | |
| std::cout << " O "; | |
| break; | |
| case Cell::X: | |
| std::cout << " X "; | |
| break; | |
| } | |
| if (x != 2) { | |
| std::cout << "|"; | |
| } | |
| } | |
| if (y != 2) { | |
| std::cout << "\n-----------\n"; | |
| } | |
| } | |
| std::cout << std::endl; | |
| } | |
| int main() { | |
| bool endedGame = false; | |
| Board board = make(); | |
| Board *b = &board; | |
| onEndGame(b, [&endedGame](Judge j) { | |
| switch (j) { | |
| case Judge::O: | |
| std::cout << "O の勝ち!\n"; | |
| break; | |
| case Judge::X: | |
| std::cout << "X の勝ち!\n"; | |
| break; | |
| case Judge::Draw: | |
| std::cout << "引き分け!\n"; | |
| break; | |
| } | |
| endedGame = true; | |
| }); | |
| while (!endedGame) { | |
| switch (next(b)) { | |
| case Stone::O: | |
| std::cout << "O の手番\n"; | |
| break; | |
| case Stone::X: | |
| std::cout << "X の手番\n"; | |
| break; | |
| } | |
| Show(b); | |
| int x, y; | |
| std::cin >> x >> y; | |
| place(b, x, y); | |
| } | |
| Show(b); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment