daily pastebin goal
57%
SHARE
TWEET

Untitled

a guest Jan 19th, 2019 56 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * Developed by:
  3.  *
  4.  * Melina Zikou(melinazgr), Orestis Ousoultzoglou(xlxs4)        20/1/2019
  5.  *
  6.  * ----------------------------------------------------------------------
  7.  *
  8.  * Licensing:
  9.  *
  10.  * The code located in https://github.com/xlxs4/picaria is licensed under
  11.  * the GNU GPL v3.0 license, unless explicitly stated otherwise.
  12.  *
  13.  * ----------------------------------------------------------------------
  14.  *
  15.  ****
  16.  *
  17.  * NAME: PICARIA
  18.  *
  19.  * PURPOSE: To implement the game of tic-tac-toe using the terminal.
  20.  *
  21.  * DESCRIPTION: PICARIA is the result of an essay assigned in the first
  22.  * semester at the Aristotle's University of Thessaloniki(AUTh) CSd.
  23.  * It is written in C, using the terminal as a visual means of
  24.  * implementing the infamous tic-tac-toe game.
  25.  * It currently features the VS Mode, AI Mode and, finally, Statistics.
  26.  * After being greeted by the CLI Menu, the user is able to freely traverse
  27.  * through and tinker with the aforementioned options.
  28.  *
  29.  * OPTIONS:
  30.  *
  31.  * VS Mode      Play Against a Human Opponent(locally)
  32.  *              After both players enter their names and select a sign,
  33.  *              they each take alternating turns (using 1-9 as input).
  34.  *              The game board state gets refreshed after every move
  35.  *              and printed for further convinience of use.
  36.  *              
  37.  * AI Mode      Play Against the Computer
  38.  *              After the player enters his name and selects
  39.  *              his sign of choice, he battles against the AI
  40.  *              in the previously detailed way.
  41.  *          
  42.  * Statistics   The program creates and then uses the file <"stats.txt">
  43.  *              to store each player's records (Wins, Losses, Draws) in
  44.  *              a verbose and easily readable way.
  45.  *              These records get automatically updated after
  46.  *              each game is concluded. The user can also access said records
  47.  *              directly from within the program. In addition, the file
  48.  *              responsible for handling them can be exported and/or
  49.  *              altered in whatever way the user may see fit.
  50.  *  
  51.  * CAVEAT:      This program is used as an educational medium.
  52.  *              No guarantee that this program will successfully work on all
  53.  *              platforms, nor that trapping of inconsistent parameters is
  54.  *              complete and foolproof. Use At Your Own Risk.
  55.  *
  56.  ****      
  57.  *
  58.  */
  59.  
  60. #include <assert.h>
  61. #include <conio.h>
  62. #include <ctype.h>
  63. #include <malloc.h>
  64. #include <stdlib.h>
  65. #include <stdio.h>
  66. #include <string.h>
  67.  
  68. #define NAME_SIZE 250
  69. #define PLAYER1 1
  70. #define PLAYER2 -1
  71. #define COMPUTER PLAYER2
  72. #define EMPTY 0
  73.  
  74. /*
  75.  * From here on out is the code split into various
  76.  * .c and .h files merged together.
  77. */
  78.  
  79. // ------------------------------------------------
  80.  
  81. /* <players.h>
  82.  * This file contained the code responsible for all the
  83.  * player-related functions declarations.
  84. */
  85.  
  86.  
  87. typedef struct
  88. {
  89.     char *name;
  90.     int loss;
  91.     int win;
  92.     int draw;
  93. } Player;
  94.  
  95. Player *g_players = NULL;
  96. int g_sign1, g_sign2;
  97. int g_player1 = PLAYER1, g_player2 = PLAYER2;
  98. int g_playerCount = 0;
  99. int g_evalcount = 0;
  100.  
  101. Player *addPlayer(Player *players, char *name, int *playerCount);
  102.  
  103. int findPlayer(Player *players, int playerCount, char *name);
  104.  
  105. void freePlayers(Player *players);
  106.  
  107. void printPlayerStats(Player *players, int playerCount);
  108.  
  109. Player *loadStats(int *playerCount);
  110.  
  111. void saveStats(Player *players, int playerCount);
  112.  
  113. void addWin(Player *players, int indexPlayer);
  114.  
  115. void addLoss(Player *players, int indexPlayer);
  116.  
  117. void addDraw(Player *players, int indexPlayer);
  118.  
  119. int countNameLetters(char *name);
  120.  
  121. int maxNameSize(Player *players);
  122.  
  123. char *mygets(char *buffer, int size);
  124.  
  125. int isEmpty(const char *s);
  126.  
  127. /* <tictactoe.h>
  128.  * This file contained the code responsible for all the
  129.  * game-logic functions declarations.
  130. */
  131.  
  132. void initStats();
  133.  
  134. void initBoard(int board[9]);
  135.  
  136. void printBoard(int board[9]);
  137.  
  138. void setBoardPosition(int board[9], int position, int value);
  139.  
  140. int getBoardPosition(int board[9], int position);
  141.  
  142. int getPlayerPosition(int board[9], int player, char *namePlayer1,
  143.                       char *namePlayer2);
  144.  
  145. void markPlayerPosition(int board[9], int player, int position);
  146.  
  147.  
  148.  
  149. int hasWon(int board[9], int player);
  150.  
  151. void nextTurn(int *turn, int *player, int *opponent);
  152.  
  153. void setSign(char *namePlayer1);
  154.  
  155. int playFirst(char *namePlayer);
  156.  
  157. int movesLeft(int board[9]);
  158.  
  159. int scoreBoard(int board[9], int depth);
  160.  
  161. int max(int a, int b);
  162.  
  163. int min(int a, int b);
  164.  
  165. int minimax(int board[9], int depth, int player);
  166.  
  167. int getBestMove (int board[9]);
  168.  
  169. void clearScreen();
  170.  
  171. void playAgain(int *shouldRun);
  172.  
  173. void printStartingScreen();
  174.  
  175. void printTicTac();
  176.  
  177. void printMenu();
  178.  
  179. void clearStartingScreen();
  180.  
  181. void resizeWindow();
  182.  
  183. int getMenuSelection();
  184.  
  185. void againstComputer();
  186.  
  187. void twoPlayers();
  188.  
  189. void statistics();
  190.  
  191. void exitGame();
  192.  
  193. void pressAnyKey();
  194.  
  195. int main()
  196. {
  197.     int done = 0;
  198.     resizeWindow();
  199.     printStartingScreen();
  200.     pressAnyKey();
  201.     clearScreen();
  202.     printTicTac();
  203.     pressAnyKey();
  204.     clearScreen();
  205.  
  206.     g_players = loadStats(&g_playerCount);
  207.  
  208.     while (!done)
  209.     {
  210.         clearScreen();
  211.         printMenu();
  212.  
  213.         switch (getMenuSelection())
  214.         {
  215.         case 1:
  216.             clearScreen();
  217.             againstComputer();
  218.             break;
  219.         case 2:
  220.             clearScreen();
  221.             twoPlayers();
  222.             break;
  223.         case 3:
  224.             clearScreen();
  225.             statistics();
  226.             break;
  227.         case 4:
  228.             exitGame();
  229.             done = 1;
  230.             break;
  231.         }
  232.     }
  233.  
  234.     if (g_players != NULL)
  235.     {
  236.         freePlayers(g_players);
  237.         g_players = NULL;
  238.     }
  239.  
  240.     return 0;
  241. }
  242.  
  243. /* <players.c>
  244.  * This file contained the code responsible
  245.  *  for all the player-related functions.
  246. */
  247.  
  248. //
  249. // Adds player to the array of players.
  250. // Input
  251. //    players - existing array of players
  252. //    name - name of player to add
  253. //    playerCount - num of existing players in array
  254. // Output
  255. //    playerCount - updated number of players
  256. // Return
  257. //    returns new array of players
  258. //
  259.  
  260. Player *addPlayer(Player *players, char *name, int *playerCount)
  261. {
  262.     Player *newPlayers;
  263.     if (players == NULL)
  264.     {
  265.         newPlayers = (Player *)malloc(sizeof(Player));
  266.     }
  267.     else
  268.     {
  269.         newPlayers =
  270.             (Player *)realloc(players, (*playerCount + 1) * sizeof(Player));
  271.     }
  272.  
  273.     if (newPlayers == NULL)
  274.     {
  275.         fprintf(stderr, "Memory realloc error\n");
  276.         return NULL;
  277.     }
  278.  
  279.     memset(&newPlayers[*playerCount], 0, sizeof(Player));
  280.     newPlayers[*playerCount].name = (char *)malloc(strlen(name) + 1);
  281.     strcpy(newPlayers[*playerCount].name, name);
  282.     *playerCount = *playerCount + 1;
  283.  
  284.     return newPlayers;
  285. }
  286.  
  287. //
  288. // Checks if a player already exists.
  289. // Input
  290. //    players - existing array of players
  291. //    name - name of player to add
  292. //    playerCount - num of existing players in array
  293. // Return
  294. //    returns the index of the player if the player exists
  295. //    -1 if it doesn't
  296. //
  297.  
  298. int findPlayer(Player *players, int playerCount, char *name)
  299. {
  300.     int i;
  301.     for (i = 0; i < playerCount; i++)
  302.     {
  303.         if (strcmp(name, players[i].name) == 0)
  304.         {
  305.             return i;
  306.         }
  307.     }
  308.  
  309.     return -1;
  310. }
  311.  
  312. //
  313. // Prints player statistics.
  314. // Input
  315. //    players - existing array of players
  316. //    name - name of player to add
  317. //    playerCount - num of existing players in array
  318. // Output
  319. //    board of player stats
  320. //
  321.  
  322. void printPlayerStats(Player *players, int playerCount)
  323. {
  324.     int i, j, space;
  325.     int max = maxNameSize(players);
  326.  
  327.     printf("\n");
  328.     printf(" PLAYER STATISTICS\n");
  329.     printf("\n");
  330.  
  331.     for (i = 0; i < max / 2; i++)
  332.     {
  333.         printf(" ");
  334.     }
  335.  
  336.     printf("NAME");
  337.  
  338.     for (i = 0; i < max / 2; i++)
  339.     {
  340.         printf(" ");
  341.     }
  342.  
  343.     printf("WINS  LOSSES  DRAWS \n\n");
  344.  
  345.     for (i = 0; i < playerCount; i++)
  346.     {
  347.         if (players[i].name[0] != '\0')
  348.         {
  349.             printf("  %s", players[i].name);
  350.             space = max - strlen(players[i].name);
  351.  
  352.             for (j = 0; j < space; j++)
  353.             {
  354.                 printf(" ");
  355.             }
  356.  
  357.             printf("%4d%7d%7d", players[i].win, players[i].loss, players[i].draw);
  358.         }
  359.  
  360.         printf("\n\n");
  361.     }
  362.     printf("\n");
  363.  
  364. }
  365.  
  366. //
  367. // Frees the dynamically allocated part of the memory
  368. // responsible for storing/handling players information
  369. // Input
  370. //    players - existing array of players
  371. //
  372.  
  373. void freePlayers(Player *players)
  374. {
  375.     int i;
  376.  
  377.     if (players != NULL)
  378.     {
  379.         for (i = 0; i < g_playerCount; i++)
  380.         {
  381.             free(players[i].name);
  382.         }
  383.  
  384.         free(players);
  385.     }
  386. }
  387.  
  388. // Adds a win in player's stats.
  389.  
  390. void addWin(Player *players, int indexPlayer) { players[indexPlayer].win++; }
  391.  
  392. // Adds a loss in player's stats.
  393.  
  394. void addLoss(Player *players, int indexPlayer) { players[indexPlayer].loss++; }
  395.  
  396. // Adds a draw in player's stats.
  397.  
  398. void addDraw(Player *players, int indexPlayer) { players[indexPlayer].draw++; }
  399.  
  400. //
  401. // Reads stats from txt file and saves it in array.
  402. // Input
  403. //    playerCount - num of existing players in array
  404. // Return
  405. //    array of players
  406. //
  407.  
  408. Player *loadStats(int *playerCount)
  409. {
  410.     int i;
  411.     int win, loss, draw;
  412.     int count;
  413.     char name[NAME_SIZE];
  414.     Player *players = NULL;
  415.  
  416.     FILE *fpstats;
  417.  
  418.     fpstats = fopen("stats.txt", "r");
  419.  
  420.     // If the file does not exist it will be created later on.
  421.  
  422.     if (fpstats != NULL)
  423.     {
  424.         fscanf(fpstats, "%d", &count);
  425.         players = (Player *)malloc(count * sizeof(Player));
  426.  
  427.         if (players != NULL)
  428.         {
  429.             for (i = 0; i < count; i++)
  430.             {
  431.                 if (feof(fpstats))
  432.                 {
  433.                     break;
  434.                 }
  435.  
  436.                 fscanf(fpstats, "%s %d %d %d", name, &win, &loss, &draw);
  437.                 players[i].name = (char *)malloc(strlen(name) + 1);
  438.                 strcpy(players[i].name, name);
  439.                 players[i].win = win;
  440.                 players[i].loss = loss;
  441.                 players[i].draw = draw;
  442.             }
  443.  
  444.             *playerCount = i;
  445.         }
  446.  
  447.         fclose(fpstats);
  448.     }
  449.  
  450.     return players;
  451. }
  452.  
  453. //
  454. // Save stats in txt file.
  455. // Input
  456. //    players - existing array of players
  457. //    playerCount - num of existing players in array
  458. //  
  459.  
  460. void saveStats(Player *players, int playerCount)
  461. {
  462.     int i;
  463.     FILE *fpstats;
  464.     fpstats = fopen("stats.txt", "w");
  465.  
  466.     // If the file does not exist it will be created later on.
  467.     if (fpstats != NULL)
  468.     {
  469.         fprintf(fpstats, "%d\n", playerCount);
  470.         if (players != NULL)
  471.         {
  472.             for (i = 0; i < playerCount; i++)
  473.             {
  474.                 fprintf(fpstats, "%s\n%d %d %d\n", players[i].name, players[i].win,
  475.                         players[i].loss, players[i].draw);
  476.             }
  477.         }
  478.  
  479.         fclose(fpstats);
  480.     }
  481. }
  482.  
  483. //
  484. // Finds max name size in existing array of players.
  485. // Input
  486. //    players - existing array of players
  487. // Return
  488. //    max name size
  489. //
  490.  
  491. int maxNameSize(Player *players)
  492. {
  493.     int i, max = 0;
  494.  
  495.     for (i = 0; i < g_playerCount; i++)
  496.     {
  497.         if (strlen(players[i].name) > max)
  498.         {
  499.             max = strlen(players[i].name);
  500.         }
  501.     }
  502.  
  503.     return max;
  504. }
  505.  
  506. //
  507. // Reads a line from the user with max charactes the int size.
  508. // Input
  509. //    buffer - where to store the string
  510. //    size - max size of buffer
  511. // output
  512. //    stores the string into the buffer
  513. // return
  514. //    if string is larger than the buffer the string is truncated
  515. //
  516.  
  517. char *mygets(char *buffer, int size)
  518. {
  519.     fgets(buffer, size, stdin);
  520.     int i;
  521.     for (i = 0; i < size; i++)
  522.     {
  523.         if (buffer[i] == '\n')
  524.         {
  525.             buffer[i] = '\0';
  526.             break;
  527.         }
  528.     }
  529.  
  530.     buffer[size - 1] = '\0';
  531.     return 0;
  532. }
  533.  
  534. //
  535. // Checks whether a given string is empty.
  536. // (""  or <contains_only_whitespace)
  537. // Input
  538. //    string *s
  539. // Return
  540. //    1 if string is empty; 0 otherwise
  541. //
  542.  
  543. int isEmpty(const char *s)
  544. {
  545.     while (*s != '\0')
  546.     {
  547.         if (!isspace((unsigned char)*s))
  548.         {
  549.             return 0;
  550.         }
  551.         s++;
  552.     }
  553.     return 1;
  554. }
  555.  
  556. /* <tictactoe.c>
  557.  * This file contained the code responsible
  558.  *  for all the game logic functions.
  559. */
  560.  
  561. void initBoard(int board[9])
  562. {
  563.     int i;
  564.     for (i = 0; i < 9; i++)
  565.     {
  566.         board[i] = 0;
  567.     }
  568. }
  569.  
  570. void setBoardPosition(int board[9], int position, int value)
  571. {
  572.     assert(position >= 1 && position <= 9);
  573.     board[position - 1] = value;
  574. }
  575.  
  576. int getBoardPosition(int board[9], int position)
  577. {
  578.     assert(position >= 1 && position <= 9);
  579.     return board[position - 1];
  580. }
  581.  
  582. void printBoard(int board[9])
  583. {
  584.     char space[50];
  585.     memset(space, 32, sizeof(space));
  586.     space[49] = 0;
  587.     printf("%s", space);
  588.     printf("------------------------------------\n");
  589.     printf("%s", space);
  590.     printf("|           |           |          |\n");
  591.     printf("%s", space);
  592.     printf("|           |           |          |\n");
  593.     printf("%s", space);
  594.     printf("|     %c     |     %c     |     %c    |\n", (char)(board[0]),
  595.            (char)(board[1]), (char)(board[2]));
  596.  
  597.     printf("%s", space);
  598.     printf("|           |           |          |\n");
  599.     printf("%s", space);
  600.     printf("|           |           |          |\n");
  601.     printf("%s", space);
  602.     printf("------------------------------------\n");
  603.     printf("%s", space);
  604.     printf("|           |           |          |\n");
  605.     printf("%s", space);
  606.     printf("|           |           |          |\n");
  607.     printf("%s", space);
  608.     printf("|     %c     |     %c     |     %c    |\n", (char)(board[3]),
  609.            (char)(board[4]), (char)(board[5]));
  610.  
  611.     printf("%s", space);
  612.     printf("|           |           |          |\n");
  613.     printf("%s", space);
  614.     printf("|           |           |          |\n");
  615.     printf("%s", space);
  616.     printf("------------------------------------\n");
  617.     printf("%s", space);
  618.     printf("|           |           |          |\n");
  619.     printf("%s", space);
  620.     printf("|           |           |          |\n");
  621.     printf("%s", space);
  622.     printf("|     %c     |     %c     |     %c    |\n", (char)(board[6]),
  623.            (char)(board[7]), (char)(board[8]));
  624.  
  625.     printf("%s", space);
  626.     printf("|           |           |          |\n");
  627.     printf("%s", space);
  628.     printf("|           |           |          |\n");
  629.     printf("%s", space);
  630.     printf("------------------------------------\n");
  631.  
  632.     printf("\n");
  633. }
  634.  
  635. int hasWon(int board[9], int player)
  636. {
  637.     int sign;
  638.     if (player == PLAYER1)
  639.     {
  640.         sign = g_sign1;
  641.     }
  642.     else
  643.     {
  644.         sign = g_sign2;
  645.     }
  646.  
  647.     return ((board[0] == sign && board[1] == sign && board[2] == sign) ||
  648.             (board[3] == sign && board[4] == sign && board[5] == sign) ||
  649.             (board[6] == sign && board[7] == sign && board[8] == sign) ||
  650.             (board[0] == sign && board[3] == sign && board[6] == sign) ||
  651.             (board[1] == sign && board[4] == sign && board[7] == sign) ||
  652.             (board[2] == sign && board[5] == sign && board[8] == sign) ||
  653.             (board[0] == sign && board[4] == sign && board[8] == sign) ||
  654.             (board[2] == sign && board[4] == sign && board[6] == sign))
  655.                ? 1
  656.                : 0;
  657. }
  658.  
  659. void setSign(char *namePlayer1)
  660. {
  661.     char selection;
  662.     printf("select your desired sign %s\n", namePlayer1);
  663.     printf("press either X or O\n");
  664.     do
  665.     {
  666.         selection = toupper(getch());
  667.         switch (selection)
  668.         {
  669.         case 'X':
  670.             g_sign1 = 'X', g_sign2 = 'O';
  671.             break;
  672.         case 'O':
  673.             g_sign1 = 'O', g_sign2 = 'X';
  674.             break;
  675.         default:
  676.             printf("choose between X and O!\n");
  677.             break;
  678.         }
  679.  
  680.     } while (selection != 'X' && selection != 'O');
  681. }
  682.  
  683. void nextTurn(int *turn, int *player, int *opponent)
  684. {
  685.     (*turn)++;
  686.     if (*player == PLAYER1)
  687.     {
  688.         *player = PLAYER2;
  689.         *opponent = PLAYER1;
  690.     }
  691.     else
  692.     {
  693.         *player = PLAYER1;
  694.         *opponent = PLAYER2;
  695.     }
  696. }
  697.  
  698. //
  699. // Gets the position of the user to play.
  700. //  Input
  701. //    player - the player to mark position
  702. //
  703. //  Return
  704. //    the position to play, value 1-9
  705. //
  706.  
  707. int getPlayerPosition(int board[9], int player, char *namePlayer1,
  708.                       char *namePlayer2)
  709. {
  710.     int position;
  711.     int inputInvalid = 1;
  712.     char selection;
  713.     if (player == 1)
  714.     {
  715.         printf("your turn, player %s. (select 1 - 9): \n", namePlayer1);
  716.     }
  717.     else
  718.     {
  719.         printf("your turn, player %s. (select 1 - 9): \n", namePlayer2);
  720.     }
  721.  
  722.     do
  723.     {
  724.         position = getch();
  725.  
  726.     // Esc
  727.     if (position == 27)
  728.     {
  729.         printf("Would you like to exit? Y/N\n");
  730.         do{
  731.             selection = toupper(getch());
  732.        
  733.         } while(selection != 'Y' && selection != 'N');
  734.  
  735.         if (selection == 'Y')
  736.             return -1;
  737.     }
  738.  
  739.     position = getch() - '0';
  740.  
  741.         if (position < 1 || position > 9)
  742.         {
  743.             printf(
  744.                 "invalid selection, please try again.\
  745.                    Only values 1-9 accepted.\n");
  746.             continue;
  747.         }
  748.  
  749.         if (getBoardPosition(board, position) != 0)
  750.         {
  751.             printf("invalid selection, please try again\n");
  752.         }
  753.         else
  754.         {
  755.             inputInvalid = 0;
  756.         }
  757.  
  758.     } while (inputInvalid);
  759.  
  760.     return position;
  761. }
  762.  
  763. // Marks the position of the player on the board.
  764. //  Input
  765. //     board -
  766. //     player - the player to mark position
  767. //     position - the position to mark, values 1-9
  768. //
  769. //  Return
  770. //
  771.  
  772. void markPlayerPosition(int board[9], int player, int position)
  773. {
  774.     int sign;
  775.     if (player == PLAYER1)
  776.     {
  777.         sign = g_sign1;
  778.     }
  779.     else
  780.     {
  781.         sign = g_sign2;
  782.     }
  783.  
  784.     setBoardPosition(board, position, sign);
  785. }
  786.  
  787. void playAgain(int *shouldRun)
  788. {
  789.     printf("Would you like to play again?\t Y/N\n");
  790.     int inputInvalid = 1;
  791.     do
  792.     {
  793.         char selection;
  794.         selection = toupper(getch());
  795.         if (selection == 'N')
  796.         {
  797.             inputInvalid = 0;
  798.             *shouldRun = 0;
  799.         }
  800.         if (selection == 'Y')
  801.         {
  802.             inputInvalid = 0;
  803.         }
  804.         else
  805.         {
  806.             printf("Invalid selection.\n");
  807.             printf("Would you like to play again?\t Y/N\n");
  808.         }
  809.     } while (inputInvalid);
  810. }
  811.  
  812. void clearScreen() { system("cls"); }
  813.  
  814. void pressAnyKey()
  815. {
  816.     printf("Press any key to continue\n");
  817.     getch();
  818. }
  819.  
  820. void printStartingScreen(void)
  821. {
  822.     printf(
  823.         ".----------------.  .----------------.  .----------------.  "
  824.         ".----------------.  .----------------.  .----------------.  "
  825.         ".----------------.  \n");
  826.     printf(
  827.         "| .--------------. || .--------------. || .--------------. || "
  828.         ".--------------. || .--------------. || .--------------. || "
  829.         ".--------------. |\n");
  830.     printf(
  831.         "| |   ______     | || |     _____    | || |     ______   | || |      __ "
  832.         "     | || |  _______     | || |     _____    | || |      __      | |\n");
  833.     printf(
  834.         "| |  |_   __ \\   | || |    |_   _|   | || |   .' ___  |  | || |     /  "
  835.         "\\     | || | |_   __ \\    | || |    |_   _|   | || |     /  \\     | "
  836.         "|\n");
  837.     printf(
  838.         "| |    | |__) |  | || |      | |     | || |  / .'   \\_|  | || |    / "
  839.         "/\\ \\    | || |   | |__) |   | || |      | |     | || |    / /\\ \\    "
  840.         "| |\n");
  841.     printf(
  842.         "| |    |  ___/   | || |      | |     | || |  | |         | || |   / "
  843.         "____ \\   | || |   |  __ /    | || |      | |     | || |   / ____ \\   "
  844.         "| |\n");
  845.     printf(
  846.         "| |   _| |_      | || |     _| |_    | || |  \\ `.___.'\\  | || | _/ /  "
  847.         "  \\ \\_ | || |  _| |  \\ \\_  | || |     _| |_    | || | _/ /    \\ "
  848.         "\\_ | |\n");
  849.     printf(
  850.         "| |  |_____|     | || |    |_____|   | || |   `._____.'  | || ||____|  "
  851.         "|____|| || | |____| |___| | || |    |_____|   | || ||____|  |____|| "
  852.         "|\n");
  853.     printf(
  854.         "| |              | || |              | || |              | || |         "
  855.         "     | || |              | || |              | || |              | |\n");
  856.     printf(
  857.         "| '--------------' || '--------------' || '--------------' || "
  858.         "'--------------' || '--------------' || '--------------' || "
  859.         "'--------------' |\n");
  860.     printf(
  861.         " '----------------'  '----------------'  '----------------'  "
  862.         "'----------------'  '----------------'  '----------------'  "
  863.         "'----------------' \n");
  864.  
  865.     printf(
  866.         "                                                                        "
  867.         "                                                                    \n");
  868.     printf(
  869.         "                                                                        "
  870.         "                                                                    \n");
  871.     printf(
  872.         "                                                                        "
  873.         "                                                                    \n");
  874.     printf(
  875.         "                                                                        "
  876.         "                                                                    \n");
  877.     printf(
  878.         "                                                                        "
  879.         "                                                                    \n");
  880.     printf(
  881.         "                                                   _   _      _         "
  882.         "    _                                                               \n");
  883.     printf(
  884.         "                                                  | | (_)    | |        "
  885.         "   | |                                                              \n");
  886.     printf(
  887.         "                                                  | |_ _  ___| |_ __ _  "
  888.         "___| |_ ___   ___                                                   \n");
  889.     printf(
  890.         "                                                  | __| |/ __| __/ _` "
  891.         "|/ __| __/ _ \\ / _ \\                                                "
  892.         "\n");
  893.     printf(
  894.         "                                                  | |_| | (__| || (_| | "
  895.         "(__| || (_) |  __/                                                  \n");
  896.     printf(
  897.         "                                                   "
  898.         "\\__|_|\\___|\\__\\__,_|\\___|\\__\\___/ \\___|                         "
  899.         "                 \n");
  900.     printf(
  901.         "                                                                        "
  902.         "                                                                    \n");
  903.     printf(
  904.         "                                                                        "
  905.         "                                                                    \n");
  906.     printf(
  907.         "                                                                        "
  908.         "                                                                    \n");
  909.     printf(
  910.         "                                                                        "
  911.         "                                                                    \n");
  912.     printf(
  913.         "                                                                        "
  914.         "                                                                    \n");
  915.     printf(
  916.         "                                                                        "
  917.         "                                                                    \n");
  918.     printf(
  919.         "                                                                        "
  920.         "                                                                    \n");
  921.     printf(
  922.         "                                                                        "
  923.         "                                                                    \n");
  924.     printf(
  925.         "                                                                        "
  926.         "                                                                    \n");
  927. }
  928.  
  929. void printTicTac()
  930. {
  931.     printf(
  932.         "                                                                        "
  933.         "                                                                    \n");
  934.     printf(
  935.         "                                                                        "
  936.         "                                                                    \n");
  937.     printf(
  938.         "                                                          ||            "
  939.         "       ||                                                           \n");
  940.     printf(
  941.         "                                                          ||            "
  942.         "       ||                                                           \n");
  943.     printf(
  944.         "                                               o  o       ||     \\\\   "
  945.         " //      ||       o  o                                             \n");
  946.     printf(
  947.         "                                            o        o    ||      \\\\  "
  948.         "//       ||    o        o                                          \n");
  949.     printf(
  950.         "                                           o          o   ||       "
  951.         "\\\\//        ||   o          o                                         "
  952.         "\n");
  953.     printf(
  954.         "                                           o          o   ||       "
  955.         "//\\\\        ||   o          o                                         "
  956.         "\n");
  957.     printf(
  958.         "                                            o        o    ||      //  "
  959.         "\\\\       ||    o        o                                          "
  960.         "\n");
  961.     printf(
  962.         "                                               o  o       ||     //    "
  963.         "\\\\      ||       o  o                                             \n");
  964.     printf(
  965.         "                                                          ||            "
  966.         "       ||                                                           \n");
  967.     printf(
  968.         "                                     "
  969.         "|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||       "
  970.         "                               \n");
  971.     printf(
  972.         "                                                          ||            "
  973.         "       ||                                                           \n");
  974.     printf(
  975.         "                                               o  o       ||     \\\\   "
  976.         " //      ||                                                        \n");
  977.     printf(
  978.         "                                            o        o    ||      \\\\  "
  979.         "//       ||                                                        \n");
  980.     printf(
  981.         "                                           o          o   ||       "
  982.         "\\\\//        ||                                                        "
  983.         "\n");
  984.     printf(
  985.         "                                           o          o   ||       "
  986.         "//\\\\        ||                                                        "
  987.         "\n");
  988.     printf(
  989.         "                                            o        o    ||      //  "
  990.         "\\\\       ||                                                        "
  991.         "\n");
  992.     printf(
  993.         "                                               o  o       ||     //    "
  994.         "\\\\      ||                                                        \n");
  995.     printf(
  996.         "                                                          ||            "
  997.         "       ||                                                           \n");
  998.     printf(
  999.         "                                     "
  1000.         "|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||       "
  1001.         "                               \n");
  1002.     printf(
  1003.         "                                                          ||            "
  1004.         "       ||                                                           \n");
  1005.     printf(
  1006.         "                                               o  o       ||            "
  1007.         "       ||     \\\\    //                                           \n");
  1008.     printf(
  1009.         "                                            o        o    ||            "
  1010.         "       ||      \\\\  //                                            \n");
  1011.     printf(
  1012.         "                                           o          o   ||            "
  1013.         "       ||       \\\\//                                             \n");
  1014.     printf(
  1015.         "                                           o          o   ||            "
  1016.         "       ||       //\\\\                                             \n");
  1017.     printf(
  1018.         "                                            o        o    ||            "
  1019.         "       ||      //  \\\\                                            \n");
  1020.     printf(
  1021.         "                                               o  o       ||            "
  1022.         "       ||     //    \\\\                                           \n");
  1023.     printf(
  1024.         "                                                          ||            "
  1025.         "       ||                                                           \n");
  1026.     printf(
  1027.         "                                                          ||            "
  1028.         "       ||                                                           \n");
  1029. }
  1030.  
  1031. void printMenu()
  1032. {
  1033.     printf("                                        \n");
  1034.     printf("                                        \n");
  1035.     printf("         MAIN MENU                      \n");
  1036.     printf("                                        \n");
  1037.     printf("         Press 1 - 4 to choose          \n");
  1038.     printf("                                        \n");
  1039.     printf("                                        \n");
  1040.     printf("         1. PLAY AGAINST THE COMPUTER   \n");
  1041.     printf("                                        \n");
  1042.     printf("         2. PLAY AGAINST AN OPPONENT    \n");
  1043.     printf("                                        \n");
  1044.     printf("         3. VIEW PLAYER STATISTICS      \n");
  1045.     printf("                                        \n");
  1046.     printf("         4. EXIT GAME                   \n");
  1047.     printf("                                        \n");
  1048. }
  1049.  
  1050. int getMenuSelection()
  1051. {
  1052.     int inputInvalid = 1;
  1053.     int menuSelection;
  1054.     do
  1055.     {
  1056.         menuSelection = getch() - '0';
  1057.         if (menuSelection < 1 || menuSelection > 4)
  1058.         {
  1059.             continue;
  1060.         }
  1061.         else
  1062.         {
  1063.             inputInvalid = 0;
  1064.             return menuSelection;
  1065.         }
  1066.  
  1067.     } while (inputInvalid);
  1068.  
  1069.     return menuSelection;
  1070. }
  1071.  
  1072.  
  1073. void twoPlayers()
  1074. {
  1075.     int board[9];
  1076.     int shouldRun = 1;
  1077.     int position;
  1078.  
  1079.     while (shouldRun)
  1080.     {
  1081.         int turn = 1;
  1082.         int player = g_player1;
  1083.         int opponent = g_player2;
  1084.         int nameEmpty;
  1085.         int playerFound;
  1086.         int inputInvalid = 1;
  1087.         char namePlayer1[NAME_SIZE], namePlayer2[NAME_SIZE];
  1088.  
  1089.         // Get name for Player1.
  1090.         do
  1091.         {
  1092.             printf("Enter your name Player1: ");
  1093.             mygets(namePlayer1, NAME_SIZE);
  1094.             nameEmpty = isEmpty(namePlayer1);
  1095.             if (nameEmpty == 1)
  1096.             {
  1097.                 printf("Your name must contain at least one character\n");
  1098.             }
  1099.             else
  1100.             {
  1101.                 inputInvalid = 0;
  1102.             }
  1103.         } while (inputInvalid);
  1104.         inputInvalid = 1;
  1105.  
  1106.         playerFound = findPlayer(g_players, g_playerCount, namePlayer1);
  1107.         if (playerFound == -1)
  1108.         {
  1109.             g_players = addPlayer(g_players, namePlayer1, &g_playerCount);
  1110.             if (g_players == NULL)
  1111.             {
  1112.                 break;
  1113.             }
  1114.         }
  1115.  
  1116.         // Get name for Player2.
  1117.  
  1118.         do
  1119.         {
  1120.             printf("Enter your name Player2: ");
  1121.             mygets(namePlayer2, NAME_SIZE);
  1122.             nameEmpty = isEmpty(namePlayer2);
  1123.             if (nameEmpty == 1)
  1124.             {
  1125.                 printf("Your name must contain at least one character\n");
  1126.             }
  1127.             else
  1128.             {
  1129.                 if (strcmp(namePlayer1, namePlayer2) == 0)
  1130.                 {
  1131.                     printf("You need to select a different name"
  1132.                            " other than %s\n",
  1133.                            namePlayer1);
  1134.                 }
  1135.                 else
  1136.                 {
  1137.                     inputInvalid = 0;
  1138.                 }
  1139.             }
  1140.         } while (inputInvalid);
  1141.         inputInvalid = 1;
  1142.  
  1143.         clearScreen();
  1144.  
  1145.         playerFound = findPlayer(g_players, g_playerCount, namePlayer2);
  1146.         if (playerFound == -1)
  1147.         {
  1148.             g_players = addPlayer(g_players, namePlayer2, &g_playerCount);
  1149.             if (g_players == NULL)
  1150.             {
  1151.                 break;
  1152.             }
  1153.         }
  1154.  
  1155.         int indexPlayer1 = findPlayer(g_players, g_playerCount, namePlayer1);
  1156.         int indexPlayer2 = findPlayer(g_players, g_playerCount, namePlayer2);
  1157.  
  1158.         // Start game.
  1159.        
  1160.         setSign(namePlayer1);
  1161.         clearScreen();
  1162.         initBoard(board);
  1163.         printBoard(board);
  1164.  
  1165.         int gameEnded = 0;
  1166.         while (!gameEnded)
  1167.         {
  1168.             position = getPlayerPosition(board, player, namePlayer1, namePlayer2);
  1169.             markPlayerPosition(board, player, position);
  1170.             clearScreen();
  1171.             printBoard(board);
  1172.             if (hasWon(board, player) == 1)
  1173.             {
  1174.                 if (player == 1)
  1175.                 {
  1176.                     printf("Congratulations %s you have won!\n", namePlayer1);
  1177.                     addWin(g_players, indexPlayer1);
  1178.                     addLoss(g_players, indexPlayer2);
  1179.                 }
  1180.                 else
  1181.                 {
  1182.                     printf("Congratulations %s you have won!\n", namePlayer2);
  1183.                     addWin(g_players, indexPlayer2);
  1184.                     addLoss(g_players, indexPlayer1);
  1185.                 }
  1186.  
  1187.                 gameEnded = 1;
  1188.             }
  1189.  
  1190.             nextTurn(&turn, &player, &opponent);
  1191.             if (turn > 9 && (!hasWon(board, PLAYER1) && !hasWon(board, PLAYER2)))
  1192.             {
  1193.                 printf("It's a draw!\n");
  1194.                 addDraw(g_players, indexPlayer1);
  1195.                 addDraw(g_players, indexPlayer2);
  1196.                 gameEnded = 1;
  1197.             }
  1198.         }
  1199.  
  1200.         if (position == -1)
  1201.         break;
  1202.  
  1203.         playAgain(&shouldRun);
  1204.     }
  1205. }
  1206.  
  1207. //
  1208. // Chekcs if there are any positions left to play.
  1209. //
  1210.  
  1211. int movesLeft(int board[9])
  1212. {
  1213.   int i;
  1214.   for(i = 0; i < 9; i++)
  1215.   {
  1216.     if (board[i] == EMPTY)
  1217.       return 1;
  1218.   }
  1219.   return 0;
  1220. }
  1221.  
  1222. //
  1223. // Evaluates the board and returns appropriate score
  1224. // taking in cosideration the depth.
  1225. // If no one has won returns 0.
  1226. //
  1227.  
  1228. int scoreBoard(int board[9], int depth)
  1229. {
  1230.   if (hasWon(board, PLAYER1))
  1231.     return 10 - depth;
  1232.   if (hasWon(board, COMPUTER))
  1233.     return depth - 10;
  1234.  
  1235.   return 0;
  1236. }
  1237.  
  1238. int max(int a, int b)
  1239. {
  1240.   if (a > b)
  1241.     return a;
  1242.   return b;    
  1243. }
  1244.  
  1245. int min(int a, int b)
  1246. {
  1247.   if (a < b)
  1248.     return a;
  1249.   return b;    
  1250. }
  1251.  
  1252. //
  1253. // Implementation of minimax algorithm.
  1254. //
  1255. // Computes all possible games that can be played
  1256. // and returns the value of the board.
  1257. //
  1258. // maximizer = player/PLAYER1
  1259. // minimizer = computer/PLAYER2
  1260. //
  1261.  
  1262. int minimax(int board[9], int depth, int player)
  1263. {  
  1264.     int maximizerScore, minimizerScore;  
  1265.     int i;
  1266.  
  1267.     g_evalcount++;
  1268.    
  1269.     // If the game is in the terminal node
  1270.     // return the score based on the depth
  1271.    
  1272.       if(!movesLeft(board) || hasWon(board, PLAYER1) || hasWon(board, COMPUTER ))  
  1273.         return scoreBoard(board, depth);
  1274.        
  1275.  
  1276.     // maximizer's turn (player)
  1277.     if(player == PLAYER1)
  1278.     {
  1279.         maximizerScore = -10000;
  1280.  
  1281.         for(i = 0; i < 9; i++)
  1282.         {
  1283.             if (board[i] == EMPTY)
  1284.             {
  1285.                 // Makes the move
  1286.                 board[i] = g_sign1;
  1287.  
  1288.                 // Recursion with minimax to find max score
  1289.                 maximizerScore = max ( maximizerScore,
  1290.                                         minimax(board, depth - 1, (-1)*player));
  1291.  
  1292.                 // Undo the move
  1293.                 board[i] = EMPTY;
  1294.             }
  1295.         }
  1296.         return maximizerScore ;
  1297.     }
  1298.  
  1299.     // Minimizer's turn (computer)
  1300.     else
  1301.     {
  1302.         minimizerScore = 10000;
  1303.  
  1304.         for(i = 0; i < 9; i++)
  1305.         {
  1306.             if (board[i] == EMPTY)
  1307.             {
  1308.                 // Makes the move
  1309.                 board[i] = g_sign2;
  1310.  
  1311.                 // Recursion with minimax to find min score
  1312.                 minimizerScore = min ( minimizerScore,
  1313.                                         minimax(board, depth - 1, (-1)*player));
  1314.  
  1315.                 // Undo the move
  1316.                 board[i] = EMPTY;
  1317.             }
  1318.         }
  1319.         return minimizerScore;
  1320.     }
  1321.  
  1322. }
  1323.  
  1324.  
  1325. // Returns the position of the best move
  1326.  
  1327. int getBestMove (int board[9])
  1328. {
  1329.   int bestScore = 10000;
  1330.   int bestMove = -1;
  1331.   int moveScore;
  1332.   int i;
  1333.  
  1334.  g_evalcount = 0;
  1335.  
  1336.   // Goes through all empty cells.
  1337.   // Calls minimax on each empty cell.
  1338.  
  1339.   for(i = 0; i < 9; i++)
  1340.   {
  1341.     g_evalcount = 0;
  1342.     if(board[i] == EMPTY)
  1343.     {
  1344.       board[i] = g_sign2;
  1345.       moveScore = minimax(board, 9, PLAYER1);
  1346.       board[i] = EMPTY;
  1347.  
  1348.       if (moveScore < bestScore)
  1349.       {
  1350.         bestMove = i + 1;
  1351.         bestScore = moveScore;
  1352.       }
  1353.     }
  1354.   }
  1355.  
  1356.   return bestMove;
  1357. }
  1358.  
  1359. //
  1360. // Asks the player if they want to
  1361. // play first against the computer.
  1362. //  Return
  1363. //      1 if they chose to play first
  1364. //      0 otherwise
  1365. //
  1366.  
  1367. int playFirst(char *namePlayer) {
  1368.   char selection;
  1369.   int first = -1;    
  1370.   clearScreen();
  1371.   printf("%s do you want to play first? Y/N \n", namePlayer);
  1372.   do {
  1373.     selection = toupper(getch());
  1374.     if(selection == 'Y')
  1375.         first = 1;
  1376.     if(selection == 'N')
  1377.         first = 0;    
  1378.   } while (first == -1);
  1379.  
  1380.   return first;
  1381. }
  1382.  
  1383.  
  1384. void againstComputer() {
  1385.   int board[9];
  1386.   int shouldRun = 1;
  1387.    int position;
  1388.  
  1389.   while (shouldRun) {
  1390.     int countMoves = 0;
  1391.     int player = g_player1;
  1392.     int playerFound;
  1393.     int inputInvalid = 1;
  1394.     int first;
  1395.    
  1396.     char namePlayer[NAME_SIZE];
  1397.  
  1398.  
  1399.     // Get name for player.
  1400.  
  1401.     do {
  1402.         printf("Enter your name: ");
  1403.         mygets(namePlayer, NAME_SIZE);
  1404.         if (namePlayer[0] != '\0') {
  1405.             inputInvalid = 0;
  1406.         } else {
  1407.             printf("You need to enter a name\n");
  1408.         }
  1409.     } while (inputInvalid);
  1410.     inputInvalid = 1;
  1411.  
  1412.     playerFound = findPlayer(g_players, g_playerCount, namePlayer);
  1413.     if (playerFound == -1) {
  1414.       g_players = addPlayer(g_players, namePlayer, &g_playerCount);
  1415.       if (g_players == NULL) {
  1416.         break;
  1417.       }
  1418.     }
  1419.  
  1420.     clearScreen();
  1421.  
  1422.     int indexPlayer = findPlayer(g_players, g_playerCount, namePlayer);
  1423.  
  1424.     // Start game
  1425.  
  1426.     setSign(namePlayer);
  1427.     first = playFirst(namePlayer);
  1428.    
  1429.     player = g_player1;
  1430.    
  1431.     clearScreen();
  1432.     initBoard(board);
  1433.     printBoard(board);
  1434.  
  1435.     int gameEnded = 0;
  1436.     while (!gameEnded) {
  1437.  
  1438.       if(first % 2 == 1)
  1439.       {
  1440.         position = getPlayerPosition(board, PLAYER1, namePlayer, namePlayer);
  1441.         if(position == -1)
  1442.             break;
  1443.         markPlayerPosition(board, player, position);
  1444.       }
  1445.  
  1446.       if(first % 2 == 0)
  1447.       {
  1448.         position = getBestMove(board);
  1449.         markPlayerPosition(board, PLAYER2, position);
  1450.       }
  1451.      
  1452.       first++;
  1453.       countMoves++;
  1454.       clearScreen();
  1455.       printBoard(board);
  1456.         if (hasWon(board, PLAYER1) == 1)
  1457.         {
  1458.             printf("Congratulations %s you have won!\n", namePlayer);
  1459.             addWin(g_players, indexPlayer);
  1460.             gameEnded = 1;
  1461.         }
  1462.         else if (hasWon(board, PLAYER2) == 1)
  1463.         {
  1464.             printf("%s you have lost!\n", namePlayer);
  1465.             addLoss(g_players, indexPlayer);
  1466.             gameEnded = 1;
  1467.         }
  1468.         else if (countMoves == 9)
  1469.         {
  1470.             printf("It's a draw!\n");
  1471.             addDraw(g_players, indexPlayer);
  1472.             gameEnded = 1;
  1473.         }
  1474.     }
  1475.      if (position == -1)
  1476.         break;
  1477.     playAgain(&shouldRun);
  1478.  
  1479.   }
  1480. }
  1481.  
  1482. void statistics()
  1483. {
  1484.     printPlayerStats(g_players, g_playerCount);
  1485.     pressAnyKey();
  1486. }
  1487.  
  1488. void exitGame() { saveStats(g_players, g_playerCount); }
  1489.  
  1490. void resizeWindow() { system("mode con:cols=140 lines=35"); }
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