Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <SFML/Graphics.hpp>
- #include <array>
- #include <iostream>
- #include <string>
- const int CELL_SIZE = 70;
- const int GRID_SIZE = 3;
- const int BIG_GRID_SIZE = 3;
- const int PADDING = 3;
- const int WINDOW_SIZE = CELL_SIZE * GRID_SIZE * BIG_GRID_SIZE + PADDING * (BIG_GRID_SIZE - 1);
- enum class Player { None, X, O };
- class SmallGrid {
- public:
- SmallGrid() : winner(Player::None) {
- for (auto& row : cells) {
- row.fill(Player::None);
- }
- }
- void draw(sf::RenderWindow& window, int offsetX, int offsetY, bool highlight) const {
- // Определяем цвет фона
- sf::Color backgroundColor = (highlight && winner == Player::None) ? sf::Color(200, 200, 200) : sf::Color::White;
- // Проверяем, выиграно ли игровое поле
- bool gameWon = (winner != Player::None);
- // Если игра выиграна, перекрашиваем весь фон
- if (gameWon) {
- backgroundColor = sf::Color::White;
- }
- // Рисуем клетки игрового поля
- for (int y = 0; y < GRID_SIZE; ++y) {
- for (int x = 0; x < GRID_SIZE; ++x) {
- sf::RectangleShape cellShape(sf::Vector2f(CELL_SIZE, CELL_SIZE));
- cellShape.setPosition(offsetX + x * CELL_SIZE, offsetY + y * CELL_SIZE);
- cellShape.setOutlineColor(sf::Color::Black);
- cellShape.setOutlineThickness(1);
- cellShape.setFillColor(backgroundColor);
- window.draw(cellShape);
- // Рисуем крестик или кружочек, если они есть
- if (cells[y][x] == Player::X) {
- drawX(window, offsetX + x * CELL_SIZE, offsetY + y * CELL_SIZE);
- }
- else if (cells[y][x] == Player::O) {
- drawO(window, offsetX + x * CELL_SIZE, offsetY + y * CELL_SIZE);
- }
- }
- }
- // Если игра выиграна и нет выделения, рисуем большой символ на белом фоне
- if (gameWon && !highlight) {
- drawLargeSymbol(window, offsetX, offsetY);
- }
- }
- bool isFull() const {
- if (winner != Player::None) return true;
- for (const auto& row : cells) {
- for (const auto& cell : row) {
- if (cell == Player::None) return false;
- }
- }
- return true;
- }
- Player checkWinner() const {
- if (winner != Player::None) return winner;
- // Check rows
- for (int y = 0; y < GRID_SIZE; ++y) {
- if (cells[y][0] != Player::None && cells[y][0] == cells[y][1] && cells[y][1] == cells[y][2]) {
- winner = cells[y][0];
- winningLine = { {0, y}, {2, y} };
- return winner;
- }
- }
- // Check columns
- for (int x = 0; x < GRID_SIZE; ++x) {
- if (cells[0][x] != Player::None && cells[0][x] == cells[1][x] && cells[1][x] == cells[2][x]) {
- winner = cells[0][x];
- winningLine = { {x, 0}, {x, 2} };
- return winner;
- }
- }
- // Check diagonals
- if (cells[0][0] != Player::None && cells[0][0] == cells[1][1] && cells[1][1] == cells[2][2]) {
- winner = cells[0][0];
- winningLine = { {0, 0}, {2, 2} };
- return winner;
- }
- if (cells[0][2] != Player::None && cells[0][2] == cells[1][1] && cells[1][1] == cells[2][0]) {
- winner = cells[0][2];
- winningLine = { {2, 0}, {0, 2} };
- return winner;
- }
- return Player::None;
- }
- bool makeMove(int x, int y, Player player) {
- if (cells[y][x] == Player::None && winner == Player::None) {
- cells[y][x] = player;
- return true;
- }
- return false;
- }
- private:
- std::array<std::array<Player, GRID_SIZE>, GRID_SIZE> cells;
- mutable Player winner;
- mutable std::pair<std::pair<int, int>, std::pair<int, int>> winningLine;
- void drawX(sf::RenderWindow& window, int posX, int posY) const {
- sf::RectangleShape line1(sf::Vector2f(CELL_SIZE, 5));
- line1.setFillColor(sf::Color::Red);
- line1.setPosition(posX + 10, posY + 5);
- line1.setRotation(45);
- sf::RectangleShape line2(sf::Vector2f(CELL_SIZE, 5));
- line2.setFillColor(sf::Color::Red);
- line2.setPosition(posX + 10, posY + CELL_SIZE - 15);
- line2.setRotation(-45);
- window.draw(line1);
- window.draw(line2);
- }
- void drawO(sf::RenderWindow& window, int posX, int posY) const {
- sf::CircleShape circle(CELL_SIZE / 2 - 10);
- circle.setPosition(posX + 10, posY + 10);
- circle.setOutlineThickness(5);
- circle.setOutlineColor(sf::Color::Blue);
- circle.setFillColor(sf::Color::Transparent);
- window.draw(circle);
- }
- void drawLargeSymbol(sf::RenderWindow& window, int offsetX, int offsetY) const {
- // Определяем цвет фона
- sf::Color backgroundColor = sf::Color::White;
- // Рисуем фон
- sf::RectangleShape background(sf::Vector2f(GRID_SIZE * CELL_SIZE, GRID_SIZE * CELL_SIZE));
- background.setPosition(offsetX, offsetY);
- background.setFillColor(backgroundColor);
- window.draw(background);
- // Рисуем большой символ
- if (winner == Player::X) {
- drawLargeX(window, offsetX, offsetY);
- }
- else if (winner == Player::O) {
- drawLargeO(window, offsetX, offsetY);
- }
- }
- void drawLargeX(sf::RenderWindow& window, int offsetX, int offsetY) const {
- sf::RectangleShape line1(sf::Vector2f(GRID_SIZE * CELL_SIZE - 20, 10));
- line1.setFillColor(sf::Color::Red);
- line1.setPosition(offsetX + 10, offsetY + 10);
- line1.setRotation(45);
- sf::RectangleShape line2(sf::Vector2f(GRID_SIZE * CELL_SIZE - 20, 10));
- line2.setFillColor(sf::Color::Red);
- line2.setPosition(offsetX + 10, offsetY + GRID_SIZE * CELL_SIZE - 10);
- line2.setRotation(-45);
- window.draw(line1);
- window.draw(line2);
- }
- void drawLargeO(sf::RenderWindow& window, int offsetX, int offsetY) const {
- sf::CircleShape circle((GRID_SIZE * CELL_SIZE) / 2 - 10);
- circle.setPosition(offsetX + 10, offsetY + 10);
- circle.setOutlineThickness(10);
- circle.setOutlineColor(sf::Color::Blue);
- circle.setFillColor(sf::Color::Transparent);
- window.draw(circle);
- }
- };
- class BigGrid {
- public:
- BigGrid() {
- for (auto& row : grids) {
- row.fill(SmallGrid());
- }
- }
- void draw(sf::RenderWindow& window, int nextBigX, int nextBigY) const {
- for (int y = 0; y < BIG_GRID_SIZE; ++y) {
- for (int x = 0; x < BIG_GRID_SIZE; ++x) {
- int offsetX = x * (GRID_SIZE * CELL_SIZE + PADDING);
- int offsetY = y * (GRID_SIZE * CELL_SIZE + PADDING);
- bool highlight = (nextBigX == -1 && nextBigY == -1) || (nextBigX == x && nextBigY == y) || isGridFull(nextBigX, nextBigY);
- grids[y][x].draw(window, offsetX, offsetY, highlight);
- }
- }
- // Draw grid lines for the big grid
- sf::RectangleShape line;
- line.setFillColor(sf::Color::Black);
- for (int i = 1; i < BIG_GRID_SIZE; ++i) {
- line.setSize(sf::Vector2f(WINDOW_SIZE, 2));
- line.setPosition(0, i * GRID_SIZE * CELL_SIZE + (i - 1) * PADDING + PADDING / 2);
- window.draw(line);
- line.setSize(sf::Vector2f(2, WINDOW_SIZE));
- line.setPosition(i * GRID_SIZE * CELL_SIZE + (i - 1) * PADDING + PADDING / 2, 0);
- window.draw(line);
- }
- }
- bool makeMove(int bigX, int bigY, int smallX, int smallY, Player player) {
- return grids[bigY][bigX].makeMove(smallX, smallY, player);
- }
- bool isGridFull(int bigX, int bigY) const {
- return grids[bigY][bigX].isFull();
- }
- Player checkGridWinner(int bigX, int bigY) const {
- return grids[bigY][bigX].checkWinner();
- }
- bool isGridWon(int bigX, int bigY) const {
- return grids[bigY][bigX].checkWinner() != Player::None;
- }
- Player checkBigGridWinner() const {
- for (int y = 0; y < BIG_GRID_SIZE; ++y) {
- if (isGridWon(y, 0) && checkGridWinner(y, 0) == checkGridWinner(y, 1) && checkGridWinner(y, 1) == checkGridWinner(y, 2)) {
- return checkGridWinner(y, 0);
- }
- }
- for (int x = 0; x < BIG_GRID_SIZE; ++x) {
- if (isGridWon(0, x) && checkGridWinner(0, x) == checkGridWinner(1, x) && checkGridWinner(1, x) == checkGridWinner(2, x)) {
- return checkGridWinner(0, x);
- }
- }
- if (isGridWon(0, 0) && checkGridWinner(0, 0) == checkGridWinner(1, 1) && checkGridWinner(1, 1) == checkGridWinner(2, 2)) {
- return checkGridWinner(0, 0);
- }
- if (isGridWon(0, 2) && checkGridWinner(0, 2) == checkGridWinner(1, 1) && checkGridWinner(1, 1) == checkGridWinner(2, 0)) {
- return checkGridWinner(0, 2);
- }
- return Player::None;
- }
- bool isFull() const {
- for (int y = 0; y < BIG_GRID_SIZE; ++y) {
- for (int x = 0; x < BIG_GRID_SIZE; ++x) {
- if (!grids[y][x].isFull()) {
- return false;
- }
- }
- }
- return true;
- }
- private:
- std::array<std::array<SmallGrid, BIG_GRID_SIZE>, BIG_GRID_SIZE> grids;
- };
- int main() {
- sf::RenderWindow window(sf::VideoMode(WINDOW_SIZE, WINDOW_SIZE), "Ultimate Tic-Tac-Toe");
- BigGrid bigGrid;
- Player currentPlayer = Player::X;
- int nextBigX = -1, nextBigY = -1;
- bool gameOver = false;
- std::string gameOverMessage;
- while (window.isOpen()) {
- sf::Event event;
- while (window.pollEvent(event)) {
- if (event.type == sf::Event::Closed)
- {
- window.close();
- }
- else if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left && !gameOver) {
- sf::Vector2i mousePos = sf::Mouse::getPosition(window);
- int bigX = mousePos.x / (GRID_SIZE * CELL_SIZE + PADDING);
- int bigY = mousePos.y / (GRID_SIZE * CELL_SIZE + PADDING);
- int smallX = (mousePos.x % (GRID_SIZE * CELL_SIZE + PADDING)) / CELL_SIZE;
- int smallY = (mousePos.y % (GRID_SIZE * CELL_SIZE + PADDING)) / CELL_SIZE;
- if (bigX >= 0 && bigX < BIG_GRID_SIZE && bigY >= 0 && bigY < BIG_GRID_SIZE &&
- smallX >= 0 && smallX < GRID_SIZE && smallY >= 0 && smallY < GRID_SIZE &&
- (nextBigX == -1 && nextBigY == -1 || (bigX == nextBigX && bigY == nextBigY)) &&
- bigGrid.makeMove(bigX, bigY, smallX, smallY, currentPlayer)) {
- Player currentBigWinner = bigGrid.checkBigGridWinner();
- if (currentBigWinner != Player::None || bigGrid.isFull()) {
- gameOver = true;
- if (currentBigWinner != Player::None) {
- gameOverMessage = (currentBigWinner == Player::X) ? "X Wins!" : "O Wins!";
- }
- else {
- gameOverMessage = "It's a tie!";
- }
- }
- else
- {
- nextBigX = smallX;
- nextBigY = smallY;
- currentPlayer = (currentPlayer == Player::X) ? Player::O : Player::X;
- }
- }
- }
- }
- window.clear(sf::Color::White);
- bigGrid.draw(window, nextBigX, nextBigY);
- if (gameOver)
- {
- sf::Font font;
- if (!font.loadFromFile("arial.ttf"))
- {
- std::cerr << "Failed to load font file" << std::endl;
- return EXIT_FAILURE;
- }
- sf::Text text(gameOverMessage, font, 50);
- text.setFillColor(sf::Color::Black);
- sf::FloatRect textRect = text.getLocalBounds();
- text.setOrigin(textRect.left + textRect.width / 2.0f, textRect.top + textRect.height / 2.0f);
- text.setPosition(sf::Vector2f(WINDOW_SIZE / 2.0f, WINDOW_SIZE / 2.0f));
- window.draw(text);
- }
- window.display();
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement