Advertisement
Volatile_Pulse

Tic-Tac-Toe.cpp

Jul 19th, 2012
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.47 KB | None | 0 0
  1. #include <functional>
  2. #include <iostream>
  3. #include <vector>
  4. #include <string>
  5. #include <windows.h>
  6.  
  7. void VP_ClearScreen() {
  8.     CONSOLE_SCREEN_BUFFER_INFO csbi;
  9.     HANDLE hStdOut;
  10.     DWORD count;
  11.     DWORD cellCount;
  12.     COORD homeCoords = { 0, 0 };
  13.  
  14.     hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
  15.     if (hStdOut == INVALID_HANDLE_VALUE) return;
  16.  
  17.     // Get the number of cells in the current buffer
  18.     if (!GetConsoleScreenBufferInfo( hStdOut, &csbi )) return;
  19.     cellCount = csbi.dwSize.X *csbi.dwSize.Y;
  20.  
  21.     // Fill the entire buffer with spaces
  22.     if (!FillConsoleOutputCharacter(hStdOut,(TCHAR) ' ', cellCount, homeCoords, &count))
  23.         return;
  24.  
  25.     // Fill the entire buffer with the current colors and attributes
  26.     if (!FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, cellCount, homeCoords, &count))
  27.         return;
  28.  
  29.     // Move the cursor home
  30.     SetConsoleCursorPosition( hStdOut, homeCoords );
  31.     /* Windows */
  32. }
  33.  
  34. void VP_SetConsoleCursor(bool bCursor) {
  35.     CONSOLE_CURSOR_INFO curCursorInfo;
  36.     curCursorInfo.bVisible = bCursor;
  37.     curCursorInfo.dwSize = 1;
  38.     SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &curCursorInfo);
  39. }
  40.  
  41. void VP_GoToXY(int x, int y) {
  42.     COORD CursorPosition = {static_cast<short>(x), static_cast<short>(y)};
  43.     SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), CursorPosition);
  44. }
  45.  
  46. int VP_GetCh () {
  47.     HANDLE hConsole;
  48.     INPUT_RECORD inrec;
  49.     DWORD count, mode;
  50.  
  51.     hConsole = GetStdHandle(STD_INPUT_HANDLE);
  52.     if (hConsole == INVALID_HANDLE_VALUE || !GetConsoleMode(hConsole, &mode)|| !SetConsoleMode(hConsole, 0))
  53.         return 0;
  54.  
  55.     FlushConsoleInputBuffer(hConsole);
  56.  
  57.     do {
  58.         ReadConsoleInput(hConsole, &inrec, 1, &count);
  59.     } while ((inrec.EventType != KEY_EVENT) || inrec.Event.KeyEvent.bKeyDown);
  60.  
  61.     SetConsoleMode(hConsole, mode);
  62.  
  63.     return inrec.Event.KeyEvent.wVirtualKeyCode;
  64. }
  65.  
  66. // Enum for positions
  67. enum position {LEFT, CENTER, RIGHT, TOP, BOTTOM};
  68.  
  69. class Menu {
  70.    public:
  71.       // Define Empty Menu with a Title and set Left and Right Selectors
  72.       Menu (std::string title = "",
  73.             std::string leftSelector = "",
  74.             std::string rightSelector = "",
  75.             position verticalPosition = TOP,
  76.             position horizontalPosition = LEFT) :
  77.                strMenuTitle(title),
  78.                strLeftSelector(leftSelector),
  79.                strRightSelector(rightSelector),
  80.                posVPosition(verticalPosition),
  81.                posHPosition(horizontalPosition),
  82.                vMenuOptions(),
  83.                vMenuFunctions(),
  84.                iLastSelection(1),
  85.                bWrapAround(true) {}
  86.  
  87.       // Set Title for the Menu
  88.       void SetTitle (std::string title) {
  89.          strMenuTitle = title;
  90.       }
  91.  
  92.       // Set Left and Right Selectors
  93.       void SetSelectors (std::string leftSelector, std::string rightSelector) {
  94.          strLeftSelector = leftSelector;
  95.          strRightSelector = rightSelector;
  96.       }
  97.  
  98.       // Set Menu Location
  99.       void SetLocation (position verticalPosition = TOP, position horizontalPosition = LEFT) {
  100.          posVPosition = verticalPosition;
  101.          posHPosition = horizontalPosition;
  102.       }
  103.  
  104.       // Allow Option Selection to return from bottom/top to top/bottom
  105.       void Wrap (bool wrapAround = true) {
  106.          bWrapAround = wrapAround;
  107.       }
  108.  
  109.       // Add new Option
  110.       void AddOption (std::string option) {
  111.          vMenuOptions.push_back (option);
  112.          vMenuFunctions.resize (vMenuOptions.size());
  113.       }
  114.  
  115.       // Add new Option with a function
  116.       void AddOption (std::string option, std::function<void ()> func) {
  117.          vMenuOptions.push_back (option);
  118.          vMenuFunctions.push_back (func);
  119.       }
  120.  
  121.       // Set Option x to "text"
  122.       void SetOption (unsigned int number, std::string option);
  123.  
  124.       // Set Option x to "text" with a function
  125.       void SetOption (unsigned int number, std::string option, std::function<void ()> func);
  126.  
  127.       // Allow Option Selection to return from bottom/top to top/bottom
  128.       unsigned int LastSelection() {
  129.          return iLastSelection;
  130.       }
  131.  
  132.       // Allow Option Selection to return from bottom/top to top/bottom
  133.       int Size() {
  134.          return vMenuOptions.size();
  135.       }
  136.  
  137.       // Display menu with an option already highlighted
  138.       void Play ();
  139.    private:
  140.       // Private function to Draw the menu
  141.       void Draw();
  142.       // Define a string to hold the left selector
  143.       std::string strMenuTitle;
  144.       // Define a string to hold the left selector
  145.       std::string strLeftSelector;
  146.       // Define a string to hold the right selector
  147.       std::string strRightSelector;
  148.       // Define a position to hold the vertical position
  149.       position posVPosition;
  150.       // Define a position to hold the horizontal position
  151.       position posHPosition;
  152.       // Define a vactor for storing the option strings
  153.       std::vector<std::string> vMenuOptions;
  154.       // Define a vector for storing the option functions
  155.       std::vector<std::function <void ()>> vMenuFunctions;
  156.       // Define an unsigned int to hold the last selected option
  157.       unsigned int iLastSelection;
  158.       // Define wrap around option
  159.       bool bWrapAround;
  160. };
  161.  
  162. void Menu::SetOption (unsigned int number, std::string option) {
  163.    // Resize vMenuOptions to allow option at position
  164.    if (vMenuOptions.size() < number) {
  165.       vMenuOptions.resize (number, "");
  166.       vMenuFunctions.resize (number);
  167.    }
  168.  
  169.    // Assign the new option
  170.    vMenuOptions[ (number - 1)] = option;
  171. }
  172.  
  173. void Menu::SetOption (unsigned int number, std::string option, std::function<void ()> func) {
  174.    // Resize vMenuOptions to allow option at position
  175.    if (vMenuOptions.size() < number) {
  176.       vMenuOptions.resize (number, "");
  177.       vMenuFunctions.resize (number);
  178.    }
  179.  
  180.    // Assign the new option
  181.    vMenuOptions[ (number - 1)] = option;
  182.    // Assign the new function
  183.    vMenuFunctions[(number - 1)] = func;
  184. }
  185.  
  186. void Menu::Draw () {
  187.    // Clear the screen
  188.    VP_ClearScreen();
  189.  
  190.    // Draw Title
  191.    if (!strMenuTitle.empty() ) {
  192.  
  193.       // Print Title
  194.       VP_GoToXY ( ( (posHPosition == RIGHT) ? (79 - strRightSelector.length() - strMenuTitle.length() ) :
  195.                     (posHPosition == CENTER) ? ( (79 - strMenuTitle.length() ) / 2) :
  196.                     /*(posHPosition == LEFT) ?*/ strLeftSelector.length() ),
  197.                   ( (posVPosition == BOTTOM) ? (25 - Size() - 2) :
  198.                     (posVPosition == CENTER) ? ( (25 - Size() - 2) / 2) :
  199.                     /*(posVPosition == TOP) ?*/ 0) );
  200.       std::cout << strMenuTitle;
  201.  
  202.       // Print Seperator
  203.       VP_GoToXY ( ( (posHPosition == RIGHT) ? (79 - strRightSelector.length() - strMenuTitle.length() ) :
  204.                     (posHPosition == CENTER) ? ( (79 - strMenuTitle.length() ) / 2) :
  205.                     /*(posHPosition == LEFT) ?*/ strLeftSelector.length() ),
  206.                   ( (posVPosition == BOTTOM) ? (25 - Size() - 2) :
  207.                     (posVPosition == CENTER) ? ( (25 - Size() - 2) / 2) :
  208.                     /*(posVPosition == TOP) ?*/ 0) + 1);
  209.       for (unsigned int i = 0; i < strMenuTitle.length(); i ++)
  210.          std::cout << "-";
  211.    }
  212.  
  213.    // Draw Options
  214.    for (unsigned int i = 0; i < vMenuOptions.size(); i ++) {
  215.       // Output Menu Option
  216.       VP_GoToXY ( ( (posHPosition == RIGHT) ? (79 - strRightSelector.length() - vMenuOptions[i].length() ) :
  217.                     (posHPosition == CENTER) ? ( (79 - vMenuOptions[i].length() ) / 2) :
  218.                     /*(posHPosition == LEFT) ?*/ strLeftSelector.length() ),
  219.                   ( (posVPosition == BOTTOM) ? (25 - Size() - 2) :
  220.                     (posVPosition == CENTER) ? ( (25 - Size() - 2) / 2) :
  221.                     /*(posVPosition == TOP) ?*/ 0) + ( (strMenuTitle.empty() ) ? i : (i + 2) ) );
  222.       std::cout << vMenuOptions[i];
  223.    }
  224. }
  225.  
  226. void Menu::Play () {
  227.    // Draw the menu
  228.    Draw();
  229.  
  230.    // Define Variables
  231.    int iKeyPress;
  232.  
  233.    // Handle User Input until ENTER is Pressed
  234.    do {
  235.       // Draw Left Selector
  236.       VP_GoToXY ( ( (posHPosition == RIGHT) ? (79 - strRightSelector.length() - vMenuOptions[ (iLastSelection - 1)].length() - strLeftSelector.length() ) :
  237.                     (posHPosition == CENTER) ? ( (79 - vMenuOptions[ (iLastSelection - 1)].length() ) / 2 - strLeftSelector.length() ) :
  238.                     /*(posHPosition == LEFT) ?*/ 0),
  239.                   ( (posVPosition == BOTTOM) ? (25 - Size() - 2) :
  240.                     (posVPosition == CENTER) ? ( (25 - Size() - 2) / 2) :
  241.                     /*(posVPosition == TOP) ?*/ 0) + ( (strMenuTitle.empty() ) ? (iLastSelection - 1) : (iLastSelection + 1) ) );
  242.       std::cout << strLeftSelector;
  243.  
  244.       // Draw Right Selector
  245.       VP_GoToXY ( ( (posHPosition == RIGHT) ? (79 - strRightSelector.length() ) :
  246.                     (posHPosition == CENTER) ? ( (79 + vMenuOptions[ (iLastSelection - 1)].length() ) / 2) :
  247.                     /*(posHPosition == LEFT) ?*/ strLeftSelector.length() + vMenuOptions[ (iLastSelection - 1)].length() ),
  248.                   ( (posVPosition == BOTTOM) ? (25 - Size() - 2) :
  249.                     (posVPosition == CENTER) ? ( (25 - Size() - 2) / 2) :
  250.                     /*(posVPosition == TOP) ?*/ 0) + ( (strMenuTitle.empty() ) ? (iLastSelection - 1) : (iLastSelection + 1) ) );
  251.       std::cout << strRightSelector;
  252.  
  253.       iKeyPress = VP_GetCh();
  254.  
  255.       // Handle User Input
  256.       switch (iKeyPress) {
  257.             // User Pressed Up
  258.          case VK_UP:
  259.             // Clear Left Selector
  260.             VP_GoToXY ( ( (posHPosition == RIGHT) ? (79 - strRightSelector.length() - vMenuOptions[ (iLastSelection - 1)].length() - strLeftSelector.length() ) :
  261.                           (posHPosition == CENTER) ? ( (79 - vMenuOptions[ (iLastSelection - 1)].length() ) / 2 - strLeftSelector.length() ) :
  262.                           /*(posHPosition == LEFT) ?*/ 0),
  263.                         ( (posVPosition == BOTTOM) ? (25 - Size() - 2) :
  264.                           (posVPosition == CENTER) ? ( (25 - Size() - 2) / 2) :
  265.                           /*(posVPosition == TOP) ?*/ 0) + ( (strMenuTitle.empty() ) ? (iLastSelection - 1) : (iLastSelection + 1) ) );
  266.             for (unsigned int i = 0; i < strLeftSelector.length(); i ++)
  267.                std::cout << " ";
  268.  
  269.             // Clear Right Selector
  270.             VP_GoToXY ( ( (posHPosition == RIGHT) ? (79 - strRightSelector.length() ) :
  271.                           (posHPosition == CENTER) ? ( (79 + vMenuOptions[ (iLastSelection - 1)].length() ) / 2) :
  272.                           /*(posHPosition == LEFT) ?*/ strLeftSelector.length() + vMenuOptions[ (iLastSelection - 1)].length() ),
  273.                         ( (posVPosition == BOTTOM) ? (25 - Size() - 2) :
  274.                           (posVPosition == CENTER) ? ( (25 - Size() - 2) / 2) :
  275.                           /*(posVPosition == TOP) ?*/ 0) + ( (strMenuTitle.empty() ) ? (iLastSelection - 1) : (iLastSelection + 1) ) );
  276.             for (unsigned int i = 0; i < strRightSelector.length(); i ++)
  277.                std::cout << " ";
  278.  
  279.             // Set iLastSelection and allow for loop around
  280.             iLastSelection = ( (iLastSelection == 1) ? ( (bWrapAround) ? vMenuOptions.size() : 1) : (iLastSelection - 1) );
  281.             break;
  282.  
  283.             // User Pressed Down
  284.          case VK_DOWN:
  285.             // Clear Left Selector
  286.             VP_GoToXY ( ( (posHPosition == RIGHT) ? (79 - strRightSelector.length() - vMenuOptions[ (iLastSelection - 1)].length() - strLeftSelector.length() ) :
  287.                           (posHPosition == CENTER) ? ( (79 - vMenuOptions[ (iLastSelection - 1)].length() ) / 2 - strLeftSelector.length() ) :
  288.                           /*(posHPosition == LEFT) ?*/ 0),
  289.                         ( (posVPosition == BOTTOM) ? (25 - Size() - 2) :
  290.                           (posVPosition == CENTER) ? ( (25 - Size() - 2) / 2) :
  291.                           /*(posVPosition == TOP) ?*/ 0) + ( (strMenuTitle.empty() ) ? (iLastSelection - 1) : (iLastSelection + 1) ) );
  292.             for (unsigned int i = 0; i < strLeftSelector.length(); i ++)
  293.                std::cout << " ";
  294.  
  295.             // Clear Right Selector
  296.             VP_GoToXY ( ( (posHPosition == RIGHT) ? (79 - strRightSelector.length() ) :
  297.                           (posHPosition == CENTER) ? ( (79 + vMenuOptions[ (iLastSelection - 1)].length() ) / 2) :
  298.                           /*(posHPosition == LEFT) ?*/ strLeftSelector.length() + vMenuOptions[ (iLastSelection - 1)].length() ),
  299.                         ( (posVPosition == BOTTOM) ? (25 - Size() - 2) :
  300.                           (posVPosition == CENTER) ? ( (25 - Size() - 2) / 2) :
  301.                           /*(posVPosition == TOP) ?*/ 0) + ( (strMenuTitle.empty() ) ? (iLastSelection - 1) : (iLastSelection + 1) ) );
  302.             for (unsigned int i = 0; i < strRightSelector.length(); i ++)
  303.                std::cout << " ";
  304.  
  305.             // Set iLastSelection and allow for loop around
  306.             iLastSelection = ( (iLastSelection == vMenuOptions.size() ) ? ( (bWrapAround) ? 1 : vMenuOptions.size() ) : (iLastSelection + 1) );
  307.             break;
  308.  
  309.             // User Pressed Enter
  310.          case VK_RETURN:
  311.             if(vMenuFunctions[(iLastSelection - 1)]) {
  312.                VP_ClearScreen();
  313.                vMenuFunctions[(iLastSelection - 1)]();
  314.             }
  315.             Draw();
  316.       }
  317.    } while (vMenuFunctions[(iLastSelection - 1)] || (iKeyPress != VK_RETURN));
  318. }
  319.  
  320. void DrawBoard(int board[], std::string players[]) {
  321.    for (int i = 0; i < 9; i ++) {
  322.       VP_GoToXY(37 + ((i % 3) * 2), 11 + ((i / 3) * 2));
  323.       std::cout << ((board[i]) ? ((board[i] == 1) ? "X" : "O") : " ");
  324.       if (i % 3 == 2) {
  325.          if (i / 3 != 2) {
  326.             VP_GoToXY(37, 12 + ((i / 3) * 2));
  327.             std::cout << static_cast<char> (196)
  328.                       << static_cast<char> (197)
  329.                       << static_cast<char> (196)
  330.                       << static_cast<char> (197)
  331.                       << static_cast<char> (196);
  332.          }
  333.       }
  334.       else
  335.          std::cout << static_cast<char> (179);
  336.    }
  337.    VP_GoToXY(0, 12);
  338.    std::cout << " " << players[0];
  339.    VP_GoToXY(78 - players[1].length(), 12);
  340.    std::cout << players[1];
  341. }
  342.  
  343. void Move(int board[], std::string players[], int &player) {
  344.    DrawBoard(board, players);
  345.    VP_GoToXY(((player == 1) ? 0 : 78 - players[1].length()), 12);
  346.    std::cout << "<" << players[player - 1] << ">";
  347.    int position = 1;
  348.    while (board[(position - 1)])
  349.       position ++;
  350.    int keyPress;
  351.    do {
  352.       VP_GoToXY(37 + (((position - 1) % 3) * 2), 11 + (((position - 1) / 3) * 2));
  353.       std::cout << ((player == 1) ? "X" : "O");
  354.       keyPress = VP_GetCh();
  355.       VP_GoToXY(37 + (((position - 1) % 3) * 2), 11 + (((position - 1) / 3) * 2));
  356.       std::cout << " ";
  357.       do {
  358.          if (keyPress == VK_RIGHT)
  359.             position = ((position < 9) ? (position + 1) : 1);
  360.          if (keyPress == VK_LEFT)
  361.             position = ((position > 1) ? (position - 1) : 9);
  362.          if (keyPress == VK_DOWN) {
  363.             position = ((position < 9) ? (position + 3) : 1);
  364.             if (position > 9)
  365.                position = position - 9 + 1;
  366.          }
  367.          if (keyPress == VK_UP) {
  368.             position = ((position > 1) ? (position - 3) : 9);
  369.             if (position < 1)
  370.                position = position + 9 - 1;
  371.          }
  372.       } while (board[(position - 1)]);
  373.    } while (keyPress != VK_RETURN);
  374.    board[(position - 1)] = player;
  375.    VP_GoToXY(((player == 1) ? 0 : 78 - players[1].length()), 12);
  376.    std::cout << " " << players[player - 1] << " ";
  377.    player = ((player == 1) ? 2 : 1);
  378. }
  379.  
  380. int Winner(int board[]) {
  381.    for(int i = 0; i < 3; i ++)
  382.       // Horizontal Victory
  383.       if (board[(i * 3) + 0] == board[(i * 3) + 1]
  384.        && board[(i * 3) + 1] == board[(i * 3) + 2])
  385.          return board[(i * 3) + 0];
  386.  
  387.       // Vertical Victory
  388.       else if (board[(0 * 3) + i] == board[(1 * 3) + i]
  389.             && board[(1 * 3) + i] == board[(2 * 3) + i])
  390.          return board[(0 * 3) + i];
  391.  
  392.    // Diagonal Victory
  393.    if (board[0] == board[4] && board[4] == board[8])
  394.       return board[0];
  395.    if (board[2] == board[4] && board[4] == board[6])
  396.       return board[2];
  397.    // Draw
  398.    int moves = 0;
  399.    for (int i = 0; i < 9; i ++)
  400.       if (board[i])
  401.          moves ++;
  402.    if (moves == 9)
  403.       return 3;
  404.    return 0;
  405. }
  406.  
  407. void TicTacToe() {
  408.    // Create game board
  409.    int tttBoard[] = {
  410.       0,0,0,
  411.       0,0,0,
  412.       0,0,0
  413.    };
  414.    // Create player
  415.    int player = 1;
  416.    // Create winner
  417.    int winner;
  418.    // Create player names
  419.    std::string players[] = {
  420.       "Becky",
  421.       "Zach"
  422.    };
  423.    DrawBoard(tttBoard, players);
  424.    do {
  425.       Move(tttBoard, players, player);
  426.    } while (!(winner = Winner(tttBoard)));
  427.  
  428.    VP_ClearScreen();
  429.    DrawBoard(tttBoard, players);
  430.    VP_GoToXY(26, 17);
  431.  
  432.    // Player won
  433.    if (winner != 3)
  434.       std::cout << players[(winner - 1)] << " won! Great Job!";
  435.    // Draw
  436.    else
  437.       std::cout << "No one won! Game ended in a Draw!";
  438.    std::cout << "\nPress any key to continue...";
  439.    VP_GetCh();
  440. }
  441.  
  442. int main() {
  443.    VP_SetConsoleCursor(false);
  444.    // Define Settings Menu
  445.    //Menu SettingsMenu("Settings", "-> ", " <-", CENTER, CENTER);
  446.    // Define Main Menu
  447.    Menu MainMenu("Tic-Tac-Toe", "-> ", " <-", CENTER, CENTER);
  448.    MainMenu.AddOption("Play Tic-Tac-Toe", TicTacToe);
  449.    //MainMenu.AddOption("Settings", std::bind(&Menu::Play, std::ref(SettingsMenu)));
  450.    MainMenu.AddOption("Exit");
  451.  
  452.    MainMenu.Play();
  453.  
  454.    return 0;
  455. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement