-2

I'm coding a game of tic tac toe in C. Here's the logic. The User goes first, selects a slot. The positions of the slot are calculated using simple formulae. Then the selected slot is filled. Next, the computer selects a slot, randomly. For this, i've used the rand() function, in stdlib.h. Initially, all elements of the 3x3 matrix are set at 0. My problem is, even if all the other elements are 0, and the user selects slot 5 or slot 9, the user wins. Same thing for the comp also. Here's my code-

#include<stdio.h>
#include<stdlib.h>
int check(int[][3]);
void print(int[][3]);
main()
{
 int i,j,match[3][3]={0},posx,posy,comp_posx,comp_posy,fill=0,slot,user_score=0,comp_score=0;
 char ch;
 srand(time(NULL));
 do
 {
  while(fill<9)
  {
   printf("\nEnter the slot you want to fill.\n");
   scanf("%d",&slot);
   if (slot > 9)
   {
    printf("Error!\nSlot value cannot exceed 9.\n");
    continue;
   }
   else if( slot >= 1&&slot <=3)
   {
    posx=0;
    posy=slot-1;
   }
   else if (slot >= 4 && slot <= 6)
   {
    posx=1;
    posy=slot-4;
   }
   else
   {
    posx=2;
    posy=slot-7;
   }
   if (match[posx][posy] == 0)
   {
    match[posx][posy]=1;
    fill++;
    check(match);
    if(check(match)==1)
    {
     printf("The user wins!\n");
     user_score++;
     print(match);
     break;
    }
    else if(check(match)==-1)
    {
     printf("The computer wins!\n");
     comp_score++;
     print(match);
    }
    else
    {
     if(fill==9)
     {
      printf("It's a draw!\n");
      print(match);
      break;
     }
     else
     {
      printf(" ");
     }
    }
   }
   else
   {
    printf("Sorry! This slot is already filled.\nPlease pick another slot.\n");
    continue;
   }
   label:
   comp_posx=rand()%3;
   comp_posy=rand()%3;
   if(match[comp_posx][comp_posy]==0)
   {
    match[comp_posx][comp_posy]=-1;
    fill++;
    check(match);
    if (check(match)==1)
    {
     printf("The user wins!\n");
     user_score++;
     print(match);
     break;
    }
    else if(check(match)==-1)
    {
     printf("The computer wins!\n");
     comp_score++;
     print(match);
     break;
    }
    else
    {
     if (fill==9)
     {
      printf("It's a draw!\n");
      print(match);
      break;
     }
     else
     {
      printf(" ");
     }
    }
   }
   else
   goto label;
   for(i=0;i<3;i++)
   {
    printf("\n");
    for(j=0;j<3;j++)
    {
    printf("%d\t",match[i][j]);
    }
   }
  }
  for(i=0;i<3;i++)
  {
   for(j=0;j<3;j++)
   {
    match[i][j]=0;
   }
  }
  printf("Continue? Y/N\n");
  scanf("%c %c",&ch,&ch);
 }
 while(ch=='y'||ch=='Y');
 printf("FINAL SCORES>>\nUser=%d\nComputer=%d\n",user_score,comp_score);
}
int check(int match[][3])
{
 int i,j;
 if( match[2][0]==match[1][1] && match[1][1]==match[0][2] )
 {
  if (match[0][2]==1)
  return 1;
  else if (match[0][2]==-1)
  return -1;
  else
  printf(" ");
 }
 for(i=0;i<3;i++)
 {
  if (match[i][0]==match[i][1]&&match[i][1]==match[i][2])
  {
   if(match[i][1]==1)
   return 1;
   else if(match[i][1]==-1)
   return -1;
   else
   continue;
  }
 }
 for(j=0;j<3;j++)
 {
  if(match[0][j]==match[1][j]&&match[0][j]==match[2][j])
  {
   if (match[0][j]==1)
   return 1;
   else if(match[0][j]==-1)
   return -1;
   else
   continue;
  }
 }
 for (i=0;i<1;i++)
 {
  if(match[i][i]==match[i+1][i+1]&&match[i][i]==match[i+2][i+2])
  {
   if (match[i][i]==1)
   return 1;
   else if (match[i][i]==-1)       return -1;
  else continue;
  }
 }
}
 void print(int match[][3])
 {
  int i,j;
  for(i=0;i<3;i++)
  {
   printf("\n");
   for(j=0;j<3;j++)
   {
    printf("%d\t",match[i][j]);
   }
  }
 }

Can You suggest changes in the code, so that i won't have those problems?

Mahesh Kumar
  • 9
  • 1
  • 1
  • 2
  • While that's waaay too much code to parse after 2 hours of sleep and no coffee yet, I'd suggest removing the "user wins" cases, it gives the (perhaps) wrong impression that you don't understand the game. – Blindy May 09 '12 at 14:30
  • 4
    Now might be a good time to learn to use a debugger so that you can step through the code and see where the problems are. – Paul R May 09 '12 at 14:31
  • And for heaven's sake get that `goto` out of there. Learn to indent consistently and your code will be easier to read. – Adam Casey May 09 '12 at 16:29

2 Answers2

1

This code has a lot of mess, but the reason for your problem is that you don't return value (or, in other words, return garbage value) from check if nobody wins. Add the line return 0; at the end of check.

asaelr
  • 5,438
  • 1
  • 16
  • 22
  • There appears to be another problem. 'fill' is supposed to be incremented every time the user or the computer fills any slot, and the condition for a draw is '(fill==9)'. But the game results in a draw even when only 4 slots are filled. And after a draw, the computer asks the question 'Continue? Y/N'. If I enter Y, the comp keeps asking the same question again and again. It's something like an infinite loop. – Mahesh Kumar May 09 '12 at 15:05
  • Thanks mate. Found the problem. just added 'fill=0;' at the end of all the game ending conditions. and added return 0; at the end of check(). :) – Mahesh Kumar May 09 '12 at 15:16
1

I cant suggest a solution to your code, but a solution in the implementation. I once had to implement a TicTacToe in C, and I ended up using something similar to a MiniMax algorithm, you can find it here at github.

With a TicTacToe game you have 9! (362880) possible states for the game. Each state represents a given combination of X and O in the board. Those states can represent an "invalid state" (that is, you can never reach that state by playing), a "tie", a "X wins", or "O wins".

Since you have a relatively small amount of possible states, you can calculate all those possible states by playing each possible move (I did this when the game initializes, since it is a small amount of work to do and was not concerned about performance), and relate an initial move with their possible next moves.

This wil give you a tree that, given an initial move, will lead you to a tie, a win, or a lose scenario (depending of course of who is X and who is O). Once you reach that state, you can propagate this result up to the very first move.

As a result, when the human player makes a move, the computer will just be following this tree of possible moves, always playing what gives a result of "win" or "tie", but never a "lose". It's just a state machine that changes state with each move. The human changes the state by playing, and the computer chooses its next state by playing a move that will redirect the game to a final state of win (from the computer perspective) or a tie if it's not possible to win.

So in essence, this is a "perfect tic tac toe player". You wont be able to beat it. If you play flawlessly, you can tie the match, but never win.

marcelog
  • 7,062
  • 1
  • 33
  • 46