Advertisement
sigmachto

Untitled

May 28th, 2024
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.73 KB | None | 0 0
  1. #include <SFML/Graphics.hpp>
  2. #include <array>
  3. #include <iostream>
  4. #include <string>
  5.  
  6. const int CELL_SIZE = 70;
  7. const int GRID_SIZE = 3;
  8. const int BIG_GRID_SIZE = 3;
  9. const int PADDING = 3;
  10. const int WINDOW_SIZE = CELL_SIZE * GRID_SIZE * BIG_GRID_SIZE + PADDING * (BIG_GRID_SIZE - 1);
  11.  
  12. enum class Player { None, X, O };
  13.  
  14. class SmallGrid {
  15. public:
  16.     SmallGrid() : winner(Player::None) {
  17.         for (auto& row : cells) {
  18.             row.fill(Player::None);
  19.         }
  20.     }
  21.  
  22.     void draw(sf::RenderWindow& window, int offsetX, int offsetY, bool highlight) const {
  23.         // Определяем цвет фона
  24.         sf::Color backgroundColor = (highlight && winner == Player::None) ? sf::Color(200, 200, 200) : sf::Color::White;
  25.  
  26.         // Проверяем, выиграно ли игровое поле
  27.         bool gameWon = (winner != Player::None);
  28.  
  29.         // Если игра выиграна, перекрашиваем весь фон
  30.         if (gameWon) {
  31.             backgroundColor = sf::Color::White;
  32.         }
  33.  
  34.         // Рисуем клетки игрового поля
  35.         for (int y = 0; y < GRID_SIZE; ++y) {
  36.             for (int x = 0; x < GRID_SIZE; ++x) {
  37.                 sf::RectangleShape cellShape(sf::Vector2f(CELL_SIZE, CELL_SIZE));
  38.                 cellShape.setPosition(offsetX + x * CELL_SIZE, offsetY + y * CELL_SIZE);
  39.                 cellShape.setOutlineColor(sf::Color::Black);
  40.                 cellShape.setOutlineThickness(1);
  41.                 cellShape.setFillColor(backgroundColor);
  42.                 window.draw(cellShape);
  43.  
  44.                 // Рисуем крестик или кружочек, если они есть
  45.                 if (cells[y][x] == Player::X) {
  46.                     drawX(window, offsetX + x * CELL_SIZE, offsetY + y * CELL_SIZE);
  47.                 }
  48.                 else if (cells[y][x] == Player::O) {
  49.                     drawO(window, offsetX + x * CELL_SIZE, offsetY + y * CELL_SIZE);
  50.                 }
  51.             }
  52.         }
  53.  
  54.         // Если игра выиграна и нет выделения, рисуем большой символ на белом фоне
  55.         if (gameWon && !highlight) {
  56.             drawLargeSymbol(window, offsetX, offsetY);
  57.         }
  58.     }
  59.  
  60.  
  61.  
  62.     bool isFull() const {
  63.         if (winner != Player::None) return true;
  64.         for (const auto& row : cells) {
  65.             for (const auto& cell : row) {
  66.                 if (cell == Player::None) return false;
  67.             }
  68.         }
  69.         return true;
  70.     }
  71.  
  72.     Player checkWinner() const {
  73.         if (winner != Player::None) return winner;
  74.         // Check rows
  75.         for (int y = 0; y < GRID_SIZE; ++y) {
  76.             if (cells[y][0] != Player::None && cells[y][0] == cells[y][1] && cells[y][1] == cells[y][2]) {
  77.                 winner = cells[y][0];
  78.                 winningLine = { {0, y}, {2, y} };
  79.                 return winner;
  80.             }
  81.         }
  82.         // Check columns
  83.         for (int x = 0; x < GRID_SIZE; ++x) {
  84.             if (cells[0][x] != Player::None && cells[0][x] == cells[1][x] && cells[1][x] == cells[2][x]) {
  85.                 winner = cells[0][x];
  86.                 winningLine = { {x, 0}, {x, 2} };
  87.                 return winner;
  88.             }
  89.         }
  90.         // Check diagonals
  91.         if (cells[0][0] != Player::None && cells[0][0] == cells[1][1] && cells[1][1] == cells[2][2]) {
  92.             winner = cells[0][0];
  93.             winningLine = { {0, 0}, {2, 2} };
  94.             return winner;
  95.         }
  96.         if (cells[0][2] != Player::None && cells[0][2] == cells[1][1] && cells[1][1] == cells[2][0]) {
  97.             winner = cells[0][2];
  98.             winningLine = { {2, 0}, {0, 2} };
  99.             return winner;
  100.         }
  101.         return Player::None;
  102.     }
  103.  
  104.     bool makeMove(int x, int y, Player player) {
  105.         if (cells[y][x] == Player::None && winner == Player::None) {
  106.             cells[y][x] = player;
  107.             return true;
  108.         }
  109.         return false;
  110.     }
  111.  
  112. private:
  113.     std::array<std::array<Player, GRID_SIZE>, GRID_SIZE> cells;
  114.     mutable Player winner;
  115.     mutable std::pair<std::pair<int, int>, std::pair<int, int>> winningLine;
  116.  
  117.     void drawX(sf::RenderWindow& window, int posX, int posY) const {
  118.         sf::RectangleShape line1(sf::Vector2f(CELL_SIZE, 5));
  119.         line1.setFillColor(sf::Color::Red);
  120.         line1.setPosition(posX + 10, posY + 5);
  121.         line1.setRotation(45);
  122.  
  123.         sf::RectangleShape line2(sf::Vector2f(CELL_SIZE, 5));
  124.         line2.setFillColor(sf::Color::Red);
  125.         line2.setPosition(posX + 10, posY + CELL_SIZE - 15);
  126.         line2.setRotation(-45);
  127.  
  128.         window.draw(line1);
  129.         window.draw(line2);
  130.     }
  131.  
  132.     void drawO(sf::RenderWindow& window, int posX, int posY) const {
  133.         sf::CircleShape circle(CELL_SIZE / 2 - 10);
  134.         circle.setPosition(posX + 10, posY + 10);
  135.         circle.setOutlineThickness(5);
  136.         circle.setOutlineColor(sf::Color::Blue);
  137.         circle.setFillColor(sf::Color::Transparent);
  138.         window.draw(circle);
  139.     }
  140.  
  141.     void drawLargeSymbol(sf::RenderWindow& window, int offsetX, int offsetY) const {
  142.         // Определяем цвет фона
  143.         sf::Color backgroundColor = sf::Color::White;
  144.  
  145.         // Рисуем фон
  146.         sf::RectangleShape background(sf::Vector2f(GRID_SIZE * CELL_SIZE, GRID_SIZE * CELL_SIZE));
  147.         background.setPosition(offsetX, offsetY);
  148.         background.setFillColor(backgroundColor);
  149.         window.draw(background);
  150.  
  151.         // Рисуем большой символ
  152.         if (winner == Player::X) {
  153.             drawLargeX(window, offsetX, offsetY);
  154.         }
  155.         else if (winner == Player::O) {
  156.             drawLargeO(window, offsetX, offsetY);
  157.         }
  158.     }
  159.  
  160.  
  161.     void drawLargeX(sf::RenderWindow& window, int offsetX, int offsetY) const {
  162.         sf::RectangleShape line1(sf::Vector2f(GRID_SIZE * CELL_SIZE - 20, 10));
  163.         line1.setFillColor(sf::Color::Red);
  164.         line1.setPosition(offsetX + 10, offsetY + 10);
  165.         line1.setRotation(45);
  166.  
  167.         sf::RectangleShape line2(sf::Vector2f(GRID_SIZE * CELL_SIZE - 20, 10));
  168.         line2.setFillColor(sf::Color::Red);
  169.         line2.setPosition(offsetX + 10, offsetY + GRID_SIZE * CELL_SIZE - 10);
  170.         line2.setRotation(-45);
  171.  
  172.         window.draw(line1);
  173.         window.draw(line2);
  174.     }
  175.  
  176.     void drawLargeO(sf::RenderWindow& window, int offsetX, int offsetY) const {
  177.         sf::CircleShape circle((GRID_SIZE * CELL_SIZE) / 2 - 10);
  178.         circle.setPosition(offsetX + 10, offsetY + 10);
  179.         circle.setOutlineThickness(10);
  180.         circle.setOutlineColor(sf::Color::Blue);
  181.         circle.setFillColor(sf::Color::Transparent);
  182.         window.draw(circle);
  183.     }
  184. };
  185.  
  186. class BigGrid {
  187. public:
  188.     BigGrid() {
  189.         for (auto& row : grids) {
  190.             row.fill(SmallGrid());
  191.         }
  192.     }
  193.  
  194.     void draw(sf::RenderWindow& window, int nextBigX, int nextBigY) const {
  195.         for (int y = 0; y < BIG_GRID_SIZE; ++y) {
  196.             for (int x = 0; x < BIG_GRID_SIZE; ++x) {
  197.                 int offsetX = x * (GRID_SIZE * CELL_SIZE + PADDING);
  198.                 int offsetY = y * (GRID_SIZE * CELL_SIZE + PADDING);
  199.                 bool highlight = (nextBigX == -1 && nextBigY == -1) || (nextBigX == x && nextBigY == y) || isGridFull(nextBigX, nextBigY);
  200.                 grids[y][x].draw(window, offsetX, offsetY, highlight);
  201.             }
  202.         }
  203.  
  204.         // Draw grid lines for the big grid
  205.         sf::RectangleShape line;
  206.         line.setFillColor(sf::Color::Black);
  207.         for (int i = 1; i < BIG_GRID_SIZE; ++i) {
  208.             line.setSize(sf::Vector2f(WINDOW_SIZE, 2));
  209.             line.setPosition(0, i * GRID_SIZE * CELL_SIZE + (i - 1) * PADDING + PADDING / 2);
  210.             window.draw(line);
  211.             line.setSize(sf::Vector2f(2, WINDOW_SIZE));
  212.             line.setPosition(i * GRID_SIZE * CELL_SIZE + (i - 1) * PADDING + PADDING / 2, 0);
  213.             window.draw(line);
  214.         }
  215.     }
  216.  
  217.     bool makeMove(int bigX, int bigY, int smallX, int smallY, Player player) {
  218.         return grids[bigY][bigX].makeMove(smallX, smallY, player);
  219.     }
  220.  
  221.     bool isGridFull(int bigX, int bigY) const {
  222.         return grids[bigY][bigX].isFull();
  223.     }
  224.  
  225.     Player checkGridWinner(int bigX, int bigY) const {
  226.         return grids[bigY][bigX].checkWinner();
  227.     }
  228.  
  229.     bool isGridWon(int bigX, int bigY) const {
  230.         return grids[bigY][bigX].checkWinner() != Player::None;
  231.     }
  232.  
  233.     Player checkBigGridWinner() const {
  234.         for (int y = 0; y < BIG_GRID_SIZE; ++y) {
  235.             if (isGridWon(y, 0) && checkGridWinner(y, 0) == checkGridWinner(y, 1) && checkGridWinner(y, 1) == checkGridWinner(y, 2)) {
  236.                 return checkGridWinner(y, 0);
  237.             }
  238.         }
  239.         for (int x = 0; x < BIG_GRID_SIZE; ++x) {
  240.             if (isGridWon(0, x) && checkGridWinner(0, x) == checkGridWinner(1, x) && checkGridWinner(1, x) == checkGridWinner(2, x)) {
  241.                 return checkGridWinner(0, x);
  242.             }
  243.         }
  244.         if (isGridWon(0, 0) && checkGridWinner(0, 0) == checkGridWinner(1, 1) && checkGridWinner(1, 1) == checkGridWinner(2, 2)) {
  245.             return checkGridWinner(0, 0);
  246.         }
  247.         if (isGridWon(0, 2) && checkGridWinner(0, 2) == checkGridWinner(1, 1) && checkGridWinner(1, 1) == checkGridWinner(2, 0)) {
  248.             return checkGridWinner(0, 2);
  249.         }
  250.         return Player::None;
  251.     }
  252.  
  253.     bool isFull() const {
  254.         for (int y = 0; y < BIG_GRID_SIZE; ++y) {
  255.             for (int x = 0; x < BIG_GRID_SIZE; ++x) {
  256.                 if (!grids[y][x].isFull()) {
  257.                     return false;
  258.                 }
  259.             }
  260.         }
  261.         return true;
  262.     }
  263.  
  264. private:
  265.     std::array<std::array<SmallGrid, BIG_GRID_SIZE>, BIG_GRID_SIZE> grids;
  266. };
  267.  
  268. int main() {
  269.     sf::RenderWindow window(sf::VideoMode(WINDOW_SIZE, WINDOW_SIZE), "Ultimate Tic-Tac-Toe");
  270.  
  271.     BigGrid bigGrid;
  272.     Player currentPlayer = Player::X;
  273.     int nextBigX = -1, nextBigY = -1;
  274.     bool gameOver = false;
  275.     std::string gameOverMessage;
  276.  
  277.     while (window.isOpen()) {
  278.         sf::Event event;
  279.         while (window.pollEvent(event)) {
  280.             if (event.type == sf::Event::Closed)
  281.             {
  282.                 window.close();
  283.             }
  284.             else if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left && !gameOver) {
  285.                 sf::Vector2i mousePos = sf::Mouse::getPosition(window);
  286.                 int bigX = mousePos.x / (GRID_SIZE * CELL_SIZE + PADDING);
  287.                 int bigY = mousePos.y / (GRID_SIZE * CELL_SIZE + PADDING);
  288.                 int smallX = (mousePos.x % (GRID_SIZE * CELL_SIZE + PADDING)) / CELL_SIZE;
  289.                 int smallY = (mousePos.y % (GRID_SIZE * CELL_SIZE + PADDING)) / CELL_SIZE;
  290.  
  291.                 if (bigX >= 0 && bigX < BIG_GRID_SIZE && bigY >= 0 && bigY < BIG_GRID_SIZE &&
  292.                     smallX >= 0 && smallX < GRID_SIZE && smallY >= 0 && smallY < GRID_SIZE &&
  293.                     (nextBigX == -1 && nextBigY == -1 || (bigX == nextBigX && bigY == nextBigY)) &&
  294.                     bigGrid.makeMove(bigX, bigY, smallX, smallY, currentPlayer)) {
  295.  
  296.                     Player currentBigWinner = bigGrid.checkBigGridWinner();
  297.                     if (currentBigWinner != Player::None || bigGrid.isFull()) {
  298.                         gameOver = true;
  299.                         if (currentBigWinner != Player::None) {
  300.                             gameOverMessage = (currentBigWinner == Player::X) ? "X Wins!" : "O Wins!";
  301.                         }
  302.                         else {
  303.                             gameOverMessage = "It's a tie!";
  304.                         }
  305.                     }
  306.                     else
  307.                     {
  308.                         nextBigX = smallX;
  309.                         nextBigY = smallY;
  310.                         currentPlayer = (currentPlayer == Player::X) ? Player::O : Player::X;
  311.                     }
  312.                 }
  313.             }
  314.         }
  315.  
  316.         window.clear(sf::Color::White);
  317.         bigGrid.draw(window, nextBigX, nextBigY);
  318.         if (gameOver)
  319.         {
  320.             sf::Font font;
  321.             if (!font.loadFromFile("arial.ttf"))
  322.             {
  323.                 std::cerr << "Failed to load font file" << std::endl;
  324.                 return EXIT_FAILURE;
  325.             }
  326.             sf::Text text(gameOverMessage, font, 50);
  327.             text.setFillColor(sf::Color::Black);
  328.             sf::FloatRect textRect = text.getLocalBounds();
  329.             text.setOrigin(textRect.left + textRect.width / 2.0f, textRect.top + textRect.height / 2.0f);
  330.             text.setPosition(sf::Vector2f(WINDOW_SIZE / 2.0f, WINDOW_SIZE / 2.0f));
  331.             window.draw(text);
  332.         }
  333.         window.display();
  334.     }
  335.  
  336.     return 0;
  337. }
  338.  
  339.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement