From 7c9489b254ddbdf6245dda8c6861ecb0823113f7 Mon Sep 17 00:00:00 2001 From: Kinza <148489795+kinza7124@users.noreply.github.com> Date: Sun, 13 Jul 2025 23:01:11 +0500 Subject: [PATCH] Enhance Tic-Tac-Toe: Added Two-Player Mode and Improved Computer mode Logic Features Added: Two Player Mode: 1. Added an option for two human players to play against each other (difficulty = 3). 2. Implemented two_player_move() function to handle player turns dynamically. AI Enhancements: Improved computer move logic to handle: 1. Immediate win detection. 2. Immediate blocking of player's winning move. 3. Opposite corner strategy. 4. Fork prevention when player takes opposite corners. 5. Priority for center, corners, and sides based on optimal strategies (God mode). --- 8 Tic Tac Toe/tic-tac-toe.c | 595 +++++++++++++++++++++++------------- 1 file changed, 386 insertions(+), 209 deletions(-) diff --git a/8 Tic Tac Toe/tic-tac-toe.c b/8 Tic Tac Toe/tic-tac-toe.c index c2b62fe..753f472 100644 --- a/8 Tic Tac Toe/tic-tac-toe.c +++ b/8 Tic Tac Toe/tic-tac-toe.c @@ -1,248 +1,425 @@ -#include -#include -#include +#include +#include +#include -#define BOARD_SIZE 3 -#define X 'X' -#define O 'O' +int difficulty; typedef struct { - int player; - int computer; - int draw; + int player; + int computer; + int draw; } Score; -int difficulty; -Score score = {.player = 0, .computer = 0, .draw = 0}; +Score score = {0, 0, 0}; -void input_difficulty(); +void get_difficulty(); void clear_screen(); -void print_board(char board[BOARD_SIZE][BOARD_SIZE]); -int check_win(char board[BOARD_SIZE][BOARD_SIZE], char player); -int check_draw(char board[BOARD_SIZE][BOARD_SIZE]); -void play_game(); -void player_move(char board[BOARD_SIZE][BOARD_SIZE]); -void computer_move(char board[BOARD_SIZE][BOARD_SIZE]); -int is_valid_move(char board[BOARD_SIZE][BOARD_SIZE], int row, int col); - -int main() { - srand(time(NULL)); - int choice; - input_difficulty(); - do { - play_game(); - printf("\nPlay again? (1 for yes, 0 for no): "); - scanf("%d", &choice); - } while (choice == 1); - printf("\nBye Bye, thanks for playing."); +void print_board(char board[3][3]); +int checkwin(char board[3][3], char player); +int checkdraw(char board[3][3]); +void playgame(); +void playermove(char board[3][3]); +void computermove(char board[3][3]); +void two_player_move(char board[3][3], char player); +int validmove(char board[3][3], int row, int col); + + +int main(){ + srand(time(NULL)); + int choice; + get_difficulty(); + do { + + playgame(); + + printf("\nDo you want to play again ? (1 for yes, 2 for no): "); + scanf(" %d", &choice); + + } while(choice == 1); + + printf("\nDeveloped by HUSSAIN"); + printf("\nThanks for playing"); + + return 0; } -void play_game() { - char board[BOARD_SIZE][BOARD_SIZE] = { - {' ', ' ', ' '}, - {' ', ' ', ' '}, - {' ', ' ', ' '}, - }; - char current_player = rand() % 2 == 0 ? X : O; - - print_board(board); - while (1) { - if (current_player == X) { - player_move(board); - print_board(board); - if (check_win(board, X)) { - score.player++; - print_board(board); - printf("Congratulation You have won.!!!"); - break; - } - current_player = O; - } else { - computer_move(board); - print_board(board); - if (check_win(board, O)) { - score.computer++; - print_board(board); - printf("I won !!! But you played well..."); - break; - } - current_player = X; +void playgame(){ + char board[3][3] = { + {' ', ' ', ' '}, + {' ', ' ', ' '}, + {' ', ' ', ' '}, + }; + + char current_player = 'X'; + + if(difficulty == 1 || difficulty == 2) { + if(rand() % 2 == 0) { + current_player = 'X'; + } else { + current_player = 'O'; + } + } + + while(1){ + print_board(board); + + if(difficulty == 3) { + two_player_move(board, current_player); + + if(checkwin(board, current_player)) { + + if(current_player == 'X') { + score.player++; + print_board(board); + printf("\nCONGRATULATIONS Player %c won the game", current_player); + return; + + } else { + + score.computer++; + print_board(board); + printf("\nCONGRATULATIONS Player %c won the game", current_player); + return; + } + } + + if(checkdraw(board)) { + score.draw++; + print_board(board); + printf("\nIt's a draw!"); + return; } - if (check_draw(board)) { - score.draw++; - print_board(board); - printf("\nIt's a draw!"); - break; + current_player = (current_player == 'X') ? 'O' : 'X'; + } else { + + if(current_player == 'X'){ + playermove(board); + + + if(checkwin(board,'X')){ + score.player++; + print_board(board); + + printf("\nCONGRATULATIONS Player X won the game"); + return; + } + + current_player = 'O'; + + } else { + computermove(board); + + + if(checkwin(board,'O')) { + score.computer++; + print_board(board); + + printf("\nCONGRATULATIONS Player O (COMPUTER) won the game"); + return; + } + + current_player = 'X'; + } + + if(checkdraw(board)){ + score.draw++; + print_board(board); + + printf("\nIts a draw!"); + return; + } + } + } } - } + +int validmove(char board[3][3], int row, int col){ + return !(row < 0 || + row > 2 || + col < 0 || + col > 2 || + board[row][col] != ' '); } -int is_valid_move(char board[BOARD_SIZE][BOARD_SIZE], int row, int col) { - return !(row < 0 || col < 0 || - row > 2 || col > 2 || - board[row][col] != ' '); + +void two_player_move(char board[3][3], char player){ + + int row, col; + + do{ + printf("\nPlayer %c's turn", player); + printf("\nEnter row and column (1-3) for %c : ", player); + scanf(" %d %d", &row, &col); + + row--; + col--; + } while(!validmove(board, row, col)); + + board[row][col] = player; + } -void player_move(char board[BOARD_SIZE][BOARD_SIZE]) { - int count = 0, x, y; - for (int i = 0; i < BOARD_SIZE; i++) { - for (int j = 0; j < BOARD_SIZE; j++) { - if (board[i][j] == ' ') { - count++; - x = i; - y = j; - } - } +void playermove(char board[3][3]){ + + int count = 0, x, y; + for(int i = 0; i < 3; i++){ + for(int j = 0; j < 3; j++){ + if(board[i][j] == ' '){ + count++; + x = i; + y = j; + } + } + } + + if(count == 1){ + board[x][y] = 'X'; + return; + } + + int row, col; + do { + printf("\nPlayer X's turn"); + + printf("\nEnter row and column (1-3) for X : "); + scanf(" %d", &row); + scanf(" %d", &col); + + row--; + col--; + + }while(!validmove(board, row, col)); + + board[row][col] = 'X'; +} + +void computermove(char board[3][3]){ + + // 1.IMMEDIATE WIN + for(int i = 0; i < 3; i++){ + for(int j = 0; j < 3; j++){ + + if(board[i][j] == ' '){ + board[i][j] = 'O'; + if(checkwin(board, 'O')){ + return; + } + board[i][j] = ' '; + } + } } + - if (count == 1) { - board[x][y] = X; - return; + // 2.IMMEDIATE BLOCK + for(int i = 0; i < 3; i++){ + for(int j = 0; j < 3; j++){ + + if(board[i][j] == ' '){ + board[i][j] = 'X'; + if(checkwin(board, 'X')){ + board[i][j] = 'O'; + return; + } + board[i][j] = ' '; + } + } } - int row, col; - do { - printf("\nPlayer X's turn."); - printf("\nEnter row and column (1-3) for X: "); - scanf("%d", &row); - scanf("%d", &col); - row--; col--; // converting to zero based - } while (!is_valid_move(board, row, col)); - board[row][col] = X; -} + if(difficulty == 2){ + -void computer_move(char board[BOARD_SIZE][BOARD_SIZE]) { - // 1. Play for Immediate win - for (int i = 0; i < BOARD_SIZE; i++) { - for (int j = 0; j < BOARD_SIZE; j++) { - if (board[i][j] == ' ') { - board[i][j] = O; - if (check_win(board, O)) { - return; + //3. TAKE CENTER IF POSSIBLE + if(board[1][1] == ' '){ + board[1][1] = 'O'; + return; + } + + // 4.Take opposite corner if player took one corner + if(board[0][0] == 'X' && board[2][2] == ' '){ + board[2][2] = 'O'; + return; + } + if(board[2][2] == 'X' && board[0][0] == ' '){ + board[0][0] = 'O'; + return; + } + if(board[0][2] == 'X' && board[2][0] == ' '){ + board[2][0] = 'O'; + return; + } + if(board[2][0] == 'X' && board[0][2] == ' '){ + board[0][2] = 'O'; + return; } - board[i][j] = ' '; - } - } - } - // 2. Play for Immediate Block - for (int i = 0; i < BOARD_SIZE; i++) { - for (int j = 0; j < BOARD_SIZE; j++) { - if (board[i][j] == ' ') { - board[i][j] = X; - if (check_win(board, X)) { - board[i][j] = O; - return; + + // 5.If player takes opposite corners, take any side to prevent fork + if((board[0][0] == 'X' && board[2][2] == 'X') || + (board[0][2] == 'X' && board[2][0] == 'X')){ + if(board[0][1] == ' '){ + board[0][1] = 'O'; + return; + } + if(board[1][0] == ' '){ + board[1][0] = 'O'; + return; + } + if(board[1][2] == ' '){ + board[1][2] = 'O'; + return; + } + if(board[2][1] == ' '){ + board[2][1] = 'O'; + return; + } } - board[i][j] = ' '; - } - } - } - // GOD Mode - if (difficulty == 2) { - // 3. Play Center if available - if (board[1][1] == ' ') { - board[1][1] = O; - return; - } - // 4. Play Corner if available - int corner[4][2] = { - {0, 0}, - {0, 2}, - {2, 0}, - {2, 2} - }; - for (int i = 0; i < 4; i++) { - if (board[corner[i][0]][corner[i][1]] == ' ') { - board[corner[i][0]][corner[i][1]] = O; - return; - } - } - } + // 6.Prioritize remaining corners - // 5. Play first available move - for (int i = 0; i < BOARD_SIZE; i++) { - for (int j = 0; j < BOARD_SIZE; j++) { - if (board[i][j] == ' ') { - board[i][j] = O; - return; - } - } - } -} + if(board[0][0] == ' '){ + board[0][0] = 'O'; + return; + } + + if(board[0][2] == ' '){ + board[0][2] = 'O'; + return; + } + + if(board[2][0] == ' '){ + board[2][0] = 'O'; + return; + } + + if(board[2][2] == ' '){ + board[2][2] = 'O'; + return; + } -int check_win(char board[BOARD_SIZE][BOARD_SIZE], char player) { - for (int i = 0; i < BOARD_SIZE; i++) { - if (board[i][0] == player && board[i][1] == player && board[i][2] == player) { - return 1; - } - if (board[0][i] == player && board[1][i] == player && board[2][i] == player) { - return 1; + + // 7.Take sides if no corner is free + if(board[0][1] == ' '){ + board[0][1] = 'O'; + return; + } + if(board[1][0] == ' '){ + board[1][0] = 'O'; + return; + } + if(board[1][2] == ' '){ + board[1][2] = 'O'; + return; + } + if(board[2][1] == ' '){ + board[2][1] = 'O'; + return; + } +} + //8.TAKE FIRST AVAIABLE MOVE + for(int i = 0; i < 3; i++){ + for(int j = 0; j < 3; j++){ + + if(board[i][j] == ' '){ + board[i][j] = 'O'; + return; + } + } } - } + +} - if ((board[0][0] == player && board[1][1] == player && board[2][2] == player) || - (board[2][0] == player && board[1][1] == player && board[0][2] == player)) { - return 1; - } - return 0; +int checkdraw(char board[3][3]){ + for(int i = 0; i < 3; i++){ + for(int j = 0; j < 3; j++){ + if(board[i][j] == ' '){ + return 0; + } + } + } + + return 1; } -int check_draw(char board[BOARD_SIZE][BOARD_SIZE]) { - for (int i = 0; i < BOARD_SIZE; i++) { - for (int j = 0; j < BOARD_SIZE; j++) { - if (board[i][j] == ' ') { - return 0; - } - } - } - return 1; +int checkwin(char board[3][3], char player){ + + for(int i = 0; i < 3; i++){ + if(board[i][0] == player && board[i][1] == player && board[i][2] == player){ + return 1; + } + + if(board[0][i] == player && board[1][i] == player && board[2][i] == player){ + return 1; + } + } + + if((board[0][0] == player && board[1][1] == player && board[2][2] == player) || + (board[0][2] == player && board[1][1] == player && board[2][0] == player)){ + + return 1; + } + + return 0; } -void print_board(char board[BOARD_SIZE][BOARD_SIZE]) { - clear_screen(); - printf("Score - Player X: %d, Computer: %d, Draws: %d", score.player, score.computer, score.draw); - printf("\nTic-Tac-Toe\n"); - - for (int i = 0 ; i < BOARD_SIZE; i++) { - printf("\n"); - for (int j = 0; j < BOARD_SIZE; j++) { - printf(" %c ", board[i][j]); - if (j < BOARD_SIZE - 1) { - printf("|"); - } - } - if (i < BOARD_SIZE - 1) { - printf("\n---+---+---"); - } - } - printf("\n\n"); +void print_board(char board[3][3]){ + + clear_screen(); + if(difficulty == 3) { + printf("Score : PLAYER X = %d , PLAYER O = %d , DRAW (O/X) = %d", + score.player, score.computer, score.draw); + } else { + printf("Score : PLAYER (X) = %d , COMPUTER (O) = %d , DRAW (O/X) = %d", + score.player, score.computer, score.draw); + } + + + printf("\n==================\nTIC_TAC_TOE (O/X)\n==================\n"); + + for(int i = 0; i < 3; i++){ + printf("\n"); + if(i != 0){ + printf("---+---+---\n"); + } + for(int j = 0; j < 3; j++){ + if(j != 0){ + printf("|"); + } + printf(" %c ", board[i][j]); + } + } + printf("\n\n"); } -void input_difficulty() { - while (1) { - printf("\nSelect difficulty level:"); - printf("\n1. Human (Standard)"); - printf("\n2. God (Impossible to win)"); - printf("\nEnter your choice: "); - scanf("%d", &difficulty); - - if (difficulty != 1 && difficulty != 2) { - printf("\nIncorrect choice enter (1/2)!!"); - } else { - break; - } - }; +void get_difficulty(){ + + while(1){ + printf("\n==================\nTIC_TAC_TOE (O/X)\n==================\n"); + printf("\nChoose difficulty level: "); + printf("\n1. Computer (Standard) "); + printf("\n2. Computer (Impossible To Win) "); + printf("\n3. Two Player Mode"); + printf("\nEnter your choice : "); + scanf(" %d", &difficulty); + + if(difficulty != 1 && difficulty != 2 && difficulty != 3){ + printf("\nInvalid input. Please enter (1/2/3):\n"); + } else { + break; + } + + } + } -void clear_screen() { - #ifdef _Win32 - system("cls"); - #else - system("clear"); - #endif -} \ No newline at end of file +void clear_screen(){ + + #ifdef _WIN32 + system("cls"); + + #else + system("clear"); + + #endif +}