Advertisement
Hanaigi

Untitled

Dec 14th, 2024
30
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.57 KB | None | 0 0
  1. #include <SFML/Graphics.hpp>
  2. #include <array>
  3. #include <iostream>
  4. #include <string>
  5.  
  6. const int WINDOW_SIZE = 600;
  7. const int GRID_SIZE = 3;
  8. const float CELL_SIZE = WINDOW_SIZE / GRID_SIZE;
  9.  
  10. enum class Cell {
  11.     Empty,
  12.     Cross,
  13.     Circle
  14. };
  15.  
  16. enum class Player {
  17.     None,
  18.     Player1,
  19.     Player2
  20. };
  21.  
  22. class Game {
  23. public:
  24.     virtual void resetGame() = 0;
  25.     virtual void resetRound() = 0;
  26.     virtual bool makeMove(int x, int y) = 0;
  27.     virtual void nextTurn() = 0;
  28.     virtual Player getCurrentPlayer() const = 0;
  29.     virtual bool checkRoundEnd() = 0;
  30.     virtual bool checkGameEnd() const = 0;
  31.     virtual void render(sf::RenderWindow& window) = 0;
  32.     virtual ~Game() = default;
  33. };
  34.  
  35. class GameBoard {
  36. private:
  37.     std::array<std::array<Cell, GRID_SIZE>, GRID_SIZE> grid;
  38.  
  39. public:
  40.     GameBoard() { reset(); }
  41.  
  42.     void reset() {
  43.         for (auto& row : grid) {
  44.             for (auto& cell : row) {
  45.                 cell = Cell::Empty;
  46.             }
  47.         }
  48.     }
  49.  
  50.     bool setCell(int x, int y, Cell value) {
  51.         if (grid[y][x] == Cell::Empty) {
  52.             grid[y][x] = value;
  53.             return true;
  54.         }
  55.         return false;
  56.     }
  57.  
  58.     Cell getCell(int x, int y) const {
  59.         return grid[y][x];
  60.     }
  61.  
  62.     Player checkWinner() const {
  63.         for (int i = 0; i < GRID_SIZE; ++i) {
  64.             if (grid[i][0] != Cell::Empty && grid[i][0] == grid[i][1] && grid[i][1] == grid[i][2]) {
  65.                 return grid[i][0] == Cell::Cross ? Player::Player1 : Player::Player2;
  66.             }
  67.             if (grid[0][i] != Cell::Empty && grid[0][i] == grid[1][i] && grid[1][i] == grid[2][i]) {
  68.                 return grid[0][i] == Cell::Cross ? Player::Player1 : Player::Player2;
  69.             }
  70.         }
  71.         if (grid[0][0] != Cell::Empty && grid[0][0] == grid[1][1] && grid[1][1] == grid[2][2]) {
  72.             return grid[0][0] == Cell::Cross ? Player::Player1 : Player::Player2;
  73.         }
  74.         if (grid[0][2] != Cell::Empty && grid[0][2] == grid[1][1] && grid[1][1] == grid[2][0]) {
  75.             return grid[0][2] == Cell::Cross ? Player::Player1 : Player::Player2;
  76.         }
  77.         return Player::None;
  78.     }
  79.  
  80.     bool isFull() const {
  81.         for (const auto& row : grid) {
  82.             for (const auto& cell : row) {
  83.                 if (cell == Cell::Empty) return false;
  84.             }
  85.         }
  86.         return true;
  87.     }
  88. };
  89.  
  90. class TicTacToe : public Game {
  91. private:
  92.     GameBoard board;
  93.     Player currentPlayer;
  94.     int scorePlayer1;
  95.     int scorePlayer2;
  96.     int round;
  97.     Player winner;
  98.  
  99. public:
  100.     TicTacToe() : currentPlayer(Player::Player1), scorePlayer1(0), scorePlayer2(0), round(1), winner(Player::None) {}
  101.  
  102.     TicTacToe(Player startingPlayer) : currentPlayer(startingPlayer), scorePlayer1(0), scorePlayer2(0), round(1), winner(Player::None) {}
  103.  
  104.     void resetGame() override {
  105.         board.reset();
  106.         currentPlayer = Player::Player1;
  107.         scorePlayer1 = 0;
  108.         scorePlayer2 = 0;
  109.         round = 1;
  110.         winner = Player::None;
  111.     }
  112.  
  113.     void resetRound() override {
  114.         board.reset();
  115.         currentPlayer = Player::Player1;
  116.     }
  117.  
  118.     void nextTurn() override {
  119.         currentPlayer = (currentPlayer == Player::Player1) ? Player::Player2 : Player::Player1;
  120.     }
  121.  
  122.     Player getCurrentPlayer() const override {
  123.         return currentPlayer;
  124.     }
  125.  
  126.     bool makeMove(int x, int y) override {
  127.         Cell cellValue = (currentPlayer == Player::Player1) ? Cell::Cross : Cell::Circle;
  128.         return board.setCell(x, y, cellValue);
  129.     }
  130.  
  131.     bool checkRoundEnd() override {
  132.         Player roundWinner = board.checkWinner();
  133.         if (roundWinner != Player::None) {
  134.             if (roundWinner == Player::Player1) ++scorePlayer1;
  135.             if (roundWinner == Player::Player2) ++scorePlayer2;
  136.             winner = roundWinner;
  137.             return true;
  138.         }
  139.         if (board.isFull()) {
  140.             winner = Player::None;
  141.             return true;
  142.         }
  143.         return false;
  144.     }
  145.  
  146.     bool checkGameEnd() const override {
  147.         return scorePlayer1 == 2 || scorePlayer2 == 2;
  148.     }
  149.  
  150.     void render(sf::RenderWindow& window) override {
  151.         sf::RectangleShape line(sf::Vector2f(WINDOW_SIZE, 5));
  152.         line.setFillColor(sf::Color::Black);
  153.         for (int i = 1; i < GRID_SIZE; ++i) {
  154.             line.setPosition(0, i * CELL_SIZE);
  155.             window.draw(line);
  156.             line.setSize(sf::Vector2f(5, WINDOW_SIZE));
  157.             line.setPosition(i * CELL_SIZE, 0);
  158.             window.draw(line);
  159.             line.setSize(sf::Vector2f(WINDOW_SIZE, 5));
  160.         }
  161.  
  162.         for (int y = 0; y < GRID_SIZE; ++y) {
  163.             for (int x = 0; x < GRID_SIZE; ++x) {
  164.                 Cell cell = board.getCell(x, y);
  165.                 if (cell == Cell::Cross) {
  166.                     sf::RectangleShape cross1(sf::Vector2f(CELL_SIZE - 40, 10));
  167.                     cross1.setFillColor(sf::Color::Red);
  168.                     cross1.setOrigin(cross1.getSize().x / 2, cross1.getSize().y / 2);
  169.                     cross1.setPosition(x * CELL_SIZE + CELL_SIZE / 2, y * CELL_SIZE + CELL_SIZE / 2);
  170.                     cross1.setRotation(45);
  171.  
  172.                     sf::RectangleShape cross2(sf::Vector2f(CELL_SIZE - 40, 10));
  173.                     cross2.setFillColor(sf::Color::Red);
  174.                     cross2.setOrigin(cross2.getSize().x / 2, cross2.getSize().y / 2);
  175.                     cross2.setPosition(x * CELL_SIZE + CELL_SIZE / 2, y * CELL_SIZE + CELL_SIZE / 2);
  176.                     cross2.setRotation(-45);
  177.  
  178.                     window.draw(cross1);
  179.                     window.draw(cross2);
  180.                 } else if (cell == Cell::Circle) {
  181.                     sf::CircleShape circle(CELL_SIZE / 2 - 15);
  182.                     circle.setFillColor(sf::Color::Transparent);
  183.                     circle.setOutlineThickness(10);
  184.                     circle.setOutlineColor(sf::Color::Blue);
  185.                     circle.setPosition(x * CELL_SIZE + 15, y * CELL_SIZE + 15);
  186.                     window.draw(circle);
  187.                 }
  188.             }
  189.         }
  190.  
  191.         if (checkGameEnd()) {
  192.             sf::Font font;
  193.             if (!font.loadFromFile("arialmt.ttf")) {
  194.                 std::cerr << "Ошибка загрузки шрифта!" << std::endl;
  195.                 return;
  196.             }
  197.  
  198.             sf::Text winnerText;
  199.             winnerText.setFont(font);
  200.             winnerText.setCharacterSize(50);
  201.             winnerText.setFillColor(sf::Color::Black);
  202.  
  203.             if (scorePlayer1 == 2) {
  204.                 winnerText.setString("Player 1 Wins!");
  205.             } else if (scorePlayer2 == 2) {
  206.                 winnerText.setString("Player 2 Wins!");
  207.             }
  208.  
  209.             winnerText.setPosition(WINDOW_SIZE / 2 - winnerText.getGlobalBounds().width / 2, WINDOW_SIZE / 2 - 50);
  210.             window.draw(winnerText);
  211.  
  212.             sf::RectangleShape button(sf::Vector2f(200, 50));
  213.             button.setFillColor(sf::Color::Green);
  214.             button.setPosition(WINDOW_SIZE / 2 - 100, WINDOW_SIZE / 2 + 50);
  215.  
  216.             sf::Font buttonFont;
  217.             if (!buttonFont.loadFromFile("arialmt.ttf")) {
  218.                 std::cerr << "Ошибка загрузки шрифта для кнопки!" << std::endl;
  219.                 return;
  220.             }
  221.  
  222.             sf::Text buttonText;
  223.             buttonText.setFont(buttonFont);
  224.             buttonText.setString("Restart");
  225.             buttonText.setCharacterSize(30);
  226.             buttonText.setFillColor(sf::Color::White);
  227.             buttonText.setPosition(WINDOW_SIZE / 2 - buttonText.getGlobalBounds().width / 2, WINDOW_SIZE / 2 + 60);
  228.  
  229.             window.draw(button);
  230.             window.draw(buttonText);
  231.         }
  232.     }
  233.  
  234.     bool isRestartButtonClicked(const sf::RenderWindow& window, const sf::Event& event) const {
  235.         if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) {
  236.             sf::Vector2i mousePos = sf::Mouse::getPosition(window);
  237.             sf::FloatRect buttonBounds(WINDOW_SIZE / 2 - 100, WINDOW_SIZE / 2 + 50, 200, 50);
  238.             return buttonBounds.contains(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y));
  239.         }
  240.         return false;
  241.     }
  242. };
  243.  
  244. int main() {
  245.     sf::RenderWindow window(sf::VideoMode(WINDOW_SIZE, WINDOW_SIZE), "Tic Tac Toe");
  246.     TicTacToe game;
  247.  
  248.     while (window.isOpen()) {
  249.         sf::Event event;
  250.         while (window.pollEvent(event)) {
  251.             if (event.type == sf::Event::Closed) {
  252.                 window.close();
  253.             }
  254.  
  255.             if (game.checkGameEnd()) {
  256.                 if (game.isRestartButtonClicked(window, event)) {
  257.                     game.resetGame();
  258.                 }
  259.             } else if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) {
  260.                 sf::Vector2i mousePos = sf::Mouse::getPosition(window);
  261.                 int x = mousePos.x / CELL_SIZE;
  262.                 int y = mousePos.y / CELL_SIZE;
  263.  
  264.                 if (x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE) {
  265.                     if (game.makeMove(x, y)) {
  266.                         if (game.checkRoundEnd()) {
  267.                             if (!game.checkGameEnd()) {
  268.                                 game.resetRound();
  269.                             }
  270.                         } else {
  271.                             game.nextTurn();
  272.                         }
  273.                     }
  274.                 }
  275.             }
  276.         }
  277.  
  278.         window.clear(sf::Color::White);
  279.         game.render(window);
  280.         window.display();
  281.     }
  282.  
  283.     return 0;
  284. }
  285.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement