diff --git a/games/tic_tac_toe.c b/games/tic_tac_toe.c index fbaf0e22be..fae70751a8 100644 --- a/games/tic_tac_toe.c +++ b/games/tic_tac_toe.c @@ -1,449 +1,218 @@ /** * @file tic-tac-toe.c - * @author [vivekboss99](github.com/vivekboss99) - * @author [Krishna Vedala](https://github.com/kvedala) + * @author + * - [vivekboss99](https://github.com/vivekboss99) + * - [Krishna Vedala](https://github.com/kvedala) + * - [Prem-2006](https://github.com/prem-2006) * @brief [Tic-Tac-Toe game](https://en.wikipedia.org/wiki/Tic-tac-toe) - * implementation in C - * @details Tic-Tac-Toe Game, where the user can decide to play with the - * computer(single player mode) or with other user(double player mode), the - * code as an array named 'game_table' which is the table and user needs to enter the - * position inside the array(from 1-9) where he/she wants to place 'X' or 'O' on the - * table. + * @details + * Simple console Tic-Tac-Toe game supporting single-player (vs computer) + * and double-player (vs human) modes. */ + #include #include -#include #include +#include -// Functions Declarations -static void singlemode(); -static void doublemode(); -static void placex(int); // used for placing position of X by the 1st player -static void place(); // used by the computer to place O -static void placey(int); // used in Double Player mode by the 2nd player to - // place the position of O -int checkwin(); // checks everytime when a player or computer places 'X' or 'O' - -/** Tic-Tac-Toe table, so basically we are using variable 'game_table' as the table(size:3X3) and - * updating it regularly - */ -static char game_table[9]; - -/** - * Main program function. - * @returns 0 on clean exit. - * @note No checks are included for program execution failures! - */ -int main() -{ - srand( (unsigned int)time(NULL)); - int l = 0; - do - { - int n = 0; - - // filling the table with multiple asterisks - for (int i = 0; i < 9; i++) game_table[i] = '*'; - - // displaying the main menu - printf("***************************************\n"); - printf("*************TIC TAC TOE***************\n"); - printf("***************************************\n"); - printf("***********1. YOU vs COMPUTER ***********\n"); - printf("***********2. YOU vs PLAYER ***********\n"); - printf("***********3.EXIT *********************\n"); - printf("Enter your choice : "); - scanf("%d", &n); - - switch (n) // switch case to select between single player mode or - // double player mode - { - case 1: - singlemode(); - break; - case 2: - doublemode(); - break; - default: - printf("THANK YOU and EXIT!"); - } - - printf("Next game ? : "); - printf("Enter 1 – YES and 0 - NO "); - scanf("%d", &l); - - } while (l == 1); +// ---- Function Declarations ---- +static void singlemode(void); +static void doublemode(void); +static void placex(int pos); +static void place_computer(void); +static void placey(int pos); +static int checkwin(void); +static int get_valid_input(void); - return 0; -} - -/** - * @brief Implementation of game vs computer - * - * @returns None - */ -void singlemode() -{ - int m; - int k = 0; - int table_fill_count=0; - - for (int i = 0; i < 3; i++) - { - for (int j = 0; j < 3; j++) - { - printf("%c ", game_table[k]); - k++; - } +// ---- Global Board ---- +static char game_table[9]; - printf("\n"); +// ---- Helper Functions ---- +static void print_board(void) { + printf("\n"); + for (int i = 0; i < 9; i++) { + printf("%c ", game_table[i]); + if ((i + 1) % 3 == 0) + printf("\n"); } + printf("\n"); +} - for (int x = 1; x < 10; x++) - { - k = 0; +// ---- Input Validation ---- +static int get_valid_input(void) { + char input[50]; + int pos = 0; - printf("Where would you like to place 'x' "); - scanf("%d", &m); + while (1) { + printf("Enter position (1-9): "); + if (!fgets(input, sizeof(input), stdin)) + continue; - placex(m); - if(table_fill_count<4) - { - place(); + if (sscanf(input, "%d", &pos) != 1 || pos < 1 || pos > 9) { + fprintf(stderr, "Invalid input! Try again.\n"); + continue; } - for (int i = 0; i < 3; i++) - { - for (int j = 0; j < 3; j++) - { - printf("%c ", game_table[k]); - k++; - - } - - printf("\n"); - } - table_fill_count++; - int o = checkwin(); - - if (o == -1 || o == -2) - { - if (o == -1) - { - printf("YOU WIN\n"); - } - if (o == -2) - { - printf("YOU LOSE\n"); - } - - break; + if (game_table[pos - 1] == 'x' || game_table[pos - 1] == 'o') { + fprintf(stderr, "Position already taken! Try again.\n"); + continue; } - if (table_fill_count==4) - { - printf("\nDRAW "); - break; - } + return pos; } } -/** - * @brief Implementation of game vs another player. - * - * @returns None - */ -void doublemode() -{ - int m; - int e1; - int k = 0; - int doublemode_table_count=0; - - for (int i = 0; i < 3; i++) - { - for (int j = 0; j < 3; j++) - { - printf("%c ", game_table[k]); - k++; - } - - printf("\n"); - } - for (int x = 1; x < 10; x++) - { - k = 0; +// ---- Player Move ---- +static void placex(int pos) { + game_table[pos - 1] = 'x'; +} - printf("PLAYER1 - where would you like to place 'x' : "); - scanf("%d", &m); +// ---- Player 2 Move ---- +static void placey(int pos) { + game_table[pos - 1] = 'o'; +} - placex(m); - if(doublemode_table_count<4) - { - printf("PLAYER2 - where would you like to place 'o' : "); - scanf("%d", &e1); +// ---- Computer Move ---- +static void place_computer(void) { + int e; + do { + e = rand() % 9; + } while (game_table[e] == 'x' || game_table[e] == 'o'); - placey(e1); - } + game_table[e] = 'o'; + printf("Computer placed at %d\n", e + 1); +} - for (int i = 0; i < 3; i++) - { - for (int j = 0; j < 3; j++) - { - printf("%c ", game_table[k]); - k++; - } +// ---- Check Win ---- +static int checkwin(void) { + int wins[8][3] = { + {0, 1, 2}, {3, 4, 5}, {6, 7, 8}, // rows + {0, 3, 6}, {1, 4, 7}, {2, 5, 8}, // columns + {0, 4, 8}, {2, 4, 6} // diagonals + }; - printf("\n"); - } - doublemode_table_count++; - int o = checkwin(); - - if (o == -1 || o == -2) - { - if (o == -1) - { - printf("Player 1 WIN\n"); - } - if (o == -2) - { - printf("Player 2 WIN\n"); - } - - break; - } - if (doublemode_table_count==4) - { - printf("\nDRAW "); - break; + for (int i = 0; i < 8; i++) { + int a = wins[i][0], b = wins[i][1], c = wins[i][2]; + if (game_table[a] == game_table[b] && game_table[b] == game_table[c]) { + if (game_table[a] == 'x') + return -1; // X wins + if (game_table[a] == 'o') + return -2; // O wins } } + return 0; // No win } -int check_placex(){ - char input[50]; - int n1; - while (1){ - fgets(input,49,stdin); - if ( strlen(input) > 2 || strlen(input) == 0){ - fprintf(stderr,"Invalid move, Enter number 1 - 9: "); - continue; - } - if(sscanf(input,"%d",&n1) != 1){ - fprintf(stderr,"Invalid move, Enter number 1 - 9: "); - continue; - } - if ((game_table[n1-1] == 'x') || (game_table[n1-1]) == 'o' || (n1== 0)){ - fprintf(stderr,"Already allocated, Enter number: "); - continue; - } - return n1; - } -} +// ---- Single Player ---- +static void singlemode(void) { + printf("\n--- You vs Computer ---\n"); + int moves = 0; + print_board(); + while (moves < 9) { + printf("Your move (X)\n"); + int pos = get_valid_input(); + placex(pos); + moves++; + print_board(); + if (checkwin() == -1) { + printf("🎉 You WIN!\n"); + return; + } + if (moves >= 9) break; + printf("Computer's move (O)\n"); + place_computer(); + moves++; + print_board(); -/** - * @brief Update table by placing an `X` - * - * @param m location to place `X` - * - * @returns None - */ -void placex(int m) -{ - int n1 = 0; - if (m >= 1 && m <= 9) - { - if (game_table[m - 1] != 'x' && game_table[m - 1] != 'o') - { - game_table[m - 1] = 'x'; + if (checkwin() == -2) { + printf("💻 Computer WINS!\n"); + return; } - else - { - int n = check_placex(); - placex(n); - } - } - else - { - int n = check_placex(); - placex(n); } -} -/** - * @brief Update table by placing an `O` - * - * @returns None - */ -void place() -{ - int e = rand() % 9; - - if (e >= 0) - { - if (game_table[e] != 'x' && game_table[e] != 'o') - { - game_table[e] = 'o'; - printf("\n Computer placed at %d position\n", e + 1); - } - else - { - place(); - } - } -} -/** - * @brief Update table by placing an `O` - * - * @param e1 location to place `O` - * - * @returns None - */ -void placey(int e1) -{ - int n1 = 0; - if (e1 >= 1 && e1 <= 9) - { - if (game_table[e1 - 1] != 'x' && game_table[e1 - 1] != 'o') - { - game_table[e1 - 1] = 'o'; - } - else - { - int n = check_placex(); - placex(n); - } - } - else - { - int n = check_placex(); - placex(n); - } + printf("🤝 It's a DRAW!\n"); } -/** - * @brief Implementation of win conditon checker for 'X' or 'O' whenever the table is updated - * - * @returns -1: if 'X' won - * @returns -2: if 'O' won - * @returns 0: if there is no win condition for 'X' or 'O' - */ -int checkwin() -{ - if (game_table[0] == game_table[1] && game_table[1] == game_table[2]) - { - if (game_table[0] == 'x' && game_table[1] == 'x' && - game_table[2] == 'x') - { - return -1; - } - if (game_table[0] == 'o' && game_table[1] == 'o' && - game_table[2] == 'o') - { - return -2; - } - } - else if (game_table[0] == game_table[4] && game_table[4] == game_table[8]) - { - if (game_table[0] == 'x' && game_table[4] == 'x' && - game_table[8] == 'x') - { - return -1; - } +// ---- Double Player ---- +static void doublemode(void) { + printf("\n--- Player 1 (X) vs Player 2 (O) ---\n"); + int moves = 0; + print_board(); - if (game_table[0] == 'o' && game_table[4] == 'o' && - game_table[8] == 'o') - { - return -2; - } - } - else if (game_table[0] == game_table[3] && game_table[3] == game_table[6]) - { - if (game_table[0] == 'x' && game_table[3] == 'x' && - game_table[6] == 'x') - { - return -1; - } + while (moves < 9) { + printf("Player 1 (X):\n"); + int p1 = get_valid_input(); + placex(p1); + moves++; + print_board(); - if (game_table[0] == 'o' && game_table[3] == 'o' && - game_table[6] == 'o') - { - return -2; - } - } - else if (game_table[3] == game_table[4] && game_table[4] == game_table[5]) - { - if (game_table[3] == 'x' && game_table[4] == 'x' && - game_table[5] == 'x') - { - return -1; + if (checkwin() == -1) { + printf("🎉 Player 1 WINS!\n"); + return; } - if (game_table[3] == 'o' && game_table[4] == 'o' && - game_table[5] == 'o') - { - return -2; - } - } - else if (game_table[6] == game_table[7] && game_table[7] == game_table[8]) - { - if (game_table[6] == 'x' && game_table[7] == 'x' && - game_table[8] == 'x') - { - return -1; - } + if (moves >= 9) break; - if (game_table[6] == 'o' && game_table[7] == 'o' && - game_table[8] == 'o') - { - return -2; - } - } - else if (game_table[1] == game_table[4] && game_table[4] == game_table[7]) - { - if (game_table[1] == 'x' && game_table[4] == 'x' && - game_table[7] == 'x') - { - return -1; - } + printf("Player 2 (O):\n"); + int p2 = get_valid_input(); + placey(p2); + moves++; + print_board(); - if (game_table[1] == 'o' && game_table[4] == 'o' && - game_table[7] == 'o') - { - return -2; + if (checkwin() == -2) { + printf("🎉 Player 2 WINS!\n"); + return; } } - else if (game_table[2] == game_table[5] && game_table[5] == game_table[8]) - { - if (game_table[2] == 'x' && game_table[5] == 'x' && - game_table[8] == 'x') - { - return -1; - } - if (game_table[2] == 'o' && game_table[5] == 'o' && - game_table[8] == 'o') - { - return -2; - } - } - else if (game_table[2] == game_table[4] && game_table[4] == game_table[6]) - { - if (game_table[2] == 'x' && game_table[4] == 'x' && - game_table[6] == 'x') - { - return -1; - } + printf("🤝 It's a DRAW!\n"); +} - if (game_table[2] == 'o' && game_table[4] == 'o' && - game_table[6] == 'o') - { - return -2; - } - } +// ---- Main ---- +int main(void) { + srand((unsigned int)time(NULL)); + int play_again = 1; + + while (play_again) { + for (int i = 0; i < 9; i++) + game_table[i] = '*'; + + printf("\n============================\n"); + printf(" TIC TAC TOE \n"); + printf("============================\n"); + printf("1. You vs Computer\n"); + printf("2. You vs Player\n"); + printf("3. Exit\n"); + printf("Choose option: "); + + int choice = 0; + scanf("%d", &choice); + getchar(); // clear newline + + switch (choice) { + case 1: + singlemode(); + break; + case 2: + doublemode(); + break; + case 3: + printf("Thanks for playing!\n"); + return 0; + default: + printf("Invalid option!\n"); + break; + } + + printf("\nPlay again? (1 = Yes / 0 = No): "); + scanf("%d", &play_again); + getchar(); + } + + printf("Goodbye!\n"); return 0; }