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 WINDOW_SIZE = 600;
- const int GRID_SIZE = 3;
- const float CELL_SIZE = WINDOW_SIZE / GRID_SIZE;
- enum class Cell {
- Empty,
- Cross,
- Circle
- };
- enum class Player {
- None,
- Player1,
- Player2
- };
- class Game {
- public:
- virtual void resetGame() = 0;
- virtual void resetRound() = 0;
- virtual bool makeMove(int x, int y) = 0;
- virtual void nextTurn() = 0;
- virtual Player getCurrentPlayer() const = 0;
- virtual bool checkRoundEnd() = 0;
- virtual bool checkGameEnd() const = 0;
- virtual void render(sf::RenderWindow& window) = 0;
- virtual ~Game() = default;
- };
- class GameBoard {
- private:
- std::array<std::array<Cell, GRID_SIZE>, GRID_SIZE> grid;
- public:
- GameBoard() { reset(); }
- void reset() {
- for (auto& row : grid) {
- for (auto& cell : row) {
- cell = Cell::Empty;
- }
- }
- }
- bool setCell(int x, int y, Cell value) {
- if (grid[y][x] == Cell::Empty) {
- grid[y][x] = value;
- return true;
- }
- return false;
- }
- Cell getCell(int x, int y) const {
- return grid[y][x];
- }
- Player checkWinner() const {
- for (int i = 0; i < GRID_SIZE; ++i) {
- if (grid[i][0] != Cell::Empty && grid[i][0] == grid[i][1] && grid[i][1] == grid[i][2]) {
- return grid[i][0] == Cell::Cross ? Player::Player1 : Player::Player2;
- }
- if (grid[0][i] != Cell::Empty && grid[0][i] == grid[1][i] && grid[1][i] == grid[2][i]) {
- return grid[0][i] == Cell::Cross ? Player::Player1 : Player::Player2;
- }
- }
- if (grid[0][0] != Cell::Empty && grid[0][0] == grid[1][1] && grid[1][1] == grid[2][2]) {
- return grid[0][0] == Cell::Cross ? Player::Player1 : Player::Player2;
- }
- if (grid[0][2] != Cell::Empty && grid[0][2] == grid[1][1] && grid[1][1] == grid[2][0]) {
- return grid[0][2] == Cell::Cross ? Player::Player1 : Player::Player2;
- }
- return Player::None;
- }
- bool isFull() const {
- for (const auto& row : grid) {
- for (const auto& cell : row) {
- if (cell == Cell::Empty) return false;
- }
- }
- return true;
- }
- };
- class TicTacToe : public Game {
- private:
- GameBoard board;
- Player currentPlayer;
- int scorePlayer1;
- int scorePlayer2;
- int round;
- Player winner;
- public:
- TicTacToe() : currentPlayer(Player::Player1), scorePlayer1(0), scorePlayer2(0), round(1), winner(Player::None) {}
- TicTacToe(Player startingPlayer) : currentPlayer(startingPlayer), scorePlayer1(0), scorePlayer2(0), round(1), winner(Player::None) {}
- void resetGame() override {
- board.reset();
- currentPlayer = Player::Player1;
- scorePlayer1 = 0;
- scorePlayer2 = 0;
- round = 1;
- winner = Player::None;
- }
- void resetRound() override {
- board.reset();
- currentPlayer = Player::Player1;
- }
- void nextTurn() override {
- currentPlayer = (currentPlayer == Player::Player1) ? Player::Player2 : Player::Player1;
- }
- Player getCurrentPlayer() const override {
- return currentPlayer;
- }
- bool makeMove(int x, int y) override {
- Cell cellValue = (currentPlayer == Player::Player1) ? Cell::Cross : Cell::Circle;
- return board.setCell(x, y, cellValue);
- }
- bool checkRoundEnd() override {
- Player roundWinner = board.checkWinner();
- if (roundWinner != Player::None) {
- if (roundWinner == Player::Player1) ++scorePlayer1;
- if (roundWinner == Player::Player2) ++scorePlayer2;
- winner = roundWinner;
- return true;
- }
- if (board.isFull()) {
- winner = Player::None;
- return true;
- }
- return false;
- }
- bool checkGameEnd() const override {
- return scorePlayer1 == 2 || scorePlayer2 == 2;
- }
- void render(sf::RenderWindow& window) override {
- sf::RectangleShape line(sf::Vector2f(WINDOW_SIZE, 5));
- line.setFillColor(sf::Color::Black);
- for (int i = 1; i < GRID_SIZE; ++i) {
- line.setPosition(0, i * CELL_SIZE);
- window.draw(line);
- line.setSize(sf::Vector2f(5, WINDOW_SIZE));
- line.setPosition(i * CELL_SIZE, 0);
- window.draw(line);
- line.setSize(sf::Vector2f(WINDOW_SIZE, 5));
- }
- for (int y = 0; y < GRID_SIZE; ++y) {
- for (int x = 0; x < GRID_SIZE; ++x) {
- Cell cell = board.getCell(x, y);
- if (cell == Cell::Cross) {
- sf::RectangleShape cross1(sf::Vector2f(CELL_SIZE - 40, 10));
- cross1.setFillColor(sf::Color::Red);
- cross1.setOrigin(cross1.getSize().x / 2, cross1.getSize().y / 2);
- cross1.setPosition(x * CELL_SIZE + CELL_SIZE / 2, y * CELL_SIZE + CELL_SIZE / 2);
- cross1.setRotation(45);
- sf::RectangleShape cross2(sf::Vector2f(CELL_SIZE - 40, 10));
- cross2.setFillColor(sf::Color::Red);
- cross2.setOrigin(cross2.getSize().x / 2, cross2.getSize().y / 2);
- cross2.setPosition(x * CELL_SIZE + CELL_SIZE / 2, y * CELL_SIZE + CELL_SIZE / 2);
- cross2.setRotation(-45);
- window.draw(cross1);
- window.draw(cross2);
- } else if (cell == Cell::Circle) {
- sf::CircleShape circle(CELL_SIZE / 2 - 15);
- circle.setFillColor(sf::Color::Transparent);
- circle.setOutlineThickness(10);
- circle.setOutlineColor(sf::Color::Blue);
- circle.setPosition(x * CELL_SIZE + 15, y * CELL_SIZE + 15);
- window.draw(circle);
- }
- }
- }
- if (checkGameEnd()) {
- sf::Font font;
- if (!font.loadFromFile("arialmt.ttf")) {
- std::cerr << "Ошибка загрузки шрифта!" << std::endl;
- return;
- }
- sf::Text winnerText;
- winnerText.setFont(font);
- winnerText.setCharacterSize(50);
- winnerText.setFillColor(sf::Color::Black);
- if (scorePlayer1 == 2) {
- winnerText.setString("Player 1 Wins!");
- } else if (scorePlayer2 == 2) {
- winnerText.setString("Player 2 Wins!");
- }
- winnerText.setPosition(WINDOW_SIZE / 2 - winnerText.getGlobalBounds().width / 2, WINDOW_SIZE / 2 - 50);
- window.draw(winnerText);
- sf::RectangleShape button(sf::Vector2f(200, 50));
- button.setFillColor(sf::Color::Green);
- button.setPosition(WINDOW_SIZE / 2 - 100, WINDOW_SIZE / 2 + 50);
- sf::Font buttonFont;
- if (!buttonFont.loadFromFile("arialmt.ttf")) {
- std::cerr << "Ошибка загрузки шрифта для кнопки!" << std::endl;
- return;
- }
- sf::Text buttonText;
- buttonText.setFont(buttonFont);
- buttonText.setString("Restart");
- buttonText.setCharacterSize(30);
- buttonText.setFillColor(sf::Color::White);
- buttonText.setPosition(WINDOW_SIZE / 2 - buttonText.getGlobalBounds().width / 2, WINDOW_SIZE / 2 + 60);
- window.draw(button);
- window.draw(buttonText);
- }
- }
- bool isRestartButtonClicked(const sf::RenderWindow& window, const sf::Event& event) const {
- if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) {
- sf::Vector2i mousePos = sf::Mouse::getPosition(window);
- sf::FloatRect buttonBounds(WINDOW_SIZE / 2 - 100, WINDOW_SIZE / 2 + 50, 200, 50);
- return buttonBounds.contains(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y));
- }
- return false;
- }
- };
- int main() {
- sf::RenderWindow window(sf::VideoMode(WINDOW_SIZE, WINDOW_SIZE), "Tic Tac Toe");
- TicTacToe game;
- while (window.isOpen()) {
- sf::Event event;
- while (window.pollEvent(event)) {
- if (event.type == sf::Event::Closed) {
- window.close();
- }
- if (game.checkGameEnd()) {
- if (game.isRestartButtonClicked(window, event)) {
- game.resetGame();
- }
- } else if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) {
- sf::Vector2i mousePos = sf::Mouse::getPosition(window);
- int x = mousePos.x / CELL_SIZE;
- int y = mousePos.y / CELL_SIZE;
- if (x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE) {
- if (game.makeMove(x, y)) {
- if (game.checkRoundEnd()) {
- if (!game.checkGameEnd()) {
- game.resetRound();
- }
- } else {
- game.nextTurn();
- }
- }
- }
- }
- }
- window.clear(sf::Color::White);
- game.render(window);
- window.display();
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement