2020-07-31 14:00:30 +03:00
|
|
|
|
/**
|
|
|
|
|
* @file tic-tac-toe.c
|
|
|
|
|
* @author [vivekboss99](github.com/vivekboss99)
|
|
|
|
|
* @author [Krishna Vedala](https://github.com/kvedala)
|
|
|
|
|
* @brief [Tic-Tac-Toe game](https://en.wikipedia.org/wiki/Tic-tac-toe)
|
|
|
|
|
* implementation in C
|
2021-12-01 20:43:09 +03:00
|
|
|
|
* @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
|
2020-07-31 14:00:30 +03:00
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <time.h>
|
2021-02-10 17:02:01 +03:00
|
|
|
|
#include <string.h>
|
2020-07-31 14:00:30 +03:00
|
|
|
|
|
|
|
|
|
// 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()
|
2021-02-10 17:02:01 +03:00
|
|
|
|
{
|
|
|
|
|
srand( (unsigned int)time(NULL));
|
2020-07-31 14:00:30 +03:00
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
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++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int x = 1; x < 10; x++)
|
|
|
|
|
{
|
|
|
|
|
k = 0;
|
|
|
|
|
|
|
|
|
|
printf("Where would you like to place 'x' ");
|
|
|
|
|
scanf("%d", &m);
|
|
|
|
|
|
|
|
|
|
placex(m);
|
|
|
|
|
if(table_fill_count<4)
|
|
|
|
|
{
|
|
|
|
|
place();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 (table_fill_count==4)
|
|
|
|
|
{
|
|
|
|
|
printf("\nDRAW ");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @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;
|
|
|
|
|
|
|
|
|
|
printf("PLAYER1 - where would you like to place 'x' : ");
|
|
|
|
|
scanf("%d", &m);
|
|
|
|
|
|
|
|
|
|
placex(m);
|
|
|
|
|
if(doublemode_table_count<4)
|
|
|
|
|
{
|
|
|
|
|
printf("PLAYER2 - where would you like to place 'o' : ");
|
|
|
|
|
scanf("%d", &e1);
|
|
|
|
|
|
|
|
|
|
placey(e1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
for (int j = 0; j < 3; j++)
|
|
|
|
|
{
|
|
|
|
|
printf("%c ", game_table[k]);
|
|
|
|
|
k++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-10 17:02:01 +03:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-07-31 14:00:30 +03:00
|
|
|
|
/**
|
|
|
|
|
* @brief Update table by placing an `X`
|
|
|
|
|
*
|
|
|
|
|
* @param m location to place `X`
|
|
|
|
|
*
|
|
|
|
|
* @returns None
|
|
|
|
|
*/
|
|
|
|
|
void placex(int m)
|
|
|
|
|
{
|
2021-02-10 17:02:01 +03:00
|
|
|
|
int n1 = 0;
|
2020-07-31 14:00:30 +03:00
|
|
|
|
if (m >= 1 && m <= 9)
|
|
|
|
|
{
|
|
|
|
|
if (game_table[m - 1] != 'x' && game_table[m - 1] != 'o')
|
|
|
|
|
{
|
|
|
|
|
game_table[m - 1] = 'x';
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-02-10 17:02:01 +03:00
|
|
|
|
int n = check_placex();
|
|
|
|
|
placex(n);
|
2020-07-31 14:00:30 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-02-10 17:02:01 +03:00
|
|
|
|
int n = check_placex();
|
|
|
|
|
placex(n);
|
2020-07-31 14:00:30 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* @brief Update table by placing an `O`
|
|
|
|
|
*
|
|
|
|
|
* @returns None
|
|
|
|
|
*/
|
|
|
|
|
void place()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
int e = rand() % 9;
|
|
|
|
|
|
2022-11-14 22:10:23 +03:00
|
|
|
|
if (e >= 0)
|
2020-07-31 14:00:30 +03:00
|
|
|
|
{
|
|
|
|
|
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)
|
|
|
|
|
{
|
2021-02-10 17:02:01 +03:00
|
|
|
|
int n1 = 0;
|
2020-07-31 14:00:30 +03:00
|
|
|
|
if (e1 >= 1 && e1 <= 9)
|
|
|
|
|
{
|
|
|
|
|
if (game_table[e1 - 1] != 'x' && game_table[e1 - 1] != 'o')
|
|
|
|
|
{
|
|
|
|
|
game_table[e1 - 1] = 'o';
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-02-10 17:02:01 +03:00
|
|
|
|
int n = check_placex();
|
|
|
|
|
placex(n);
|
2020-07-31 14:00:30 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-02-10 17:02:01 +03:00
|
|
|
|
int n = check_placex();
|
|
|
|
|
placex(n);
|
2020-07-31 14:00:30 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* @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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 (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 (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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (game_table[1] == 'o' && game_table[4] == 'o' &&
|
|
|
|
|
game_table[7] == 'o')
|
|
|
|
|
{
|
|
|
|
|
return -2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (game_table[2] == 'o' && game_table[4] == 'o' &&
|
|
|
|
|
game_table[6] == 'o')
|
|
|
|
|
{
|
|
|
|
|
return -2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|