Advertisement
Guest User

Untitled

a guest
Jan 19th, 2019
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 40.96 KB | None | 0 0
  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"); }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement