A command-line unbeatable Tic-Tac-Toe written in C












3












$begingroup$


I'm trying to learn programming and this Tic-Tac-Toe is one of my first projects. The user gets to start first as 'x' or second as 'o'.



Please give me any criticism you find on the code and give suggestions on where I can improve the structure and style.



#include <stdio.h>
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
/*the print function will be called after every input by the user*/
void print(char (*GRID)[7])
{
/*length and breadth of the grid of a tic-tac-toe game is 3*3*/
int length=7, breadth=7,i,j;
printf("nTic-Tac-Toe by Udhay Sankarnn");
for(i=0;i<length;i++)
{
printf(" ");
for(j=0;j<breadth;j++)
{
printf("%c",GRID[i][j]);
}
printf("n");
}
}
/*function to check the validity of user input*/
int valid(char (*GRID)[7],int TEMP1)
{
if(((TEMP1)>0)&&((TEMP1)<10))
{
switch (TEMP1)
{
case 1:
if (GRID[1][1]=='x'||GRID[1][1]=='o')
{
printf("nPosition already occupied!!!n");
return 0;
}
else
return 1;
break;
case 2:
if (GRID[1][3]=='x'||GRID[1][3]=='o')
{
printf("nPosition already occupied!!!n");
return 0;
}
else
return 1;
break;
case 3:
if (GRID[1][5]=='x'||GRID[1][5]=='o')
{
printf("nPosition already occupied!!!n");
return 0;
}
else
return 1;
break;
case 4:
if (GRID[3][1]=='x'||GRID[3][1]=='o')
{
printf("nPosition already occupied!!!n");
return 0;
}
else
return 1;
break;
case 5:
if (GRID[3][3]=='x'||GRID[3][3]=='o')
{
printf("nPosition already occupied!!!n");
return 0;
}
else
return 1;
break;
case 6:
if (GRID[3][5]=='x'||GRID[3][5]=='o')
{
printf("nPosition already occupied!!!n");
return 0;
}
else
return 1;
break;
case 7:
if (GRID[5][1]=='x'||GRID[5][1]=='o')
{
printf("nPosition already occupied!!!n");
return 0;
}
else
return 1;
break;
case 8:
if (GRID[5][3]=='x'||GRID[5][3]=='o')
{
printf("nPosition already occupied!!!n");
return 0;
}
else
return 1;
break;
case 9:
if (GRID[5][5]=='x'||GRID[5][5]=='o')
{
printf("nPosition already occupied!!!n");
return 0;
}
else
return 1;
break;
}
}
else
{
return 0;
}
}
/*function to get input from user*/
void get_input(char (*GRID)[7],int turn)
{
int TEMP2;
if(1==turn)
{
printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'x': ");
}
else
{
printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'o': ");
}
scanf("%d",&TEMP2);
while((valid(GRID,TEMP2))!=1)
{
//if position is already occupied
printf("nInvalid Input! Enter a valid positionn");
if(1==turn)
{
printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'x': ");
}
else
{
printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'o': ");
}
scanf("%d",&TEMP2);
}
if(1==turn)
{
switch (TEMP2)
{
case 1:GRID[1][1]='x';
break;
case 2:GRID[1][3]='x';
break;
case 3:GRID[1][5]='x';
break;
case 4:GRID[3][1]='x';
break;
case 5:GRID[3][3]='x';
break;
case 6:GRID[3][5]='x';
break;
case 7:GRID[5][1]='x';
break;
case 8:GRID[5][3]='x';
break;
case 9:GRID[5][5]='x';
break;
}
}
else
{
switch (TEMP2)
{
case 1:GRID[1][1]='o';
break;
case 2:GRID[1][3]='o';
break;
case 3:GRID[1][5]='o';
break;
case 4:GRID[3][1]='o';
break;
case 5:GRID[3][3]='o';
break;
case 6:GRID[3][5]='o';
break;
case 7:GRID[5][1]='o';
break;
case 8:GRID[5][3]='o';
break;
case 9:GRID[5][5]='o';
break;
}
}
}
//function to find the number of available available_spots
int available_spots(char (*GRID)[7])
{
int spots=0;
for(int i=1;i<6;i=i+2)
for(int j=1;j<6;j=j+2)
{
if (GRID[i][j]==' ')
spots++;
}
return spots;
}
//function to check for win condition after every move from user and computer
int terminal_state(char (*GRID)[7])
{
if (((GRID[1][1]=='o')&&(GRID[1][3]=='o'))&&((GRID[1][3]=='o')&&(GRID[1][5]=='o')))
{
return -10;
}
else if (((GRID[3][1]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[3][5]=='o')))
{
return -10;
}
else if (((GRID[5][1]=='o')&&(GRID[5][3]=='o'))&&((GRID[5][3]=='o')&&(GRID[5][5]=='o')))
{
return -10;
}
else if (((GRID[1][1]=='o')&&(GRID[3][1]=='o'))&&((GRID[3][1]=='o')&&(GRID[5][1]=='o')))
{
return -10;
}
else if (((GRID[1][3]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[5][3]=='o')))
{
return -10;
}
else if (((GRID[1][5]=='o')&&(GRID[3][5]=='o'))&&((GRID[3][5]=='o')&&(GRID[5][5]=='o')))
{
return -10;
}
else if (((GRID[1][1]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[5][5]=='o')))
{
return -10;
}
else if (((GRID[1][5]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[5][1]=='o')))
{
return -10;
}
if (((GRID[1][1]=='x')&&(GRID[1][3]=='x'))&&((GRID[1][3]=='x')&&(GRID[1][5]=='x')))
{
return 10;
}
else if (((GRID[3][1]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[3][5]=='x')))
{
return 10;
}
else if (((GRID[5][1]=='x')&&(GRID[5][3]=='x'))&&((GRID[5][3]=='x')&&(GRID[5][5]=='x')))
{
return 10;
}
else if (((GRID[1][1]=='x')&&(GRID[3][1]=='x'))&&((GRID[3][1]=='x')&&(GRID[5][1]=='x')))
{
return 10;
}
else if (((GRID[1][3]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[5][3]=='x')))
{
return 10;
}
else if (((GRID[1][5]=='x')&&(GRID[3][5]=='x'))&&((GRID[3][5]=='x')&&(GRID[5][5]=='x')))
{
return 10;
}
else if (((GRID[1][1]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[5][5]=='x')))
{
return 10;
}
else if (((GRID[1][5]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[5][1]=='x')))
{
return 10;
}
else if(available_spots(GRID)==0)
return 0;
}
/*function of minimax algorithm that is recursive*/
int minimax(char (*GRID)[7],int turn)
{
//
int best;
if(terminal_state(GRID)==10)
return 10;
if(terminal_state(GRID)==-10)
return -10;
if(terminal_state(GRID)==0)
return 0;
//
if(0==turn)
{
int i,j;
int temp;
best=1000;
for(int i=1;i<6;i=i+2)
{
for(int j=1;j<6;j=j+2)
{
if(GRID[i][j]==' ')
{
GRID[i][j]='o';
temp=minimax(GRID,1);
best=MIN(temp,best);
GRID[i][j]=' ';
}
}
}
return best;
}
else if(1==turn)
{
int i,j;
int temp;
best=-1000;
for(i=1;i<6;i=i+2)
{
for(j=1;j<6;j=j+2)
{
if(GRID[i][j]==' ')
{
GRID[i][j]='x';
temp=minimax(GRID,0);
best=MAX(temp,best);
GRID[i][j]=' ';
}
}
}
return best;
}
}
//the following function returns the best move
void computer_position(char (*GRID)[7],int turn)
{
if(0==turn)
{
int sample=1000;
int computer_move[3];
computer_move[0]=sample;
for(int i=1;i<6;i=i+2)
{
for(int j=1;j<6;j=j+2)
{
if(GRID[i][j]==' ')
{
GRID[i][j]='o';
sample=minimax(GRID,!turn);
if(sample<computer_move[0])
{
computer_move[0]=sample;
computer_move[1]=i;
computer_move[2]=j;
}
GRID[i][j]=' ';
}
}
}
GRID[computer_move[1]][computer_move[2]]='o';
}
else
{
int sample=-1000;
int computer_move[3];
computer_move[0]=sample;
for(int i=1;i<6;i=i+2)
{
for(int j=1;j<6;j=j+2)
{
if(GRID[i][j]==' ')
{
GRID[i][j]='x';
sample=minimax(GRID,!turn);
if(sample>computer_move[0])
{
computer_move[0]=sample;
computer_move[1]=i;
computer_move[2]=j;
}
GRID[i][j]=' ';
}
}
}
GRID[computer_move[1]][computer_move[2]]='x';
}
}
/*main function*/
int main()
{
//int USR_INPUT,RESULT;
char GRID[7][7]={
{'-','-','-','-','-','-','-'},
{'|',' ','|',' ','|',' ','|'},
{'-','-','-','-','-','-','-'},
{'|',' ','|',' ','|',' ','|'},
{'-','-','-','-','-','-','-'},
{'|',' ','|',' ','|',' ','|'},
{'-','-','-','-','-','-','-'}
};
int turn;
//get the turn from the user
printf("nDo you want to go first as 'x', or second as 'o'?n");
printf("nEnter 1 for 'x' or 0 for 'o':");
scanf("%d",&turn);
while((turn!=0)&&(turn!=1))
{
printf("nInvalid value for turn!n");
printf("nDo you want to go first as 'x', or second as 'o'?n");
printf("nEnter 1 for 'x' or 0 for 'o':");
scanf("%d",&turn);
}
//when no spots are available or a win condition is obtained
if(1==turn)
{
while(available_spots(GRID)!=0)
{
print(GRID);
get_input(GRID,turn);
if(terminal_state(GRID)==10)
{
print(GRID);
printf("nYou have wonnn");
return 0;
}else if (terminal_state(GRID)==-10) {
print(GRID);
printf("nComputer has wonnn");
return 0;
}else if (terminal_state(GRID)==0) {
print(GRID);
printf("nThe game is a drawnn");
return 0;
}
computer_position(GRID,!turn);
}
}
else
{
while(available_spots(GRID)!=0)
{
computer_position(GRID,!turn);
if(terminal_state(GRID)==-10)
{
print(GRID);
printf("nYou have wonnn");
return 0;
}else if (terminal_state(GRID)==10) {
print(GRID);
printf("nComputer has wonnn");
return 0;
}else if (terminal_state(GRID)==0) {
print(GRID);
printf("nThe game is a drawnn");
return 0;
}
print(GRID);
get_input(GRID,turn);
}
}
}









share|improve this question









New contributor




Udhay Sankar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$

















    3












    $begingroup$


    I'm trying to learn programming and this Tic-Tac-Toe is one of my first projects. The user gets to start first as 'x' or second as 'o'.



    Please give me any criticism you find on the code and give suggestions on where I can improve the structure and style.



    #include <stdio.h>
    #define MAX(x, y) (((x) > (y)) ? (x) : (y))
    #define MIN(x, y) (((x) < (y)) ? (x) : (y))
    /*the print function will be called after every input by the user*/
    void print(char (*GRID)[7])
    {
    /*length and breadth of the grid of a tic-tac-toe game is 3*3*/
    int length=7, breadth=7,i,j;
    printf("nTic-Tac-Toe by Udhay Sankarnn");
    for(i=0;i<length;i++)
    {
    printf(" ");
    for(j=0;j<breadth;j++)
    {
    printf("%c",GRID[i][j]);
    }
    printf("n");
    }
    }
    /*function to check the validity of user input*/
    int valid(char (*GRID)[7],int TEMP1)
    {
    if(((TEMP1)>0)&&((TEMP1)<10))
    {
    switch (TEMP1)
    {
    case 1:
    if (GRID[1][1]=='x'||GRID[1][1]=='o')
    {
    printf("nPosition already occupied!!!n");
    return 0;
    }
    else
    return 1;
    break;
    case 2:
    if (GRID[1][3]=='x'||GRID[1][3]=='o')
    {
    printf("nPosition already occupied!!!n");
    return 0;
    }
    else
    return 1;
    break;
    case 3:
    if (GRID[1][5]=='x'||GRID[1][5]=='o')
    {
    printf("nPosition already occupied!!!n");
    return 0;
    }
    else
    return 1;
    break;
    case 4:
    if (GRID[3][1]=='x'||GRID[3][1]=='o')
    {
    printf("nPosition already occupied!!!n");
    return 0;
    }
    else
    return 1;
    break;
    case 5:
    if (GRID[3][3]=='x'||GRID[3][3]=='o')
    {
    printf("nPosition already occupied!!!n");
    return 0;
    }
    else
    return 1;
    break;
    case 6:
    if (GRID[3][5]=='x'||GRID[3][5]=='o')
    {
    printf("nPosition already occupied!!!n");
    return 0;
    }
    else
    return 1;
    break;
    case 7:
    if (GRID[5][1]=='x'||GRID[5][1]=='o')
    {
    printf("nPosition already occupied!!!n");
    return 0;
    }
    else
    return 1;
    break;
    case 8:
    if (GRID[5][3]=='x'||GRID[5][3]=='o')
    {
    printf("nPosition already occupied!!!n");
    return 0;
    }
    else
    return 1;
    break;
    case 9:
    if (GRID[5][5]=='x'||GRID[5][5]=='o')
    {
    printf("nPosition already occupied!!!n");
    return 0;
    }
    else
    return 1;
    break;
    }
    }
    else
    {
    return 0;
    }
    }
    /*function to get input from user*/
    void get_input(char (*GRID)[7],int turn)
    {
    int TEMP2;
    if(1==turn)
    {
    printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'x': ");
    }
    else
    {
    printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'o': ");
    }
    scanf("%d",&TEMP2);
    while((valid(GRID,TEMP2))!=1)
    {
    //if position is already occupied
    printf("nInvalid Input! Enter a valid positionn");
    if(1==turn)
    {
    printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'x': ");
    }
    else
    {
    printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'o': ");
    }
    scanf("%d",&TEMP2);
    }
    if(1==turn)
    {
    switch (TEMP2)
    {
    case 1:GRID[1][1]='x';
    break;
    case 2:GRID[1][3]='x';
    break;
    case 3:GRID[1][5]='x';
    break;
    case 4:GRID[3][1]='x';
    break;
    case 5:GRID[3][3]='x';
    break;
    case 6:GRID[3][5]='x';
    break;
    case 7:GRID[5][1]='x';
    break;
    case 8:GRID[5][3]='x';
    break;
    case 9:GRID[5][5]='x';
    break;
    }
    }
    else
    {
    switch (TEMP2)
    {
    case 1:GRID[1][1]='o';
    break;
    case 2:GRID[1][3]='o';
    break;
    case 3:GRID[1][5]='o';
    break;
    case 4:GRID[3][1]='o';
    break;
    case 5:GRID[3][3]='o';
    break;
    case 6:GRID[3][5]='o';
    break;
    case 7:GRID[5][1]='o';
    break;
    case 8:GRID[5][3]='o';
    break;
    case 9:GRID[5][5]='o';
    break;
    }
    }
    }
    //function to find the number of available available_spots
    int available_spots(char (*GRID)[7])
    {
    int spots=0;
    for(int i=1;i<6;i=i+2)
    for(int j=1;j<6;j=j+2)
    {
    if (GRID[i][j]==' ')
    spots++;
    }
    return spots;
    }
    //function to check for win condition after every move from user and computer
    int terminal_state(char (*GRID)[7])
    {
    if (((GRID[1][1]=='o')&&(GRID[1][3]=='o'))&&((GRID[1][3]=='o')&&(GRID[1][5]=='o')))
    {
    return -10;
    }
    else if (((GRID[3][1]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[3][5]=='o')))
    {
    return -10;
    }
    else if (((GRID[5][1]=='o')&&(GRID[5][3]=='o'))&&((GRID[5][3]=='o')&&(GRID[5][5]=='o')))
    {
    return -10;
    }
    else if (((GRID[1][1]=='o')&&(GRID[3][1]=='o'))&&((GRID[3][1]=='o')&&(GRID[5][1]=='o')))
    {
    return -10;
    }
    else if (((GRID[1][3]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[5][3]=='o')))
    {
    return -10;
    }
    else if (((GRID[1][5]=='o')&&(GRID[3][5]=='o'))&&((GRID[3][5]=='o')&&(GRID[5][5]=='o')))
    {
    return -10;
    }
    else if (((GRID[1][1]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[5][5]=='o')))
    {
    return -10;
    }
    else if (((GRID[1][5]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[5][1]=='o')))
    {
    return -10;
    }
    if (((GRID[1][1]=='x')&&(GRID[1][3]=='x'))&&((GRID[1][3]=='x')&&(GRID[1][5]=='x')))
    {
    return 10;
    }
    else if (((GRID[3][1]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[3][5]=='x')))
    {
    return 10;
    }
    else if (((GRID[5][1]=='x')&&(GRID[5][3]=='x'))&&((GRID[5][3]=='x')&&(GRID[5][5]=='x')))
    {
    return 10;
    }
    else if (((GRID[1][1]=='x')&&(GRID[3][1]=='x'))&&((GRID[3][1]=='x')&&(GRID[5][1]=='x')))
    {
    return 10;
    }
    else if (((GRID[1][3]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[5][3]=='x')))
    {
    return 10;
    }
    else if (((GRID[1][5]=='x')&&(GRID[3][5]=='x'))&&((GRID[3][5]=='x')&&(GRID[5][5]=='x')))
    {
    return 10;
    }
    else if (((GRID[1][1]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[5][5]=='x')))
    {
    return 10;
    }
    else if (((GRID[1][5]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[5][1]=='x')))
    {
    return 10;
    }
    else if(available_spots(GRID)==0)
    return 0;
    }
    /*function of minimax algorithm that is recursive*/
    int minimax(char (*GRID)[7],int turn)
    {
    //
    int best;
    if(terminal_state(GRID)==10)
    return 10;
    if(terminal_state(GRID)==-10)
    return -10;
    if(terminal_state(GRID)==0)
    return 0;
    //
    if(0==turn)
    {
    int i,j;
    int temp;
    best=1000;
    for(int i=1;i<6;i=i+2)
    {
    for(int j=1;j<6;j=j+2)
    {
    if(GRID[i][j]==' ')
    {
    GRID[i][j]='o';
    temp=minimax(GRID,1);
    best=MIN(temp,best);
    GRID[i][j]=' ';
    }
    }
    }
    return best;
    }
    else if(1==turn)
    {
    int i,j;
    int temp;
    best=-1000;
    for(i=1;i<6;i=i+2)
    {
    for(j=1;j<6;j=j+2)
    {
    if(GRID[i][j]==' ')
    {
    GRID[i][j]='x';
    temp=minimax(GRID,0);
    best=MAX(temp,best);
    GRID[i][j]=' ';
    }
    }
    }
    return best;
    }
    }
    //the following function returns the best move
    void computer_position(char (*GRID)[7],int turn)
    {
    if(0==turn)
    {
    int sample=1000;
    int computer_move[3];
    computer_move[0]=sample;
    for(int i=1;i<6;i=i+2)
    {
    for(int j=1;j<6;j=j+2)
    {
    if(GRID[i][j]==' ')
    {
    GRID[i][j]='o';
    sample=minimax(GRID,!turn);
    if(sample<computer_move[0])
    {
    computer_move[0]=sample;
    computer_move[1]=i;
    computer_move[2]=j;
    }
    GRID[i][j]=' ';
    }
    }
    }
    GRID[computer_move[1]][computer_move[2]]='o';
    }
    else
    {
    int sample=-1000;
    int computer_move[3];
    computer_move[0]=sample;
    for(int i=1;i<6;i=i+2)
    {
    for(int j=1;j<6;j=j+2)
    {
    if(GRID[i][j]==' ')
    {
    GRID[i][j]='x';
    sample=minimax(GRID,!turn);
    if(sample>computer_move[0])
    {
    computer_move[0]=sample;
    computer_move[1]=i;
    computer_move[2]=j;
    }
    GRID[i][j]=' ';
    }
    }
    }
    GRID[computer_move[1]][computer_move[2]]='x';
    }
    }
    /*main function*/
    int main()
    {
    //int USR_INPUT,RESULT;
    char GRID[7][7]={
    {'-','-','-','-','-','-','-'},
    {'|',' ','|',' ','|',' ','|'},
    {'-','-','-','-','-','-','-'},
    {'|',' ','|',' ','|',' ','|'},
    {'-','-','-','-','-','-','-'},
    {'|',' ','|',' ','|',' ','|'},
    {'-','-','-','-','-','-','-'}
    };
    int turn;
    //get the turn from the user
    printf("nDo you want to go first as 'x', or second as 'o'?n");
    printf("nEnter 1 for 'x' or 0 for 'o':");
    scanf("%d",&turn);
    while((turn!=0)&&(turn!=1))
    {
    printf("nInvalid value for turn!n");
    printf("nDo you want to go first as 'x', or second as 'o'?n");
    printf("nEnter 1 for 'x' or 0 for 'o':");
    scanf("%d",&turn);
    }
    //when no spots are available or a win condition is obtained
    if(1==turn)
    {
    while(available_spots(GRID)!=0)
    {
    print(GRID);
    get_input(GRID,turn);
    if(terminal_state(GRID)==10)
    {
    print(GRID);
    printf("nYou have wonnn");
    return 0;
    }else if (terminal_state(GRID)==-10) {
    print(GRID);
    printf("nComputer has wonnn");
    return 0;
    }else if (terminal_state(GRID)==0) {
    print(GRID);
    printf("nThe game is a drawnn");
    return 0;
    }
    computer_position(GRID,!turn);
    }
    }
    else
    {
    while(available_spots(GRID)!=0)
    {
    computer_position(GRID,!turn);
    if(terminal_state(GRID)==-10)
    {
    print(GRID);
    printf("nYou have wonnn");
    return 0;
    }else if (terminal_state(GRID)==10) {
    print(GRID);
    printf("nComputer has wonnn");
    return 0;
    }else if (terminal_state(GRID)==0) {
    print(GRID);
    printf("nThe game is a drawnn");
    return 0;
    }
    print(GRID);
    get_input(GRID,turn);
    }
    }
    }









    share|improve this question









    New contributor




    Udhay Sankar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.







    $endgroup$















      3












      3








      3





      $begingroup$


      I'm trying to learn programming and this Tic-Tac-Toe is one of my first projects. The user gets to start first as 'x' or second as 'o'.



      Please give me any criticism you find on the code and give suggestions on where I can improve the structure and style.



      #include <stdio.h>
      #define MAX(x, y) (((x) > (y)) ? (x) : (y))
      #define MIN(x, y) (((x) < (y)) ? (x) : (y))
      /*the print function will be called after every input by the user*/
      void print(char (*GRID)[7])
      {
      /*length and breadth of the grid of a tic-tac-toe game is 3*3*/
      int length=7, breadth=7,i,j;
      printf("nTic-Tac-Toe by Udhay Sankarnn");
      for(i=0;i<length;i++)
      {
      printf(" ");
      for(j=0;j<breadth;j++)
      {
      printf("%c",GRID[i][j]);
      }
      printf("n");
      }
      }
      /*function to check the validity of user input*/
      int valid(char (*GRID)[7],int TEMP1)
      {
      if(((TEMP1)>0)&&((TEMP1)<10))
      {
      switch (TEMP1)
      {
      case 1:
      if (GRID[1][1]=='x'||GRID[1][1]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 2:
      if (GRID[1][3]=='x'||GRID[1][3]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 3:
      if (GRID[1][5]=='x'||GRID[1][5]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 4:
      if (GRID[3][1]=='x'||GRID[3][1]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 5:
      if (GRID[3][3]=='x'||GRID[3][3]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 6:
      if (GRID[3][5]=='x'||GRID[3][5]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 7:
      if (GRID[5][1]=='x'||GRID[5][1]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 8:
      if (GRID[5][3]=='x'||GRID[5][3]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 9:
      if (GRID[5][5]=='x'||GRID[5][5]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      }
      }
      else
      {
      return 0;
      }
      }
      /*function to get input from user*/
      void get_input(char (*GRID)[7],int turn)
      {
      int TEMP2;
      if(1==turn)
      {
      printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'x': ");
      }
      else
      {
      printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'o': ");
      }
      scanf("%d",&TEMP2);
      while((valid(GRID,TEMP2))!=1)
      {
      //if position is already occupied
      printf("nInvalid Input! Enter a valid positionn");
      if(1==turn)
      {
      printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'x': ");
      }
      else
      {
      printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'o': ");
      }
      scanf("%d",&TEMP2);
      }
      if(1==turn)
      {
      switch (TEMP2)
      {
      case 1:GRID[1][1]='x';
      break;
      case 2:GRID[1][3]='x';
      break;
      case 3:GRID[1][5]='x';
      break;
      case 4:GRID[3][1]='x';
      break;
      case 5:GRID[3][3]='x';
      break;
      case 6:GRID[3][5]='x';
      break;
      case 7:GRID[5][1]='x';
      break;
      case 8:GRID[5][3]='x';
      break;
      case 9:GRID[5][5]='x';
      break;
      }
      }
      else
      {
      switch (TEMP2)
      {
      case 1:GRID[1][1]='o';
      break;
      case 2:GRID[1][3]='o';
      break;
      case 3:GRID[1][5]='o';
      break;
      case 4:GRID[3][1]='o';
      break;
      case 5:GRID[3][3]='o';
      break;
      case 6:GRID[3][5]='o';
      break;
      case 7:GRID[5][1]='o';
      break;
      case 8:GRID[5][3]='o';
      break;
      case 9:GRID[5][5]='o';
      break;
      }
      }
      }
      //function to find the number of available available_spots
      int available_spots(char (*GRID)[7])
      {
      int spots=0;
      for(int i=1;i<6;i=i+2)
      for(int j=1;j<6;j=j+2)
      {
      if (GRID[i][j]==' ')
      spots++;
      }
      return spots;
      }
      //function to check for win condition after every move from user and computer
      int terminal_state(char (*GRID)[7])
      {
      if (((GRID[1][1]=='o')&&(GRID[1][3]=='o'))&&((GRID[1][3]=='o')&&(GRID[1][5]=='o')))
      {
      return -10;
      }
      else if (((GRID[3][1]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[3][5]=='o')))
      {
      return -10;
      }
      else if (((GRID[5][1]=='o')&&(GRID[5][3]=='o'))&&((GRID[5][3]=='o')&&(GRID[5][5]=='o')))
      {
      return -10;
      }
      else if (((GRID[1][1]=='o')&&(GRID[3][1]=='o'))&&((GRID[3][1]=='o')&&(GRID[5][1]=='o')))
      {
      return -10;
      }
      else if (((GRID[1][3]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[5][3]=='o')))
      {
      return -10;
      }
      else if (((GRID[1][5]=='o')&&(GRID[3][5]=='o'))&&((GRID[3][5]=='o')&&(GRID[5][5]=='o')))
      {
      return -10;
      }
      else if (((GRID[1][1]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[5][5]=='o')))
      {
      return -10;
      }
      else if (((GRID[1][5]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[5][1]=='o')))
      {
      return -10;
      }
      if (((GRID[1][1]=='x')&&(GRID[1][3]=='x'))&&((GRID[1][3]=='x')&&(GRID[1][5]=='x')))
      {
      return 10;
      }
      else if (((GRID[3][1]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[3][5]=='x')))
      {
      return 10;
      }
      else if (((GRID[5][1]=='x')&&(GRID[5][3]=='x'))&&((GRID[5][3]=='x')&&(GRID[5][5]=='x')))
      {
      return 10;
      }
      else if (((GRID[1][1]=='x')&&(GRID[3][1]=='x'))&&((GRID[3][1]=='x')&&(GRID[5][1]=='x')))
      {
      return 10;
      }
      else if (((GRID[1][3]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[5][3]=='x')))
      {
      return 10;
      }
      else if (((GRID[1][5]=='x')&&(GRID[3][5]=='x'))&&((GRID[3][5]=='x')&&(GRID[5][5]=='x')))
      {
      return 10;
      }
      else if (((GRID[1][1]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[5][5]=='x')))
      {
      return 10;
      }
      else if (((GRID[1][5]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[5][1]=='x')))
      {
      return 10;
      }
      else if(available_spots(GRID)==0)
      return 0;
      }
      /*function of minimax algorithm that is recursive*/
      int minimax(char (*GRID)[7],int turn)
      {
      //
      int best;
      if(terminal_state(GRID)==10)
      return 10;
      if(terminal_state(GRID)==-10)
      return -10;
      if(terminal_state(GRID)==0)
      return 0;
      //
      if(0==turn)
      {
      int i,j;
      int temp;
      best=1000;
      for(int i=1;i<6;i=i+2)
      {
      for(int j=1;j<6;j=j+2)
      {
      if(GRID[i][j]==' ')
      {
      GRID[i][j]='o';
      temp=minimax(GRID,1);
      best=MIN(temp,best);
      GRID[i][j]=' ';
      }
      }
      }
      return best;
      }
      else if(1==turn)
      {
      int i,j;
      int temp;
      best=-1000;
      for(i=1;i<6;i=i+2)
      {
      for(j=1;j<6;j=j+2)
      {
      if(GRID[i][j]==' ')
      {
      GRID[i][j]='x';
      temp=minimax(GRID,0);
      best=MAX(temp,best);
      GRID[i][j]=' ';
      }
      }
      }
      return best;
      }
      }
      //the following function returns the best move
      void computer_position(char (*GRID)[7],int turn)
      {
      if(0==turn)
      {
      int sample=1000;
      int computer_move[3];
      computer_move[0]=sample;
      for(int i=1;i<6;i=i+2)
      {
      for(int j=1;j<6;j=j+2)
      {
      if(GRID[i][j]==' ')
      {
      GRID[i][j]='o';
      sample=minimax(GRID,!turn);
      if(sample<computer_move[0])
      {
      computer_move[0]=sample;
      computer_move[1]=i;
      computer_move[2]=j;
      }
      GRID[i][j]=' ';
      }
      }
      }
      GRID[computer_move[1]][computer_move[2]]='o';
      }
      else
      {
      int sample=-1000;
      int computer_move[3];
      computer_move[0]=sample;
      for(int i=1;i<6;i=i+2)
      {
      for(int j=1;j<6;j=j+2)
      {
      if(GRID[i][j]==' ')
      {
      GRID[i][j]='x';
      sample=minimax(GRID,!turn);
      if(sample>computer_move[0])
      {
      computer_move[0]=sample;
      computer_move[1]=i;
      computer_move[2]=j;
      }
      GRID[i][j]=' ';
      }
      }
      }
      GRID[computer_move[1]][computer_move[2]]='x';
      }
      }
      /*main function*/
      int main()
      {
      //int USR_INPUT,RESULT;
      char GRID[7][7]={
      {'-','-','-','-','-','-','-'},
      {'|',' ','|',' ','|',' ','|'},
      {'-','-','-','-','-','-','-'},
      {'|',' ','|',' ','|',' ','|'},
      {'-','-','-','-','-','-','-'},
      {'|',' ','|',' ','|',' ','|'},
      {'-','-','-','-','-','-','-'}
      };
      int turn;
      //get the turn from the user
      printf("nDo you want to go first as 'x', or second as 'o'?n");
      printf("nEnter 1 for 'x' or 0 for 'o':");
      scanf("%d",&turn);
      while((turn!=0)&&(turn!=1))
      {
      printf("nInvalid value for turn!n");
      printf("nDo you want to go first as 'x', or second as 'o'?n");
      printf("nEnter 1 for 'x' or 0 for 'o':");
      scanf("%d",&turn);
      }
      //when no spots are available or a win condition is obtained
      if(1==turn)
      {
      while(available_spots(GRID)!=0)
      {
      print(GRID);
      get_input(GRID,turn);
      if(terminal_state(GRID)==10)
      {
      print(GRID);
      printf("nYou have wonnn");
      return 0;
      }else if (terminal_state(GRID)==-10) {
      print(GRID);
      printf("nComputer has wonnn");
      return 0;
      }else if (terminal_state(GRID)==0) {
      print(GRID);
      printf("nThe game is a drawnn");
      return 0;
      }
      computer_position(GRID,!turn);
      }
      }
      else
      {
      while(available_spots(GRID)!=0)
      {
      computer_position(GRID,!turn);
      if(terminal_state(GRID)==-10)
      {
      print(GRID);
      printf("nYou have wonnn");
      return 0;
      }else if (terminal_state(GRID)==10) {
      print(GRID);
      printf("nComputer has wonnn");
      return 0;
      }else if (terminal_state(GRID)==0) {
      print(GRID);
      printf("nThe game is a drawnn");
      return 0;
      }
      print(GRID);
      get_input(GRID,turn);
      }
      }
      }









      share|improve this question









      New contributor




      Udhay Sankar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.







      $endgroup$




      I'm trying to learn programming and this Tic-Tac-Toe is one of my first projects. The user gets to start first as 'x' or second as 'o'.



      Please give me any criticism you find on the code and give suggestions on where I can improve the structure and style.



      #include <stdio.h>
      #define MAX(x, y) (((x) > (y)) ? (x) : (y))
      #define MIN(x, y) (((x) < (y)) ? (x) : (y))
      /*the print function will be called after every input by the user*/
      void print(char (*GRID)[7])
      {
      /*length and breadth of the grid of a tic-tac-toe game is 3*3*/
      int length=7, breadth=7,i,j;
      printf("nTic-Tac-Toe by Udhay Sankarnn");
      for(i=0;i<length;i++)
      {
      printf(" ");
      for(j=0;j<breadth;j++)
      {
      printf("%c",GRID[i][j]);
      }
      printf("n");
      }
      }
      /*function to check the validity of user input*/
      int valid(char (*GRID)[7],int TEMP1)
      {
      if(((TEMP1)>0)&&((TEMP1)<10))
      {
      switch (TEMP1)
      {
      case 1:
      if (GRID[1][1]=='x'||GRID[1][1]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 2:
      if (GRID[1][3]=='x'||GRID[1][3]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 3:
      if (GRID[1][5]=='x'||GRID[1][5]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 4:
      if (GRID[3][1]=='x'||GRID[3][1]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 5:
      if (GRID[3][3]=='x'||GRID[3][3]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 6:
      if (GRID[3][5]=='x'||GRID[3][5]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 7:
      if (GRID[5][1]=='x'||GRID[5][1]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 8:
      if (GRID[5][3]=='x'||GRID[5][3]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      case 9:
      if (GRID[5][5]=='x'||GRID[5][5]=='o')
      {
      printf("nPosition already occupied!!!n");
      return 0;
      }
      else
      return 1;
      break;
      }
      }
      else
      {
      return 0;
      }
      }
      /*function to get input from user*/
      void get_input(char (*GRID)[7],int turn)
      {
      int TEMP2;
      if(1==turn)
      {
      printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'x': ");
      }
      else
      {
      printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'o': ");
      }
      scanf("%d",&TEMP2);
      while((valid(GRID,TEMP2))!=1)
      {
      //if position is already occupied
      printf("nInvalid Input! Enter a valid positionn");
      if(1==turn)
      {
      printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'x': ");
      }
      else
      {
      printf("nConsider the 3*3 grid with 9 positionsnnIf position is row 2 column 3, Enter 6 as inputnnEnter your position for 'o': ");
      }
      scanf("%d",&TEMP2);
      }
      if(1==turn)
      {
      switch (TEMP2)
      {
      case 1:GRID[1][1]='x';
      break;
      case 2:GRID[1][3]='x';
      break;
      case 3:GRID[1][5]='x';
      break;
      case 4:GRID[3][1]='x';
      break;
      case 5:GRID[3][3]='x';
      break;
      case 6:GRID[3][5]='x';
      break;
      case 7:GRID[5][1]='x';
      break;
      case 8:GRID[5][3]='x';
      break;
      case 9:GRID[5][5]='x';
      break;
      }
      }
      else
      {
      switch (TEMP2)
      {
      case 1:GRID[1][1]='o';
      break;
      case 2:GRID[1][3]='o';
      break;
      case 3:GRID[1][5]='o';
      break;
      case 4:GRID[3][1]='o';
      break;
      case 5:GRID[3][3]='o';
      break;
      case 6:GRID[3][5]='o';
      break;
      case 7:GRID[5][1]='o';
      break;
      case 8:GRID[5][3]='o';
      break;
      case 9:GRID[5][5]='o';
      break;
      }
      }
      }
      //function to find the number of available available_spots
      int available_spots(char (*GRID)[7])
      {
      int spots=0;
      for(int i=1;i<6;i=i+2)
      for(int j=1;j<6;j=j+2)
      {
      if (GRID[i][j]==' ')
      spots++;
      }
      return spots;
      }
      //function to check for win condition after every move from user and computer
      int terminal_state(char (*GRID)[7])
      {
      if (((GRID[1][1]=='o')&&(GRID[1][3]=='o'))&&((GRID[1][3]=='o')&&(GRID[1][5]=='o')))
      {
      return -10;
      }
      else if (((GRID[3][1]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[3][5]=='o')))
      {
      return -10;
      }
      else if (((GRID[5][1]=='o')&&(GRID[5][3]=='o'))&&((GRID[5][3]=='o')&&(GRID[5][5]=='o')))
      {
      return -10;
      }
      else if (((GRID[1][1]=='o')&&(GRID[3][1]=='o'))&&((GRID[3][1]=='o')&&(GRID[5][1]=='o')))
      {
      return -10;
      }
      else if (((GRID[1][3]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[5][3]=='o')))
      {
      return -10;
      }
      else if (((GRID[1][5]=='o')&&(GRID[3][5]=='o'))&&((GRID[3][5]=='o')&&(GRID[5][5]=='o')))
      {
      return -10;
      }
      else if (((GRID[1][1]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[5][5]=='o')))
      {
      return -10;
      }
      else if (((GRID[1][5]=='o')&&(GRID[3][3]=='o'))&&((GRID[3][3]=='o')&&(GRID[5][1]=='o')))
      {
      return -10;
      }
      if (((GRID[1][1]=='x')&&(GRID[1][3]=='x'))&&((GRID[1][3]=='x')&&(GRID[1][5]=='x')))
      {
      return 10;
      }
      else if (((GRID[3][1]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[3][5]=='x')))
      {
      return 10;
      }
      else if (((GRID[5][1]=='x')&&(GRID[5][3]=='x'))&&((GRID[5][3]=='x')&&(GRID[5][5]=='x')))
      {
      return 10;
      }
      else if (((GRID[1][1]=='x')&&(GRID[3][1]=='x'))&&((GRID[3][1]=='x')&&(GRID[5][1]=='x')))
      {
      return 10;
      }
      else if (((GRID[1][3]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[5][3]=='x')))
      {
      return 10;
      }
      else if (((GRID[1][5]=='x')&&(GRID[3][5]=='x'))&&((GRID[3][5]=='x')&&(GRID[5][5]=='x')))
      {
      return 10;
      }
      else if (((GRID[1][1]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[5][5]=='x')))
      {
      return 10;
      }
      else if (((GRID[1][5]=='x')&&(GRID[3][3]=='x'))&&((GRID[3][3]=='x')&&(GRID[5][1]=='x')))
      {
      return 10;
      }
      else if(available_spots(GRID)==0)
      return 0;
      }
      /*function of minimax algorithm that is recursive*/
      int minimax(char (*GRID)[7],int turn)
      {
      //
      int best;
      if(terminal_state(GRID)==10)
      return 10;
      if(terminal_state(GRID)==-10)
      return -10;
      if(terminal_state(GRID)==0)
      return 0;
      //
      if(0==turn)
      {
      int i,j;
      int temp;
      best=1000;
      for(int i=1;i<6;i=i+2)
      {
      for(int j=1;j<6;j=j+2)
      {
      if(GRID[i][j]==' ')
      {
      GRID[i][j]='o';
      temp=minimax(GRID,1);
      best=MIN(temp,best);
      GRID[i][j]=' ';
      }
      }
      }
      return best;
      }
      else if(1==turn)
      {
      int i,j;
      int temp;
      best=-1000;
      for(i=1;i<6;i=i+2)
      {
      for(j=1;j<6;j=j+2)
      {
      if(GRID[i][j]==' ')
      {
      GRID[i][j]='x';
      temp=minimax(GRID,0);
      best=MAX(temp,best);
      GRID[i][j]=' ';
      }
      }
      }
      return best;
      }
      }
      //the following function returns the best move
      void computer_position(char (*GRID)[7],int turn)
      {
      if(0==turn)
      {
      int sample=1000;
      int computer_move[3];
      computer_move[0]=sample;
      for(int i=1;i<6;i=i+2)
      {
      for(int j=1;j<6;j=j+2)
      {
      if(GRID[i][j]==' ')
      {
      GRID[i][j]='o';
      sample=minimax(GRID,!turn);
      if(sample<computer_move[0])
      {
      computer_move[0]=sample;
      computer_move[1]=i;
      computer_move[2]=j;
      }
      GRID[i][j]=' ';
      }
      }
      }
      GRID[computer_move[1]][computer_move[2]]='o';
      }
      else
      {
      int sample=-1000;
      int computer_move[3];
      computer_move[0]=sample;
      for(int i=1;i<6;i=i+2)
      {
      for(int j=1;j<6;j=j+2)
      {
      if(GRID[i][j]==' ')
      {
      GRID[i][j]='x';
      sample=minimax(GRID,!turn);
      if(sample>computer_move[0])
      {
      computer_move[0]=sample;
      computer_move[1]=i;
      computer_move[2]=j;
      }
      GRID[i][j]=' ';
      }
      }
      }
      GRID[computer_move[1]][computer_move[2]]='x';
      }
      }
      /*main function*/
      int main()
      {
      //int USR_INPUT,RESULT;
      char GRID[7][7]={
      {'-','-','-','-','-','-','-'},
      {'|',' ','|',' ','|',' ','|'},
      {'-','-','-','-','-','-','-'},
      {'|',' ','|',' ','|',' ','|'},
      {'-','-','-','-','-','-','-'},
      {'|',' ','|',' ','|',' ','|'},
      {'-','-','-','-','-','-','-'}
      };
      int turn;
      //get the turn from the user
      printf("nDo you want to go first as 'x', or second as 'o'?n");
      printf("nEnter 1 for 'x' or 0 for 'o':");
      scanf("%d",&turn);
      while((turn!=0)&&(turn!=1))
      {
      printf("nInvalid value for turn!n");
      printf("nDo you want to go first as 'x', or second as 'o'?n");
      printf("nEnter 1 for 'x' or 0 for 'o':");
      scanf("%d",&turn);
      }
      //when no spots are available or a win condition is obtained
      if(1==turn)
      {
      while(available_spots(GRID)!=0)
      {
      print(GRID);
      get_input(GRID,turn);
      if(terminal_state(GRID)==10)
      {
      print(GRID);
      printf("nYou have wonnn");
      return 0;
      }else if (terminal_state(GRID)==-10) {
      print(GRID);
      printf("nComputer has wonnn");
      return 0;
      }else if (terminal_state(GRID)==0) {
      print(GRID);
      printf("nThe game is a drawnn");
      return 0;
      }
      computer_position(GRID,!turn);
      }
      }
      else
      {
      while(available_spots(GRID)!=0)
      {
      computer_position(GRID,!turn);
      if(terminal_state(GRID)==-10)
      {
      print(GRID);
      printf("nYou have wonnn");
      return 0;
      }else if (terminal_state(GRID)==10) {
      print(GRID);
      printf("nComputer has wonnn");
      return 0;
      }else if (terminal_state(GRID)==0) {
      print(GRID);
      printf("nThe game is a drawnn");
      return 0;
      }
      print(GRID);
      get_input(GRID,turn);
      }
      }
      }






      beginner c tic-tac-toe ai






      share|improve this question









      New contributor




      Udhay Sankar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      Udhay Sankar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited 13 mins ago









      200_success

      130k16153417




      130k16153417






      New contributor




      Udhay Sankar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 11 hours ago









      Udhay SankarUdhay Sankar

      161




      161




      New contributor




      Udhay Sankar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Udhay Sankar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Udhay Sankar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






















          1 Answer
          1






          active

          oldest

          votes


















          3












          $begingroup$

          Please add some space to your code - it can be hard to read when it's all crammed together.





          Use ALL_CAPS names for preprocessor macros, but not for ordinary variables or functions. It's important to be able to tell them apart (because macros don't obey the rules of scope, for instance).





          The game grid is 7✕7 = 49 elements, but only 3✕3 = 9 of those elements are actually storing game state - that's only ⅕. The rest are filled with presentation constants that never need to be changed, and can be produced when printing (they don't need to be stored).





          Look at this repetition:




              case 1:
          if (GRID[1][1]=='x'||GRID[1][1]=='o')
          {
          printf("nPosition already occupied!!!n");
          return 0;
          }
          else
          return 1;
          break;
          case 2:
          if (GRID[1][3]=='x'||GRID[1][3]=='o')
          {
          printf("nPosition already occupied!!!n");
          return 0;
          }
          else
          return 1;
          break;



          Here, we're doing two things: mapping the input number to a position, and checking whether it's occupied. If we separate those computations, we'll find we don't need to repeat the tests.



          Something like this:



          if (input < 1 || input > 9) {
          /* out of range */
          return 0;
          }

          --input; /* now 0-8 */
          int x = input % 3;
          int y = input / 3;

          char occupier = grid[2*y+1][2*x+1];

          if (occupier != ' ') {
          printf("nPosition already occupied!!!n");
          return 0;
          } else {
          return 1;
          }


          Similar techniques can reduce duplication elsewhere in the program.





          Enable more warning messages in your compiler. It will help you spot errors such as these:



          gcc -std=c17 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds      -Wconversion    214336.c    -o 214336
          214336.c: In function ‘minimax’:
          214336.c:287:11: warning: unused variable ‘j’ [-Wunused-variable]
          int i,j;
          ^
          214336.c:287:9: warning: unused variable ‘i’ [-Wunused-variable]
          int i,j;
          ^
          214336.c: In function ‘valid’:
          214336.c:114:1: warning: control reaches end of non-void function [-Wreturn-type]
          }
          ^
          214336.c: In function ‘terminal_state’:
          214336.c:272:1: warning: control reaches end of non-void function [-Wreturn-type]
          }
          ^
          214336.c: In function ‘minimax’:
          214336.c:325:1: warning: control reaches end of non-void function [-Wreturn-type]
          }
          ^





          share|improve this answer









          $endgroup$













            Your Answer





            StackExchange.ifUsing("editor", function () {
            return StackExchange.using("mathjaxEditing", function () {
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            });
            });
            }, "mathjax-editing");

            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "196"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });






            Udhay Sankar is a new contributor. Be nice, and check out our Code of Conduct.










            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214336%2fa-command-line-unbeatable-tic-tac-toe-written-in-c%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            3












            $begingroup$

            Please add some space to your code - it can be hard to read when it's all crammed together.





            Use ALL_CAPS names for preprocessor macros, but not for ordinary variables or functions. It's important to be able to tell them apart (because macros don't obey the rules of scope, for instance).





            The game grid is 7✕7 = 49 elements, but only 3✕3 = 9 of those elements are actually storing game state - that's only ⅕. The rest are filled with presentation constants that never need to be changed, and can be produced when printing (they don't need to be stored).





            Look at this repetition:




                case 1:
            if (GRID[1][1]=='x'||GRID[1][1]=='o')
            {
            printf("nPosition already occupied!!!n");
            return 0;
            }
            else
            return 1;
            break;
            case 2:
            if (GRID[1][3]=='x'||GRID[1][3]=='o')
            {
            printf("nPosition already occupied!!!n");
            return 0;
            }
            else
            return 1;
            break;



            Here, we're doing two things: mapping the input number to a position, and checking whether it's occupied. If we separate those computations, we'll find we don't need to repeat the tests.



            Something like this:



            if (input < 1 || input > 9) {
            /* out of range */
            return 0;
            }

            --input; /* now 0-8 */
            int x = input % 3;
            int y = input / 3;

            char occupier = grid[2*y+1][2*x+1];

            if (occupier != ' ') {
            printf("nPosition already occupied!!!n");
            return 0;
            } else {
            return 1;
            }


            Similar techniques can reduce duplication elsewhere in the program.





            Enable more warning messages in your compiler. It will help you spot errors such as these:



            gcc -std=c17 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds      -Wconversion    214336.c    -o 214336
            214336.c: In function ‘minimax’:
            214336.c:287:11: warning: unused variable ‘j’ [-Wunused-variable]
            int i,j;
            ^
            214336.c:287:9: warning: unused variable ‘i’ [-Wunused-variable]
            int i,j;
            ^
            214336.c: In function ‘valid’:
            214336.c:114:1: warning: control reaches end of non-void function [-Wreturn-type]
            }
            ^
            214336.c: In function ‘terminal_state’:
            214336.c:272:1: warning: control reaches end of non-void function [-Wreturn-type]
            }
            ^
            214336.c: In function ‘minimax’:
            214336.c:325:1: warning: control reaches end of non-void function [-Wreturn-type]
            }
            ^





            share|improve this answer









            $endgroup$


















              3












              $begingroup$

              Please add some space to your code - it can be hard to read when it's all crammed together.





              Use ALL_CAPS names for preprocessor macros, but not for ordinary variables or functions. It's important to be able to tell them apart (because macros don't obey the rules of scope, for instance).





              The game grid is 7✕7 = 49 elements, but only 3✕3 = 9 of those elements are actually storing game state - that's only ⅕. The rest are filled with presentation constants that never need to be changed, and can be produced when printing (they don't need to be stored).





              Look at this repetition:




                  case 1:
              if (GRID[1][1]=='x'||GRID[1][1]=='o')
              {
              printf("nPosition already occupied!!!n");
              return 0;
              }
              else
              return 1;
              break;
              case 2:
              if (GRID[1][3]=='x'||GRID[1][3]=='o')
              {
              printf("nPosition already occupied!!!n");
              return 0;
              }
              else
              return 1;
              break;



              Here, we're doing two things: mapping the input number to a position, and checking whether it's occupied. If we separate those computations, we'll find we don't need to repeat the tests.



              Something like this:



              if (input < 1 || input > 9) {
              /* out of range */
              return 0;
              }

              --input; /* now 0-8 */
              int x = input % 3;
              int y = input / 3;

              char occupier = grid[2*y+1][2*x+1];

              if (occupier != ' ') {
              printf("nPosition already occupied!!!n");
              return 0;
              } else {
              return 1;
              }


              Similar techniques can reduce duplication elsewhere in the program.





              Enable more warning messages in your compiler. It will help you spot errors such as these:



              gcc -std=c17 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds      -Wconversion    214336.c    -o 214336
              214336.c: In function ‘minimax’:
              214336.c:287:11: warning: unused variable ‘j’ [-Wunused-variable]
              int i,j;
              ^
              214336.c:287:9: warning: unused variable ‘i’ [-Wunused-variable]
              int i,j;
              ^
              214336.c: In function ‘valid’:
              214336.c:114:1: warning: control reaches end of non-void function [-Wreturn-type]
              }
              ^
              214336.c: In function ‘terminal_state’:
              214336.c:272:1: warning: control reaches end of non-void function [-Wreturn-type]
              }
              ^
              214336.c: In function ‘minimax’:
              214336.c:325:1: warning: control reaches end of non-void function [-Wreturn-type]
              }
              ^





              share|improve this answer









              $endgroup$
















                3












                3








                3





                $begingroup$

                Please add some space to your code - it can be hard to read when it's all crammed together.





                Use ALL_CAPS names for preprocessor macros, but not for ordinary variables or functions. It's important to be able to tell them apart (because macros don't obey the rules of scope, for instance).





                The game grid is 7✕7 = 49 elements, but only 3✕3 = 9 of those elements are actually storing game state - that's only ⅕. The rest are filled with presentation constants that never need to be changed, and can be produced when printing (they don't need to be stored).





                Look at this repetition:




                    case 1:
                if (GRID[1][1]=='x'||GRID[1][1]=='o')
                {
                printf("nPosition already occupied!!!n");
                return 0;
                }
                else
                return 1;
                break;
                case 2:
                if (GRID[1][3]=='x'||GRID[1][3]=='o')
                {
                printf("nPosition already occupied!!!n");
                return 0;
                }
                else
                return 1;
                break;



                Here, we're doing two things: mapping the input number to a position, and checking whether it's occupied. If we separate those computations, we'll find we don't need to repeat the tests.



                Something like this:



                if (input < 1 || input > 9) {
                /* out of range */
                return 0;
                }

                --input; /* now 0-8 */
                int x = input % 3;
                int y = input / 3;

                char occupier = grid[2*y+1][2*x+1];

                if (occupier != ' ') {
                printf("nPosition already occupied!!!n");
                return 0;
                } else {
                return 1;
                }


                Similar techniques can reduce duplication elsewhere in the program.





                Enable more warning messages in your compiler. It will help you spot errors such as these:



                gcc -std=c17 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds      -Wconversion    214336.c    -o 214336
                214336.c: In function ‘minimax’:
                214336.c:287:11: warning: unused variable ‘j’ [-Wunused-variable]
                int i,j;
                ^
                214336.c:287:9: warning: unused variable ‘i’ [-Wunused-variable]
                int i,j;
                ^
                214336.c: In function ‘valid’:
                214336.c:114:1: warning: control reaches end of non-void function [-Wreturn-type]
                }
                ^
                214336.c: In function ‘terminal_state’:
                214336.c:272:1: warning: control reaches end of non-void function [-Wreturn-type]
                }
                ^
                214336.c: In function ‘minimax’:
                214336.c:325:1: warning: control reaches end of non-void function [-Wreturn-type]
                }
                ^





                share|improve this answer









                $endgroup$



                Please add some space to your code - it can be hard to read when it's all crammed together.





                Use ALL_CAPS names for preprocessor macros, but not for ordinary variables or functions. It's important to be able to tell them apart (because macros don't obey the rules of scope, for instance).





                The game grid is 7✕7 = 49 elements, but only 3✕3 = 9 of those elements are actually storing game state - that's only ⅕. The rest are filled with presentation constants that never need to be changed, and can be produced when printing (they don't need to be stored).





                Look at this repetition:




                    case 1:
                if (GRID[1][1]=='x'||GRID[1][1]=='o')
                {
                printf("nPosition already occupied!!!n");
                return 0;
                }
                else
                return 1;
                break;
                case 2:
                if (GRID[1][3]=='x'||GRID[1][3]=='o')
                {
                printf("nPosition already occupied!!!n");
                return 0;
                }
                else
                return 1;
                break;



                Here, we're doing two things: mapping the input number to a position, and checking whether it's occupied. If we separate those computations, we'll find we don't need to repeat the tests.



                Something like this:



                if (input < 1 || input > 9) {
                /* out of range */
                return 0;
                }

                --input; /* now 0-8 */
                int x = input % 3;
                int y = input / 3;

                char occupier = grid[2*y+1][2*x+1];

                if (occupier != ' ') {
                printf("nPosition already occupied!!!n");
                return 0;
                } else {
                return 1;
                }


                Similar techniques can reduce duplication elsewhere in the program.





                Enable more warning messages in your compiler. It will help you spot errors such as these:



                gcc -std=c17 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds      -Wconversion    214336.c    -o 214336
                214336.c: In function ‘minimax’:
                214336.c:287:11: warning: unused variable ‘j’ [-Wunused-variable]
                int i,j;
                ^
                214336.c:287:9: warning: unused variable ‘i’ [-Wunused-variable]
                int i,j;
                ^
                214336.c: In function ‘valid’:
                214336.c:114:1: warning: control reaches end of non-void function [-Wreturn-type]
                }
                ^
                214336.c: In function ‘terminal_state’:
                214336.c:272:1: warning: control reaches end of non-void function [-Wreturn-type]
                }
                ^
                214336.c: In function ‘minimax’:
                214336.c:325:1: warning: control reaches end of non-void function [-Wreturn-type]
                }
                ^






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered 11 hours ago









                Toby SpeightToby Speight

                24.9k740115




                24.9k740115






















                    Udhay Sankar is a new contributor. Be nice, and check out our Code of Conduct.










                    draft saved

                    draft discarded


















                    Udhay Sankar is a new contributor. Be nice, and check out our Code of Conduct.













                    Udhay Sankar is a new contributor. Be nice, and check out our Code of Conduct.












                    Udhay Sankar is a new contributor. Be nice, and check out our Code of Conduct.
















                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    Use MathJax to format equations. MathJax reference.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214336%2fa-command-line-unbeatable-tic-tac-toe-written-in-c%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Сан-Квентин

                    Алькесар

                    Josef Freinademetz