Last active
          December 10, 2024 04:55 
        
      - 
      
- 
        Save bethropolis/45af65dcd907d9c59896db121d2ed265 to your computer and use it in GitHub Desktop. 
    tik tak toe game
  
        
  
    
      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
    
  
  
    
  | /* | |
| Tic-Tac-Toe Game | |
| This file contains the implementation of a simple Tic-Tac-Toe game. | |
| The game is played between a human player (Player X) and a bot (Player O). | |
| The main functions include: | |
| - displayBoard: To display the current state of the game board. | |
| - checkWin: To check if a player has won the game. | |
| - checkDraw: To check if the game is a draw. | |
| - getPlayerMove: To get and validate the human player's move. | |
| - botMove: To let the bot make a random move. | |
| - playGame: To handle the main gameplay loop. | |
| The game starts with the human player and alternates between the player and the bot. | |
| */ | |
| // ----------------------------------------------------------------------------------------------- | |
| // STANDARD LIBRARIES | |
| // ----------------------------------------------------------------------------------------------- | |
| #include <iostream> // For input/output | |
| #include <vector> // For vector container class (game board) | |
| #include <cstdlib> // For random number generation (bot move selection) | |
| #include <ctime> // To seed random number generator | |
| #include <limits> // For clearing input buffer (cin) | |
| using namespace std; | |
| /** | |
| * @brief Displays the current state of the Tic-Tac-Toe board. | |
| * | |
| * This function takes a vector of characters representing the Tic-Tac-Toe board | |
| * and prints it in a 3x3 grid format. Each cell of the board is separated by | |
| * vertical and horizontal lines to visually represent the board. | |
| * | |
| * @param board A vector of characters representing the Tic-Tac-Toe board. | |
| * The vector should have exactly 9 elements. | |
| */ | |
| void displayBoard(const vector<char>& board) { | |
| cout << "\n"; | |
| cout << "Current Board:\n"; | |
| for (int i = 0; i < 9; i += 3) { // loop through each row | |
| cout << " " << board[i] << " | " << board[i+1] << " | " << board[i+2] << "\n"; | |
| if (i < 6) cout << "---|---|---\n"; | |
| } | |
| cout << "\n"; | |
| } | |
| /** | |
| * @brief Checks if the given player has won the game. | |
| * | |
| * This function checks all possible winning conditions in a Tic-Tac-Toe game: | |
| * - Three in a row horizontally | |
| * - Three in a row vertically | |
| * - Three in a row diagonally | |
| * | |
| * @param board A vector representing the Tic-Tac-Toe board. | |
| * @param player The player character to check for a win ('X' or 'O'). | |
| * @return true if the player has won, false otherwise. | |
| * | |
| * Example of winning states: | |
| * | |
| * Horizontal win: | |
| * X | X | X | |
| * - | - | - | |
| * - | - | - | |
| * | |
| * Vertical win: | |
| * X | - | - | |
| * X | - | - | |
| * X | - | - | |
| * | |
| * Diagonal win: | |
| * X | - | - | |
| * - | X | - | |
| * - | - | X | |
| * */ | |
| bool checkWin(const vector<char>& board, char player) { | |
| // Check rows | |
| for (int i = 0; i < 9; i += 3) { | |
| if (board[i] == player && board[i+1] == player && board[i+2] == player) { | |
| // first run: 1, 2, 3 | |
| // second run: 4, 5, 6 | |
| // third run: 7, 8, 9 | |
| return true; | |
| } | |
| } | |
| // Check columns | |
| for (int i = 0; i < 3; ++i) { | |
| if (board[i] == player && board[i+3] == player && board[i+6] == player) { | |
| // first run: 1, 4, 7 | |
| // second run: 2, 5, 8 | |
| // third run: 3, 6, 9 | |
| return true; | |
| } | |
| } | |
| // Check diagonals (top-left to bottom-right and top-right to bottom-left) | |
| if ((board[0] == player && board[4] == player && board[8] == player) || | |
| (board[2] == player && board[4] == player && board[6] == player)) { | |
| return true; | |
| } | |
| return false; | |
| } | |
| /** | |
| * @brief Checks if the game is a draw. | |
| * | |
| * This function iterates through the Tic-Tac-Toe board to determine if there are any empty cells left. | |
| * If all cells are filled and no player has won, the game is considered a draw. | |
| * | |
| * @param board A vector representing the Tic-Tac-Toe board. | |
| * @return true if the game is a draw, false otherwise. | |
| * | |
| * Example of a draw state: | |
| * | |
| * X | O | X | |
| * O | X | X | |
| * O | X | O | |
| */ | |
| bool checkDraw(const vector<char>& board) { | |
| for (const char& cell : board) { | |
| if (cell == ' ') return false; // If there's an empty cell, it's not a draw | |
| } | |
| return true; // No empty cells, it's a draw | |
| } | |
| /** | |
| * @brief Prompts the player to enter their move and validates the input. | |
| * | |
| * This function continuously prompts the player (Player X) to enter their move | |
| * until a valid move is provided. A valid move is an integer between 1 and 9 | |
| * that corresponds to an empty spot on the board. The function checks if the | |
| * input is within the valid range and if the selected cell is empty. If the | |
| * input is invalid, an error message is displayed and the player is prompted | |
| * to enter their move again. | |
| * | |
| * @param board A constant reference to a vector of characters representing the game board. | |
| * @return int The valid move entered by the player, adjusted for 0-indexing. | |
| */ | |
| int getPlayerMove(const vector<char>& board) { | |
| int move; | |
| while (true) { | |
| cout << "Your turn (Player X). Enter your move (1-9): "; | |
| cin >> move; | |
| // Check if input is valid and within range | |
| // Also check if the selected cell is empty | |
| // we are subtracting 1 from the move because the board is 0-indexed | |
| if (cin.fail() || move < 1 || move > 9 || board[move - 1] != ' ') { | |
| cout << "Invalid input! Please enter a number between 1 and 9 for an empty spot.\n"; | |
| // Clear invalid input | |
| cin.clear(); | |
| cin.ignore(numeric_limits<streamsize>::max(), '\n'); | |
| } else { | |
| return move; // Return the valid move | |
| } | |
| } | |
| } | |
| /** | |
| * @brief Lets the bot make a random move. | |
| * | |
| * This function allows the bot (Player O) to make a move by selecting a random empty spot on the board. | |
| * It ensures that the bot's move is valid by checking if the selected cell is empty. | |
| * | |
| * @param board A vector representing the Tic-Tac-Toe board. | |
| * | |
| * | |
| * Example: | |
| * Initial board state (empty): | |
| * 1 | 2 | 3 | |
| * ---|---|--- | |
| * 4 | 5 | 6 | |
| * ---|---|--- | |
| * 7 | 8 | 9 | |
| * | |
| * Suppose the board is in the following state: | |
| * X | O | X | |
| * ---|---|--- | |
| * | X | | |
| * ---|---|--- | |
| * O | | | |
| * | |
| * The bot will randomly select from the remaining empty spots (4, 6, 8, 9) | |
| * If it selects spot 6, the board will be updated to: | |
| * X | O | X | |
| * ---|---|--- | |
| * | X | O | |
| * ---|---|--- | |
| * O | | | |
| * */ | |
| void botMove(vector<char>& board) { | |
| int move; | |
| // Generate a random move until a valid move is found | |
| // Ensure the selected cell is empty | |
| do { | |
| move = rand() % 9; // Generate a random move between 0 and 8 | |
| } while (board[move] != ' '); // Ensure the move is valid | |
| board[move] = 'O'; // Place the bot's mark | |
| cout << "Bot (O) has made its move!\n"; | |
| } | |
| // Function to handle the gameplay loop | |
| void playGame() { | |
| vector<char> board(9, ' '); // Initialize the game board | |
| char currentPlayer = 'X'; // Player X always starts | |
| srand(static_cast<unsigned>(time(0))); // Seed random generator (without this, bot will make the same moves) | |
| cout << "Welcome to Tic-Tac-Toe!\n"; | |
| cout << "You are Player X. The bot is Player O.\n"; | |
| cout << "To make a move, enter a number between 1 and 9 corresponding to the board position:\n"; | |
| cout << " 1 | 2 | 3\n"; | |
| cout << "---|---|---\n"; | |
| cout << " 4 | 5 | 6\n"; | |
| cout << "---|---|---\n"; | |
| cout << " 7 | 8 | 9\n"; | |
| // Main game loop | |
| while (true) { | |
| displayBoard(board); | |
| if (currentPlayer == 'X') { | |
| // Player's turn | |
| int move = getPlayerMove(board); | |
| board[move - 1] = 'X'; | |
| } else { | |
| // Bot's turn | |
| botMove(board); | |
| } | |
| // Check if the current player wins | |
| if (checkWin(board, currentPlayer)) { | |
| displayBoard(board); | |
| if (currentPlayer == 'X') { | |
| cout << "Congratulations! You (Player X) win!\n"; | |
| } else { | |
| cout << "The bot (Player O) wins! Better luck next time.\n"; | |
| } | |
| break; | |
| } | |
| // Check if the game is a draw | |
| if (checkDraw(board)) { | |
| displayBoard(board); | |
| cout << "It's a draw! Nobody wins this time.\n"; | |
| break; | |
| } | |
| // Switch to the next player | |
| currentPlayer = (currentPlayer == 'X') ? 'O' : 'X'; | |
| } | |
| } | |
| // ----------------------------------------------------------------------------------------------- | |
| // MAIN FUNCTION | |
| // ----------------------------------------------------------------------------------------------- | |
| int main() { | |
| playGame(); // Start the game | |
| return 0; | |
| } | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment