daily pastebin goal
8%
SHARE
TWEET

Untitled

a guest Mar 21st, 2019 68 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  *  Adam
  3.  *  12/5/18
  4.  *  Tic Tac Toe - Final Project
  5.  * 
  6.  *  For my final I made a simple
  7.  *  tic tac toe game where you
  8.  *  can select to player against
  9.  *  a friend, a computer or view
  10.  *  who has the most wins, which
  11.  *  is saved in a text file
  12.  */
  13.  
  14. #include <iostream>
  15. #include <string>
  16. #include <cstdlib>
  17. #include <ctime>
  18. #include <algorithm>
  19. #include <map>
  20. #include <fstream>
  21. #include <iomanip>
  22. #include <thread>
  23.  
  24. const std::string BAR = "=====================";
  25. const std::string FILE_NAME = "Data.txt";
  26.  
  27. class TickTackToe
  28. {
  29.     std::string Player_1, Player_2;
  30.  
  31.     bool computer = false, turn = true, winner = false;
  32.  
  33.     char ticktac[9] = {'1','2','3','4','5','6','7','8','9'}; // Array of chars
  34.  
  35.         /**
  36.          *  The array is like
  37.          * 
  38.          *  [0 => '1',
  39.          *   1 => '2',
  40.          *   2 => '3',
  41.          *   3 => '4',
  42.          *   4 => '5',
  43.          *   5 => '6',
  44.          *   6 => '7',
  45.          *   7 => '8',
  46.          *   8 => '9']
  47.          * 
  48.          */
  49.  
  50.     const std::string CPU = "Computer";
  51.  
  52.     std::map<std::string, int> playerWins; // I didn't use a vector or 2d array because I think a map is more appropriate for the key pairing needed for scores, also we haven't learned them yet so it's good to learn more!
  53.  
  54.     public:
  55.  
  56.         /**
  57.          * Constructor
  58.          *
  59.          * Just made this open or make the file if it does not exist
  60.          */
  61.         TickTackToe() {
  62.  
  63.         std::ifstream ifile(FILE_NAME);
  64.  
  65.         if(ifile.fail()) {
  66.             std::ofstream ofile(FILE_NAME);
  67.             if(ofile.fail()) {
  68.                 std::cout << "[Fatal]" << " No file permissions";
  69.             }
  70.         }
  71.  
  72.         std::string key;
  73.  
  74.         int value;
  75.  
  76.             while (ifile >> key >> value) {
  77.                 this->playerWins[key] = value;
  78.             }
  79.  
  80.         ifile.close();
  81.  
  82.         }
  83.  
  84.         /**
  85.          * @param computer
  86.          */
  87.         void setComputer(const bool computer)
  88.         {
  89.             this->computer = computer;
  90.         }
  91.  
  92.         void list()
  93.         {
  94.             system("CLS");
  95.             sendHeader();
  96.             int i = 0;
  97.             for(auto pair : this->playerWins)
  98.             {
  99.                 std::string str = pair.first + ": " + std::to_string(pair.second);
  100.                 std::cout << "| " << str << std::setw(19 - str.length()) << " |" << "\n";
  101.                 i++;
  102.             }
  103.  
  104.             if(i == 0)
  105.             {
  106.                 std::cout << "No one has played any games!\n";
  107.             }
  108.  
  109.             std::cout << BAR << "\nWould you like to play again, or quit? (y,q) : ";
  110.  
  111.             // Define these
  112.  
  113.             std::string input;
  114.  
  115.             std::getline(std::cin, input);
  116.  
  117.             // Lower case it
  118.  
  119.             std::transform(input.begin(), input.end(), input.begin(), ::tolower);
  120.  
  121.             if(input != "y" && input != "yes")
  122.                 exit(0);
  123.         }
  124.  
  125.         /**
  126.          * @return bool
  127.          */
  128.         bool getComputer() const
  129.         {
  130.             return this->computer;
  131.         }
  132.  
  133.         /**
  134.          * Send the Tic Tac Toe header
  135.          */
  136.         static void sendHeader() { // Static allows it to be called without creating a TickTackToe object
  137.             system("CLS");
  138.             std::cout << BAR << "\n|  Tick Tac Toe     |\n" + BAR + "\n";
  139.         }
  140.  
  141.         /**
  142.          * Ask for the player's name(s)
  143.          * @param computer
  144.          */
  145.         void askPlayers(const bool computer) // If computer true only ask for one name, const because we aren't assigning it in this function; optimization
  146.         {
  147.             system("CLS"); // Clear screen
  148.  
  149.             const std::string PREFIX = "[Invalid] ";
  150.             const std::string NO_NUMBERS = PREFIX + "Your name can't have numbers in it!\n";
  151.             const std::string NO_SPACES = PREFIX + "No spaces allowed!\n";
  152.             const std::string COMPUTER_RESERVED = PREFIX + "The name \"Computer\" is reserved\n";
  153.             const std::string SAME_PLAYER = PREFIX + "You can't have the same name as player 1!\n";
  154.  
  155.             if(computer)
  156.             {
  157.                 while (true)
  158.                 {
  159.                     std::cout << "Enter your name : ";
  160.                     std::getline(std::cin, this->Player_1);
  161.                     if(this->Player_1 == this->CPU)
  162.                         std::cout << COMPUTER_RESERVED;
  163.                     else if(containsNumbers(this->Player_1))
  164.                         std::cout << NO_NUMBERS;
  165.                     else if(containsSpaces(this->Player_1))
  166.                         std::cout << NO_SPACES;
  167.                     else
  168.                         break;
  169.                 }
  170.                 this->Player_2 = CPU; // Player 2 is the computer
  171.                 return; // Basically if else because ends execution of function
  172.             }
  173.  
  174.             while (true)
  175.             {
  176.                 std::cout << "Enter Player 1's name : ";
  177.                 std::getline(std::cin, this->Player_1);
  178.                 if(this->Player_1 == this->CPU)
  179.                     std::cout << COMPUTER_RESERVED;
  180.                 else if(containsNumbers(this->Player_1))
  181.                     std::cout << NO_NUMBERS;
  182.                 else if(containsSpaces(this->Player_1))
  183.                     std::cout << NO_SPACES;
  184.                 else
  185.                     break;
  186.             }
  187.  
  188.             while (true)
  189.             {
  190.                 std::cout << "Enter Player 2's name : ";
  191.                 std::getline(std::cin, this->Player_2);
  192.  
  193.                 if(this->Player_2 == this->CPU)
  194.                     std::cout << COMPUTER_RESERVED;
  195.                 else if(this->Player_1 == this->Player_2)
  196.                     std::cout << SAME_PLAYER;
  197.                 else if(containsNumbers(this->Player_2))
  198.                     std::cout << NO_NUMBERS;
  199.                 else if(containsSpaces(this->Player_2))
  200.                     std::cout << NO_SPACES;
  201.                 else
  202.                     break;
  203.             }
  204.         }
  205.  
  206.         /**
  207.          * Check if a string contains numbers
  208.          * Why? I don't think people have
  209.          * numbers in their names
  210.          */
  211.         bool containsNumbers(const std::string string)
  212.         {
  213.             bool returned = false;
  214.  
  215.             for(const char &ch : string)
  216.                 if(isdigit(ch))
  217.                     returned = true;
  218.  
  219.             return  returned;
  220.         }
  221.  
  222.         /**
  223.          * Check if a string contains spaces
  224.          * Why? Spaces separate the key from
  225.          * the value in the text file
  226.          */
  227.         bool containsSpaces(const std::string string)
  228.         {
  229.             bool returned = false;
  230.  
  231.             for(const char &ch : string)
  232.                 if(isspace(ch))
  233.                     returned = true;
  234.  
  235.             return returned;
  236.         }
  237.  
  238.         /**
  239.          * Check for a win!
  240.          */
  241.         void checkBoard()
  242.         {
  243.             const bool PLAYER_ONE = true;
  244.             const bool PLAYER_TWO = false;
  245.  
  246.             bool isDraw = true;
  247.  
  248.             /**
  249.              *
  250.              * Board
  251.              *
  252.              * 0 1 2
  253.              * 3 4 5
  254.              * 6 7 8
  255.              */
  256.            
  257.             // Horizontal lines 3x
  258.  
  259.             if(this->ticktac[0] == 'X' && this->ticktac[1] == 'X' && this->ticktac[2] == 'X')
  260.                 isDraw = endEvent(PLAYER_ONE);
  261.             else if(this->ticktac[0] == 'O' && this->ticktac[1] == 'O' && this->ticktac[2] == 'O')
  262.                 isDraw = endEvent(PLAYER_TWO);
  263.             else if(this->ticktac[3] == 'X' && this->ticktac[4] == 'X' && this->ticktac[5] == 'X')
  264.                 isDraw = endEvent(PLAYER_ONE);
  265.             else if(this->ticktac[3] == 'O' && this->ticktac[4] == 'O' && this->ticktac[5] == 'O')
  266.                 isDraw = endEvent(PLAYER_TWO);
  267.             else if(this->ticktac[6] == 'X' && this->ticktac[7] == 'X' && this->ticktac[8] == 'X')
  268.                 isDraw = endEvent(PLAYER_ONE);
  269.             else if(this->ticktac[6] == 'O' && this->ticktac[7] == 'O' && this->ticktac[8] == 'O')
  270.                 isDraw = endEvent(PLAYER_TWO);
  271.  
  272.             // Vertical lines 3x
  273.  
  274.             if(this->ticktac[0] == 'X' && this->ticktac[3] == 'X' && this->ticktac[6] == 'X')
  275.                 isDraw = endEvent(PLAYER_ONE);
  276.             else if(this->ticktac[0] == 'O' && this->ticktac[3] == 'O' && this->ticktac[6] == 'O')
  277.                 isDraw = endEvent(PLAYER_TWO);
  278.             else if(this->ticktac[1] == 'X' && this->ticktac[4] == 'X' && this->ticktac[7] == 'X')
  279.                 isDraw = endEvent(PLAYER_ONE);
  280.             else if(this->ticktac[1] == 'O' && this->ticktac[4] == 'O' && this->ticktac[7] == 'O')
  281.                 isDraw = endEvent(PLAYER_TWO);
  282.             else if(this->ticktac[2] == 'X' && this->ticktac[5] == 'X' && this->ticktac[8] == 'X')
  283.                 isDraw = endEvent(PLAYER_ONE);
  284.             else if(this->ticktac[2] == 'O' && this->ticktac[5] == 'O' && this->ticktac[8] == 'O')
  285.                 isDraw = endEvent(PLAYER_TWO);
  286.  
  287.             // Diagonal lines 2x
  288.  
  289.             if(this->ticktac[0] == 'X' && this->ticktac[4] == 'X' && this->ticktac[8] == 'X')
  290.                 isDraw = endEvent(PLAYER_ONE);
  291.             else if(this->ticktac[0] == 'O' && this->ticktac[4] == 'O' && this->ticktac[8] == 'O')
  292.                 isDraw = endEvent(PLAYER_TWO);
  293.             else if(this->ticktac[2] == 'X' && this->ticktac[4] == 'X' && this->ticktac[6] == 'X')
  294.                 isDraw = endEvent(PLAYER_ONE);
  295.             else if(this->ticktac[2] == 'O' && this->ticktac[4] == 'O' && this->ticktac[6] == 'O')
  296.                 isDraw = endEvent(PLAYER_TWO);
  297.  
  298.             // This adds 1 for every taken slot on the board!
  299.  
  300.             int i = 0;
  301.  
  302.             for (char &tic : ticktac)
  303.             {
  304.                 if(tic == 'X' || tic == 'O')
  305.                     i++;
  306.             }
  307.  
  308.             // There are 9 slots, if all are full and there wasn't a win, it must be a draw!
  309.  
  310.             if(i == 9 && isDraw)
  311.                 endEvent(true, true);
  312.         }
  313.  
  314.         /**
  315.          * @param winner
  316.          * @param tie
  317.          */
  318.         bool endEvent(const bool winner, const bool tie = false) // Bool because only two potential winners
  319.         {
  320.             sendHeader();
  321.  
  322.             this->winner = true;
  323.  
  324.             if(tie)
  325.                 std::cout << "There was a draw!";
  326.             else
  327.                 std::cout << std::string(winner ? this->Player_1 : this->Player_2) << " won the game!";
  328.  
  329.             /*
  330.              * std::map find method returns: "An iterator to the element, if an element with specified key is found, or map::end otherwise."
  331.              */
  332.  
  333.             int v = 1; // v as in value
  334.  
  335.             if(playerWins.find(winner ? this->Player_1 : this->Player_2) != playerWins.end())
  336.             {
  337.                 v = playerWins[winner ? this->Player_1 : this->Player_2] + 1;
  338.             }
  339.  
  340.             playerWins[winner ? this->Player_1 : this->Player_2] = v;
  341.  
  342.             // Construct object ofile
  343.  
  344.             std::ofstream ofile(FILE_NAME);
  345.  
  346.             // Loop through file, space between each and new line after
  347.  
  348.             for (auto const& map : playerWins)
  349.             {
  350.                 ofile << map.first << " " << map.second << "\n"; // first = key, second = value
  351.             }
  352.  
  353.             ofile.close();
  354.  
  355.             std::cout << "\nWould you like to play again, or quit? (y,q) : ";
  356.  
  357.             // Define these
  358.  
  359.             std::string input;
  360.  
  361.             std::cin.clear();
  362.             std::cin.ignore();
  363.  
  364.             std::getline(std::cin, input);
  365.  
  366.             // Lower case it
  367.  
  368.             std::transform(input.begin(), input.end(), input.begin(), ::tolower);
  369.  
  370.             if(input == "y" || input ==  "yes")
  371.                 return false;
  372.  
  373.             // Else
  374.  
  375.             exit(0);
  376.         }
  377.  
  378.         /**
  379.          * Is there a winner?
  380.          */
  381.         bool isWinner() const
  382.         {
  383.             return this->winner;
  384.         }
  385.  
  386.         /**
  387.          * Send the board
  388.          */
  389.         void board() { // Optionally set some of the array functions
  390.  
  391.             sendHeader();
  392.  
  393.             std::cout << "\n";
  394.  
  395.             int i = 1;
  396.  
  397.             for (const char &tick : this->ticktac) {
  398.  
  399.                 if(i > 9)
  400.                     break;
  401.  
  402.                 std::cout << " | " << tick << " | ";
  403.  
  404.                 if(i % 3 == 0) // Make two new lines every 3
  405.                     std::cout << "\n\n";
  406.                 i++;
  407.             }
  408.         }
  409.  
  410.         /**
  411.          * Prompt for the players choice
  412.          */
  413.         void prompt()
  414.         {
  415.             int input;
  416.  
  417.             while (true)
  418.             {
  419.                 // Alternate prompts based on turns
  420.  
  421.                 if(this->computer && !this->turn)
  422.                     input = computerTurn();
  423.                 else {
  424.  
  425.                     if(this->turn)
  426.                         std::cout << "Enter the square you'd like to choose, " << this->Player_1 << " : ";
  427.                     else
  428.                         std::cout << "Enter the square you'd like to choose, " << this->Player_2 << " : ";
  429.  
  430.                     std::cin >> input;
  431.  
  432.                 }
  433.  
  434.                 // Validation
  435.  
  436.                 if(input < 1 || input > 9 ? error("You must enter a number between 1 and 9") : true){ // Strings turn into 0 so this filters out strings as well as negative numbers
  437.  
  438.                     if(this->ticktac[input - 1] == 'X' || this->ticktac[--input] == 'O')
  439.                         error("You can't select that, it's already selected!");
  440.                     else
  441.                         break;
  442.                 }
  443.                 std::cin.clear(); // This clears the cin buffer
  444.                 std::cin.ignore(); // This makes cin get rid of the garbage the user enters
  445.             }
  446.  
  447.             this->ticktac[input] = this->turn ? 'X' : 'O';
  448.  
  449.             this->turn = !this->turn; // Flip the player every time someone makes a turn.
  450.  
  451.             checkBoard();
  452.         }
  453.  
  454.         /**
  455.          * Choose a random slot
  456.          */
  457.         int computerTurn() {
  458.  
  459.             int number = 0;
  460.  
  461.             srand(time(nullptr)); // Seed random number
  462.  
  463.             while (true)
  464.             {
  465.                 number = rand() % 9;
  466.                 if(this->ticktac[number] == 'X' || this->ticktac[number] == 'O')
  467.                     continue; // Repeat until successful result
  468.  
  469.                 break;
  470.             }
  471.             return ++number;
  472.         }
  473.  
  474.         /**
  475.          * Error message
  476.          * @param msg
  477.          */
  478.         bool error(const char* msg) {
  479.             std::cout << "[Error] " << msg << "\n";
  480.             return false; // By returning a value I can shorten the code that calls this by calling a function and assigning at the same time
  481.         }
  482. };
  483.  
  484.  
  485. int main(int argc, char* argv[])
  486. {
  487.     while (true)
  488.     {
  489.         TickTackToe::sendHeader();
  490.  
  491.         std::string Player_1, Player_2; // Define variables
  492.  
  493.         // Prompt and set variables
  494.  
  495.         std::cout << "|   Choose a mode   |\n";
  496.         std::cout << BAR;
  497.         std::cout << "\n| 1 : 2 Player      |";
  498.         std::cout << "\n| 2 : Computer      |";
  499.         std::cout << "\n| 3 : View Top      |";
  500.         std::cout << "\n| 4 : Quit          |\n";
  501.         std::cout << BAR;
  502.  
  503.         std::string input;
  504.  
  505.         for (;;) // You can omit everything in a for loop to make it work like a forever loop
  506.         {
  507.             std::cout << "\nMode : ";
  508.             std::getline(std::cin,input);
  509.  
  510.             if(input != "1" && input != "2" && input != "3" && input != "4") {
  511.                 continue;
  512.             }
  513.             break;
  514.         }
  515.  
  516.         TickTackToe Project;
  517.        
  518.         // Pass to object Project
  519.         if(input == "1")
  520.             Project.setComputer(false);
  521.         else if(input == "2")
  522.             Project.setComputer(true);
  523.         else if(input == "3") {
  524.             Project.list();
  525.             continue;
  526.         }
  527.         else if(input == "4")
  528.             break;
  529.  
  530.         Project.askPlayers(Project.getComputer());
  531.  
  532.         while (!Project.isWinner())
  533.         {
  534.             Project.board();
  535.             Project.prompt();
  536.         }
  537.     }
  538. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top