Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Developed by:
- *
- * Melina Zikou(melinazgr), Orestis Ousoultzoglou(xlxs4) 20/1/2019
- *
- * ----------------------------------------------------------------------
- *
- * Licensing:
- *
- * The code located in https://github.com/xlxs4/picaria is licensed under
- * the GNU GPL v3.0 license, unless explicitly stated otherwise.
- *
- * ----------------------------------------------------------------------
- *
- ****
- *
- * NAME: PICARIA
- *
- * PURPOSE: To implement the game of tic-tac-toe using the terminal.
- *
- * DESCRIPTION: PICARIA is the result of an essay assigned in the first
- * semester at the Aristotle's University of Thessaloniki(AUTh) CSd.
- * It is written in C, using the terminal as a visual means of
- * implementing the infamous tic-tac-toe game.
- * It currently features the VS Mode, AI Mode and, finally, Statistics.
- * After being greeted by the CLI Menu, the user is able to freely traverse
- * through and tinker with the aforementioned options.
- *
- * OPTIONS:
- *
- * VS Mode Play Against a Human Opponent(locally)
- * After both players enter their names and select a sign,
- * they each take alternating turns (using 1-9 as input).
- * The game board state gets refreshed after every move
- * and printed for further convinience of use.
- *
- * AI Mode Play Against the Computer
- * After the player enters his name and selects
- * his sign of choice, he battles against the AI
- * in the previously detailed way.
- *
- * Statistics The program creates and then uses the file <"stats.txt">
- * to store each player's records (Wins, Losses, Draws) in
- * a verbose and easily readable way.
- * These records get automatically updated after
- * each game is concluded. The user can also access said records
- * directly from within the program. In addition, the file
- * responsible for handling them can be exported and/or
- * altered in whatever way the user may see fit.
- *
- * CAVEAT: This program is used as an educational medium.
- * No guarantee that this program will successfully work on all
- * platforms, nor that trapping of inconsistent parameters is
- * complete and foolproof. Use At Your Own Risk.
- *
- ****
- *
- */
- #include <assert.h>
- #include <conio.h>
- #include <ctype.h>
- #include <malloc.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #define NAME_SIZE 250
- #define PLAYER1 1
- #define PLAYER2 -1
- #define COMPUTER PLAYER2
- #define EMPTY 0
- /*
- * From here on out is the code split into various
- * .c and .h files merged together.
- */
- // ------------------------------------------------
- /* <players.h>
- * This file contained the code responsible for all the
- * player-related functions declarations.
- */
- typedef struct
- {
- char *name;
- int loss;
- int win;
- int draw;
- } Player;
- Player *g_players = NULL;
- int g_sign1, g_sign2;
- int g_player1 = PLAYER1, g_player2 = PLAYER2;
- int g_playerCount = 0;
- int g_evalcount = 0;
- Player *addPlayer(Player *players, char *name, int *playerCount);
- int findPlayer(Player *players, int playerCount, char *name);
- void freePlayers(Player *players);
- void printPlayerStats(Player *players, int playerCount);
- Player *loadStats(int *playerCount);
- void saveStats(Player *players, int playerCount);
- void addWin(Player *players, int indexPlayer);
- void addLoss(Player *players, int indexPlayer);
- void addDraw(Player *players, int indexPlayer);
- int countNameLetters(char *name);
- int maxNameSize(Player *players);
- char *mygets(char *buffer, int size);
- int isEmpty(const char *s);
- /* <tictactoe.h>
- * This file contained the code responsible for all the
- * game-logic functions declarations.
- */
- void initStats();
- void initBoard(int board[9]);
- void printBoard(int board[9]);
- void setBoardPosition(int board[9], int position, int value);
- int getBoardPosition(int board[9], int position);
- int getPlayerPosition(int board[9], int player, char *namePlayer1,
- char *namePlayer2);
- void markPlayerPosition(int board[9], int player, int position);
- int hasWon(int board[9], int player);
- void nextTurn(int *turn, int *player, int *opponent);
- void setSign(char *namePlayer1);
- int playFirst(char *namePlayer);
- int movesLeft(int board[9]);
- int scoreBoard(int board[9], int depth);
- int max(int a, int b);
- int min(int a, int b);
- int minimax(int board[9], int depth, int player);
- int getBestMove (int board[9]);
- void clearScreen();
- void playAgain(int *shouldRun);
- void printStartingScreen();
- void printTicTac();
- void printMenu();
- void clearStartingScreen();
- void resizeWindow();
- int getMenuSelection();
- void againstComputer();
- void twoPlayers();
- void statistics();
- void exitGame();
- void pressAnyKey();
- int main()
- {
- int done = 0;
- resizeWindow();
- printStartingScreen();
- pressAnyKey();
- clearScreen();
- printTicTac();
- pressAnyKey();
- clearScreen();
- g_players = loadStats(&g_playerCount);
- while (!done)
- {
- clearScreen();
- printMenu();
- switch (getMenuSelection())
- {
- case 1:
- clearScreen();
- againstComputer();
- break;
- case 2:
- clearScreen();
- twoPlayers();
- break;
- case 3:
- clearScreen();
- statistics();
- break;
- case 4:
- exitGame();
- done = 1;
- break;
- }
- }
- if (g_players != NULL)
- {
- freePlayers(g_players);
- g_players = NULL;
- }
- return 0;
- }
- /* <players.c>
- * This file contained the code responsible
- * for all the player-related functions.
- */
- //
- // Adds player to the array of players.
- // Input
- // players - existing array of players
- // name - name of player to add
- // playerCount - num of existing players in array
- // Output
- // playerCount - updated number of players
- // Return
- // returns new array of players
- //
- Player *addPlayer(Player *players, char *name, int *playerCount)
- {
- Player *newPlayers;
- if (players == NULL)
- {
- newPlayers = (Player *)malloc(sizeof(Player));
- }
- else
- {
- newPlayers =
- (Player *)realloc(players, (*playerCount + 1) * sizeof(Player));
- }
- if (newPlayers == NULL)
- {
- fprintf(stderr, "Memory realloc error\n");
- return NULL;
- }
- memset(&newPlayers[*playerCount], 0, sizeof(Player));
- newPlayers[*playerCount].name = (char *)malloc(strlen(name) + 1);
- strcpy(newPlayers[*playerCount].name, name);
- *playerCount = *playerCount + 1;
- return newPlayers;
- }
- //
- // Checks if a player already exists.
- // Input
- // players - existing array of players
- // name - name of player to add
- // playerCount - num of existing players in array
- // Return
- // returns the index of the player if the player exists
- // -1 if it doesn't
- //
- int findPlayer(Player *players, int playerCount, char *name)
- {
- int i;
- for (i = 0; i < playerCount; i++)
- {
- if (strcmp(name, players[i].name) == 0)
- {
- return i;
- }
- }
- return -1;
- }
- //
- // Prints player statistics.
- // Input
- // players - existing array of players
- // name - name of player to add
- // playerCount - num of existing players in array
- // Output
- // board of player stats
- //
- void printPlayerStats(Player *players, int playerCount)
- {
- int i, j, space;
- int max = maxNameSize(players);
- printf("\n");
- printf(" PLAYER STATISTICS\n");
- printf("\n");
- for (i = 0; i < max / 2; i++)
- {
- printf(" ");
- }
- printf("NAME");
- for (i = 0; i < max / 2; i++)
- {
- printf(" ");
- }
- printf("WINS LOSSES DRAWS \n\n");
- for (i = 0; i < playerCount; i++)
- {
- if (players[i].name[0] != '\0')
- {
- printf(" %s", players[i].name);
- space = max - strlen(players[i].name);
- for (j = 0; j < space; j++)
- {
- printf(" ");
- }
- printf("%4d%7d%7d", players[i].win, players[i].loss, players[i].draw);
- }
- printf("\n\n");
- }
- printf("\n");
- }
- //
- // Frees the dynamically allocated part of the memory
- // responsible for storing/handling players information
- // Input
- // players - existing array of players
- //
- void freePlayers(Player *players)
- {
- int i;
- if (players != NULL)
- {
- for (i = 0; i < g_playerCount; i++)
- {
- free(players[i].name);
- }
- free(players);
- }
- }
- // Adds a win in player's stats.
- void addWin(Player *players, int indexPlayer) { players[indexPlayer].win++; }
- // Adds a loss in player's stats.
- void addLoss(Player *players, int indexPlayer) { players[indexPlayer].loss++; }
- // Adds a draw in player's stats.
- void addDraw(Player *players, int indexPlayer) { players[indexPlayer].draw++; }
- //
- // Reads stats from txt file and saves it in array.
- // Input
- // playerCount - num of existing players in array
- // Return
- // array of players
- //
- Player *loadStats(int *playerCount)
- {
- int i;
- int win, loss, draw;
- int count;
- char name[NAME_SIZE];
- Player *players = NULL;
- FILE *fpstats;
- fpstats = fopen("stats.txt", "r");
- // If the file does not exist it will be created later on.
- if (fpstats != NULL)
- {
- fscanf(fpstats, "%d", &count);
- players = (Player *)malloc(count * sizeof(Player));
- if (players != NULL)
- {
- for (i = 0; i < count; i++)
- {
- if (feof(fpstats))
- {
- break;
- }
- fscanf(fpstats, "%s %d %d %d", name, &win, &loss, &draw);
- players[i].name = (char *)malloc(strlen(name) + 1);
- strcpy(players[i].name, name);
- players[i].win = win;
- players[i].loss = loss;
- players[i].draw = draw;
- }
- *playerCount = i;
- }
- fclose(fpstats);
- }
- return players;
- }
- //
- // Save stats in txt file.
- // Input
- // players - existing array of players
- // playerCount - num of existing players in array
- //
- void saveStats(Player *players, int playerCount)
- {
- int i;
- FILE *fpstats;
- fpstats = fopen("stats.txt", "w");
- // If the file does not exist it will be created later on.
- if (fpstats != NULL)
- {
- fprintf(fpstats, "%d\n", playerCount);
- if (players != NULL)
- {
- for (i = 0; i < playerCount; i++)
- {
- fprintf(fpstats, "%s\n%d %d %d\n", players[i].name, players[i].win,
- players[i].loss, players[i].draw);
- }
- }
- fclose(fpstats);
- }
- }
- //
- // Finds max name size in existing array of players.
- // Input
- // players - existing array of players
- // Return
- // max name size
- //
- int maxNameSize(Player *players)
- {
- int i, max = 0;
- for (i = 0; i < g_playerCount; i++)
- {
- if (strlen(players[i].name) > max)
- {
- max = strlen(players[i].name);
- }
- }
- return max;
- }
- //
- // Reads a line from the user with max charactes the int size.
- // Input
- // buffer - where to store the string
- // size - max size of buffer
- // output
- // stores the string into the buffer
- // return
- // if string is larger than the buffer the string is truncated
- //
- char *mygets(char *buffer, int size)
- {
- fgets(buffer, size, stdin);
- int i;
- for (i = 0; i < size; i++)
- {
- if (buffer[i] == '\n')
- {
- buffer[i] = '\0';
- break;
- }
- }
- buffer[size - 1] = '\0';
- return 0;
- }
- //
- // Checks whether a given string is empty.
- // ("" or <contains_only_whitespace)
- // Input
- // string *s
- // Return
- // 1 if string is empty; 0 otherwise
- //
- int isEmpty(const char *s)
- {
- while (*s != '\0')
- {
- if (!isspace((unsigned char)*s))
- {
- return 0;
- }
- s++;
- }
- return 1;
- }
- /* <tictactoe.c>
- * This file contained the code responsible
- * for all the game logic functions.
- */
- void initBoard(int board[9])
- {
- int i;
- for (i = 0; i < 9; i++)
- {
- board[i] = 0;
- }
- }
- void setBoardPosition(int board[9], int position, int value)
- {
- assert(position >= 1 && position <= 9);
- board[position - 1] = value;
- }
- int getBoardPosition(int board[9], int position)
- {
- assert(position >= 1 && position <= 9);
- return board[position - 1];
- }
- void printBoard(int board[9])
- {
- char space[50];
- memset(space, 32, sizeof(space));
- space[49] = 0;
- printf("%s", space);
- printf("------------------------------------\n");
- printf("%s", space);
- printf("| | | |\n");
- printf("%s", space);
- printf("| | | |\n");
- printf("%s", space);
- printf("| %c | %c | %c |\n", (char)(board[0]),
- (char)(board[1]), (char)(board[2]));
- printf("%s", space);
- printf("| | | |\n");
- printf("%s", space);
- printf("| | | |\n");
- printf("%s", space);
- printf("------------------------------------\n");
- printf("%s", space);
- printf("| | | |\n");
- printf("%s", space);
- printf("| | | |\n");
- printf("%s", space);
- printf("| %c | %c | %c |\n", (char)(board[3]),
- (char)(board[4]), (char)(board[5]));
- printf("%s", space);
- printf("| | | |\n");
- printf("%s", space);
- printf("| | | |\n");
- printf("%s", space);
- printf("------------------------------------\n");
- printf("%s", space);
- printf("| | | |\n");
- printf("%s", space);
- printf("| | | |\n");
- printf("%s", space);
- printf("| %c | %c | %c |\n", (char)(board[6]),
- (char)(board[7]), (char)(board[8]));
- printf("%s", space);
- printf("| | | |\n");
- printf("%s", space);
- printf("| | | |\n");
- printf("%s", space);
- printf("------------------------------------\n");
- printf("\n");
- }
- int hasWon(int board[9], int player)
- {
- int sign;
- if (player == PLAYER1)
- {
- sign = g_sign1;
- }
- else
- {
- sign = g_sign2;
- }
- return ((board[0] == sign && board[1] == sign && board[2] == sign) ||
- (board[3] == sign && board[4] == sign && board[5] == sign) ||
- (board[6] == sign && board[7] == sign && board[8] == sign) ||
- (board[0] == sign && board[3] == sign && board[6] == sign) ||
- (board[1] == sign && board[4] == sign && board[7] == sign) ||
- (board[2] == sign && board[5] == sign && board[8] == sign) ||
- (board[0] == sign && board[4] == sign && board[8] == sign) ||
- (board[2] == sign && board[4] == sign && board[6] == sign))
- ? 1
- : 0;
- }
- void setSign(char *namePlayer1)
- {
- char selection;
- printf("select your desired sign %s\n", namePlayer1);
- printf("press either X or O\n");
- do
- {
- selection = toupper(getch());
- switch (selection)
- {
- case 'X':
- g_sign1 = 'X', g_sign2 = 'O';
- break;
- case 'O':
- g_sign1 = 'O', g_sign2 = 'X';
- break;
- default:
- printf("choose between X and O!\n");
- break;
- }
- } while (selection != 'X' && selection != 'O');
- }
- void nextTurn(int *turn, int *player, int *opponent)
- {
- (*turn)++;
- if (*player == PLAYER1)
- {
- *player = PLAYER2;
- *opponent = PLAYER1;
- }
- else
- {
- *player = PLAYER1;
- *opponent = PLAYER2;
- }
- }
- //
- // Gets the position of the user to play.
- // Input
- // player - the player to mark position
- //
- // Return
- // the position to play, value 1-9
- //
- int getPlayerPosition(int board[9], int player, char *namePlayer1,
- char *namePlayer2)
- {
- int position;
- int inputInvalid = 1;
- char selection;
- if (player == 1)
- {
- printf("your turn, player %s. (select 1 - 9): \n", namePlayer1);
- }
- else
- {
- printf("your turn, player %s. (select 1 - 9): \n", namePlayer2);
- }
- do
- {
- position = getch();
- // Esc
- if (position == 27)
- {
- printf("Would you like to exit? Y/N\n");
- do{
- selection = toupper(getch());
- } while(selection != 'Y' && selection != 'N');
- if (selection == 'Y')
- return -1;
- }
- position = getch() - '0';
- if (position < 1 || position > 9)
- {
- printf(
- "invalid selection, please try again.\
- Only values 1-9 accepted.\n");
- continue;
- }
- if (getBoardPosition(board, position) != 0)
- {
- printf("invalid selection, please try again\n");
- }
- else
- {
- inputInvalid = 0;
- }
- } while (inputInvalid);
- return position;
- }
- // Marks the position of the player on the board.
- // Input
- // board -
- // player - the player to mark position
- // position - the position to mark, values 1-9
- //
- // Return
- //
- void markPlayerPosition(int board[9], int player, int position)
- {
- int sign;
- if (player == PLAYER1)
- {
- sign = g_sign1;
- }
- else
- {
- sign = g_sign2;
- }
- setBoardPosition(board, position, sign);
- }
- void playAgain(int *shouldRun)
- {
- printf("Would you like to play again?\t Y/N\n");
- int inputInvalid = 1;
- do
- {
- char selection;
- selection = toupper(getch());
- if (selection == 'N')
- {
- inputInvalid = 0;
- *shouldRun = 0;
- }
- if (selection == 'Y')
- {
- inputInvalid = 0;
- }
- else
- {
- printf("Invalid selection.\n");
- printf("Would you like to play again?\t Y/N\n");
- }
- } while (inputInvalid);
- }
- void clearScreen() { system("cls"); }
- void pressAnyKey()
- {
- printf("Press any key to continue\n");
- getch();
- }
- void printStartingScreen(void)
- {
- printf(
- ".----------------. .----------------. .----------------. "
- ".----------------. .----------------. .----------------. "
- ".----------------. \n");
- printf(
- "| .--------------. || .--------------. || .--------------. || "
- ".--------------. || .--------------. || .--------------. || "
- ".--------------. |\n");
- printf(
- "| | ______ | || | _____ | || | ______ | || | __ "
- " | || | _______ | || | _____ | || | __ | |\n");
- printf(
- "| | |_ __ \\ | || | |_ _| | || | .' ___ | | || | / "
- "\\ | || | |_ __ \\ | || | |_ _| | || | / \\ | "
- "|\n");
- printf(
- "| | | |__) | | || | | | | || | / .' \\_| | || | / "
- "/\\ \\ | || | | |__) | | || | | | | || | / /\\ \\ "
- "| |\n");
- printf(
- "| | | ___/ | || | | | | || | | | | || | / "
- "____ \\ | || | | __ / | || | | | | || | / ____ \\ "
- "| |\n");
- printf(
- "| | _| |_ | || | _| |_ | || | \\ `.___.'\\ | || | _/ / "
- " \\ \\_ | || | _| | \\ \\_ | || | _| |_ | || | _/ / \\ "
- "\\_ | |\n");
- printf(
- "| | |_____| | || | |_____| | || | `._____.' | || ||____| "
- "|____|| || | |____| |___| | || | |_____| | || ||____| |____|| "
- "|\n");
- printf(
- "| | | || | | || | | || | "
- " | || | | || | | || | | |\n");
- printf(
- "| '--------------' || '--------------' || '--------------' || "
- "'--------------' || '--------------' || '--------------' || "
- "'--------------' |\n");
- printf(
- " '----------------' '----------------' '----------------' "
- "'----------------' '----------------' '----------------' "
- "'----------------' \n");
- printf(
- " "
- " \n");
- printf(
- " "
- " \n");
- printf(
- " "
- " \n");
- printf(
- " "
- " \n");
- printf(
- " "
- " \n");
- printf(
- " _ _ _ "
- " _ \n");
- printf(
- " | | (_) | | "
- " | | \n");
- printf(
- " | |_ _ ___| |_ __ _ "
- "___| |_ ___ ___ \n");
- printf(
- " | __| |/ __| __/ _` "
- "|/ __| __/ _ \\ / _ \\ "
- "\n");
- printf(
- " | |_| | (__| || (_| | "
- "(__| || (_) | __/ \n");
- printf(
- " "
- "\\__|_|\\___|\\__\\__,_|\\___|\\__\\___/ \\___| "
- " \n");
- printf(
- " "
- " \n");
- printf(
- " "
- " \n");
- printf(
- " "
- " \n");
- printf(
- " "
- " \n");
- printf(
- " "
- " \n");
- printf(
- " "
- " \n");
- printf(
- " "
- " \n");
- printf(
- " "
- " \n");
- printf(
- " "
- " \n");
- }
- void printTicTac()
- {
- printf(
- " "
- " \n");
- printf(
- " "
- " \n");
- printf(
- " || "
- " || \n");
- printf(
- " || "
- " || \n");
- printf(
- " o o || \\\\ "
- " // || o o \n");
- printf(
- " o o || \\\\ "
- "// || o o \n");
- printf(
- " o o || "
- "\\\\// || o o "
- "\n");
- printf(
- " o o || "
- "//\\\\ || o o "
- "\n");
- printf(
- " o o || // "
- "\\\\ || o o "
- "\n");
- printf(
- " o o || // "
- "\\\\ || o o \n");
- printf(
- " || "
- " || \n");
- printf(
- " "
- "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| "
- " \n");
- printf(
- " || "
- " || \n");
- printf(
- " o o || \\\\ "
- " // || \n");
- printf(
- " o o || \\\\ "
- "// || \n");
- printf(
- " o o || "
- "\\\\// || "
- "\n");
- printf(
- " o o || "
- "//\\\\ || "
- "\n");
- printf(
- " o o || // "
- "\\\\ || "
- "\n");
- printf(
- " o o || // "
- "\\\\ || \n");
- printf(
- " || "
- " || \n");
- printf(
- " "
- "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| "
- " \n");
- printf(
- " || "
- " || \n");
- printf(
- " o o || "
- " || \\\\ // \n");
- printf(
- " o o || "
- " || \\\\ // \n");
- printf(
- " o o || "
- " || \\\\// \n");
- printf(
- " o o || "
- " || //\\\\ \n");
- printf(
- " o o || "
- " || // \\\\ \n");
- printf(
- " o o || "
- " || // \\\\ \n");
- printf(
- " || "
- " || \n");
- printf(
- " || "
- " || \n");
- }
- void printMenu()
- {
- printf(" \n");
- printf(" \n");
- printf(" MAIN MENU \n");
- printf(" \n");
- printf(" Press 1 - 4 to choose \n");
- printf(" \n");
- printf(" \n");
- printf(" 1. PLAY AGAINST THE COMPUTER \n");
- printf(" \n");
- printf(" 2. PLAY AGAINST AN OPPONENT \n");
- printf(" \n");
- printf(" 3. VIEW PLAYER STATISTICS \n");
- printf(" \n");
- printf(" 4. EXIT GAME \n");
- printf(" \n");
- }
- int getMenuSelection()
- {
- int inputInvalid = 1;
- int menuSelection;
- do
- {
- menuSelection = getch() - '0';
- if (menuSelection < 1 || menuSelection > 4)
- {
- continue;
- }
- else
- {
- inputInvalid = 0;
- return menuSelection;
- }
- } while (inputInvalid);
- return menuSelection;
- }
- void twoPlayers()
- {
- int board[9];
- int shouldRun = 1;
- int position;
- while (shouldRun)
- {
- int turn = 1;
- int player = g_player1;
- int opponent = g_player2;
- int nameEmpty;
- int playerFound;
- int inputInvalid = 1;
- char namePlayer1[NAME_SIZE], namePlayer2[NAME_SIZE];
- // Get name for Player1.
- do
- {
- printf("Enter your name Player1: ");
- mygets(namePlayer1, NAME_SIZE);
- nameEmpty = isEmpty(namePlayer1);
- if (nameEmpty == 1)
- {
- printf("Your name must contain at least one character\n");
- }
- else
- {
- inputInvalid = 0;
- }
- } while (inputInvalid);
- inputInvalid = 1;
- playerFound = findPlayer(g_players, g_playerCount, namePlayer1);
- if (playerFound == -1)
- {
- g_players = addPlayer(g_players, namePlayer1, &g_playerCount);
- if (g_players == NULL)
- {
- break;
- }
- }
- // Get name for Player2.
- do
- {
- printf("Enter your name Player2: ");
- mygets(namePlayer2, NAME_SIZE);
- nameEmpty = isEmpty(namePlayer2);
- if (nameEmpty == 1)
- {
- printf("Your name must contain at least one character\n");
- }
- else
- {
- if (strcmp(namePlayer1, namePlayer2) == 0)
- {
- printf("You need to select a different name"
- " other than %s\n",
- namePlayer1);
- }
- else
- {
- inputInvalid = 0;
- }
- }
- } while (inputInvalid);
- inputInvalid = 1;
- clearScreen();
- playerFound = findPlayer(g_players, g_playerCount, namePlayer2);
- if (playerFound == -1)
- {
- g_players = addPlayer(g_players, namePlayer2, &g_playerCount);
- if (g_players == NULL)
- {
- break;
- }
- }
- int indexPlayer1 = findPlayer(g_players, g_playerCount, namePlayer1);
- int indexPlayer2 = findPlayer(g_players, g_playerCount, namePlayer2);
- // Start game.
- setSign(namePlayer1);
- clearScreen();
- initBoard(board);
- printBoard(board);
- int gameEnded = 0;
- while (!gameEnded)
- {
- position = getPlayerPosition(board, player, namePlayer1, namePlayer2);
- markPlayerPosition(board, player, position);
- clearScreen();
- printBoard(board);
- if (hasWon(board, player) == 1)
- {
- if (player == 1)
- {
- printf("Congratulations %s you have won!\n", namePlayer1);
- addWin(g_players, indexPlayer1);
- addLoss(g_players, indexPlayer2);
- }
- else
- {
- printf("Congratulations %s you have won!\n", namePlayer2);
- addWin(g_players, indexPlayer2);
- addLoss(g_players, indexPlayer1);
- }
- gameEnded = 1;
- }
- nextTurn(&turn, &player, &opponent);
- if (turn > 9 && (!hasWon(board, PLAYER1) && !hasWon(board, PLAYER2)))
- {
- printf("It's a draw!\n");
- addDraw(g_players, indexPlayer1);
- addDraw(g_players, indexPlayer2);
- gameEnded = 1;
- }
- }
- if (position == -1)
- break;
- playAgain(&shouldRun);
- }
- }
- //
- // Chekcs if there are any positions left to play.
- //
- int movesLeft(int board[9])
- {
- int i;
- for(i = 0; i < 9; i++)
- {
- if (board[i] == EMPTY)
- return 1;
- }
- return 0;
- }
- //
- // Evaluates the board and returns appropriate score
- // taking in cosideration the depth.
- // If no one has won returns 0.
- //
- int scoreBoard(int board[9], int depth)
- {
- if (hasWon(board, PLAYER1))
- return 10 - depth;
- if (hasWon(board, COMPUTER))
- return depth - 10;
- return 0;
- }
- int max(int a, int b)
- {
- if (a > b)
- return a;
- return b;
- }
- int min(int a, int b)
- {
- if (a < b)
- return a;
- return b;
- }
- //
- // Implementation of minimax algorithm.
- //
- // Computes all possible games that can be played
- // and returns the value of the board.
- //
- // maximizer = player/PLAYER1
- // minimizer = computer/PLAYER2
- //
- int minimax(int board[9], int depth, int player)
- {
- int maximizerScore, minimizerScore;
- int i;
- g_evalcount++;
- // If the game is in the terminal node
- // return the score based on the depth
- if(!movesLeft(board) || hasWon(board, PLAYER1) || hasWon(board, COMPUTER ))
- return scoreBoard(board, depth);
- // maximizer's turn (player)
- if(player == PLAYER1)
- {
- maximizerScore = -10000;
- for(i = 0; i < 9; i++)
- {
- if (board[i] == EMPTY)
- {
- // Makes the move
- board[i] = g_sign1;
- // Recursion with minimax to find max score
- maximizerScore = max ( maximizerScore,
- minimax(board, depth - 1, (-1)*player));
- // Undo the move
- board[i] = EMPTY;
- }
- }
- return maximizerScore ;
- }
- // Minimizer's turn (computer)
- else
- {
- minimizerScore = 10000;
- for(i = 0; i < 9; i++)
- {
- if (board[i] == EMPTY)
- {
- // Makes the move
- board[i] = g_sign2;
- // Recursion with minimax to find min score
- minimizerScore = min ( minimizerScore,
- minimax(board, depth - 1, (-1)*player));
- // Undo the move
- board[i] = EMPTY;
- }
- }
- return minimizerScore;
- }
- }
- // Returns the position of the best move
- int getBestMove (int board[9])
- {
- int bestScore = 10000;
- int bestMove = -1;
- int moveScore;
- int i;
- g_evalcount = 0;
- // Goes through all empty cells.
- // Calls minimax on each empty cell.
- for(i = 0; i < 9; i++)
- {
- g_evalcount = 0;
- if(board[i] == EMPTY)
- {
- board[i] = g_sign2;
- moveScore = minimax(board, 9, PLAYER1);
- board[i] = EMPTY;
- if (moveScore < bestScore)
- {
- bestMove = i + 1;
- bestScore = moveScore;
- }
- }
- }
- return bestMove;
- }
- //
- // Asks the player if they want to
- // play first against the computer.
- // Return
- // 1 if they chose to play first
- // 0 otherwise
- //
- int playFirst(char *namePlayer) {
- char selection;
- int first = -1;
- clearScreen();
- printf("%s do you want to play first? Y/N \n", namePlayer);
- do {
- selection = toupper(getch());
- if(selection == 'Y')
- first = 1;
- if(selection == 'N')
- first = 0;
- } while (first == -1);
- return first;
- }
- void againstComputer() {
- int board[9];
- int shouldRun = 1;
- int position;
- while (shouldRun) {
- int countMoves = 0;
- int player = g_player1;
- int playerFound;
- int inputInvalid = 1;
- int first;
- char namePlayer[NAME_SIZE];
- // Get name for player.
- do {
- printf("Enter your name: ");
- mygets(namePlayer, NAME_SIZE);
- if (namePlayer[0] != '\0') {
- inputInvalid = 0;
- } else {
- printf("You need to enter a name\n");
- }
- } while (inputInvalid);
- inputInvalid = 1;
- playerFound = findPlayer(g_players, g_playerCount, namePlayer);
- if (playerFound == -1) {
- g_players = addPlayer(g_players, namePlayer, &g_playerCount);
- if (g_players == NULL) {
- break;
- }
- }
- clearScreen();
- int indexPlayer = findPlayer(g_players, g_playerCount, namePlayer);
- // Start game
- setSign(namePlayer);
- first = playFirst(namePlayer);
- player = g_player1;
- clearScreen();
- initBoard(board);
- printBoard(board);
- int gameEnded = 0;
- while (!gameEnded) {
- if(first % 2 == 1)
- {
- position = getPlayerPosition(board, PLAYER1, namePlayer, namePlayer);
- if(position == -1)
- break;
- markPlayerPosition(board, player, position);
- }
- if(first % 2 == 0)
- {
- position = getBestMove(board);
- markPlayerPosition(board, PLAYER2, position);
- }
- first++;
- countMoves++;
- clearScreen();
- printBoard(board);
- if (hasWon(board, PLAYER1) == 1)
- {
- printf("Congratulations %s you have won!\n", namePlayer);
- addWin(g_players, indexPlayer);
- gameEnded = 1;
- }
- else if (hasWon(board, PLAYER2) == 1)
- {
- printf("%s you have lost!\n", namePlayer);
- addLoss(g_players, indexPlayer);
- gameEnded = 1;
- }
- else if (countMoves == 9)
- {
- printf("It's a draw!\n");
- addDraw(g_players, indexPlayer);
- gameEnded = 1;
- }
- }
- if (position == -1)
- break;
- playAgain(&shouldRun);
- }
- }
- void statistics()
- {
- printPlayerStats(g_players, g_playerCount);
- pressAnyKey();
- }
- void exitGame() { saveStats(g_players, g_playerCount); }
- void resizeWindow() { system("mode con:cols=140 lines=35"); }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement