Demo entry 6318666

tic-tac-toe

   

Submitted by anonymous on Nov 07, 2016 at 12:05
Language: C++. Code size: 6.9 kB.

#include<iostream>
using namespace std;
int p1_dec(int**);     //Player 1 decision function
int p2_dec(int**);     //Player 2 decision function
int eval(int**);       //Validation code.
bool isfull(int**);
int depth=1;           //A global variable to map depth of the recursion trace 
int main()
{
  //The double pointer holds the matrix
  //p and q are the coordinates of player 2's move
  //dec is the decision of the code
  int **a,p,q,dec,turn=0;
  cout<<"Enter which player you wish to play:\n1. For player 1\n2. For player 2\n";
  cin>>turn;
  cout<<"The computer's piece is denoted by '1' and player's piece will be denoted by '2'\n";
  //Below code initializes the matrix to 0
  //We have used new and delete to enable handling the matrix as a pointer to a pointer,
  //making it easy to pass as a parameter
  
  a = new int*[3];
  for (int i=0;i<3;i++)
    a[i] = new int[3];
  for(int i=0;i<3;i++)
    {
      for(int j=0;j<3;j++)
	a[i][j]=0;            //Initializing the matrix to 0
    }


  
  do
    {
      int t;
      depth=1;                //Resetting the depth to 1 after every iteration
      if(turn==1)             //If turn is 2, skip the first input from the user
	{
	  cin>>p>>q;          //Accepting the opponents move as coordinates x,y
	  a[p-1][q-1]=2;      //Arrays are 0 indexed. So subtracting 1 from both values 
	  for(int i=0;i<3;i++)
	    {
	      for(int j=0;j<3;j++)
		{
		  cout<<a[i][j]<<" ";
		}
	      cout<<endl;
	    }
	  t=eval(a);
	  if(t!=0 || isfull(a))             //If termination condition is encountered
	    break;	  
	}
      turn=1;        //If turn was 2, after skipping the first input, make turn 1 to continue normal game
      dec=p1_dec(a);           //Make a decision      
      a[dec/3][dec%3]=1;       //Player 1's move denoted by 1
      cout<<endl<<dec/3+1<<dec%3+1<<endl;
      t=eval(a); 
      for(int i=0;i<3;i++)
	{
	  for(int j=0;j<3;j++)
	    {
	      cout<<a[i][j]<<" ";
	    }
	  cout<<endl;
	} 
      if(t!=0 || isfull(a))    //If terminating condition has occured
	break;         
    }
  while(1);
  for(int i=0;i<3;i++)         //Deallocating memory
    delete[] a[i];
  delete[] a;
  return 0;
}


//Function to find most feasible move for player 1
int p1_dec(int**a)
{
  int gain,ref=-10,move,count=0;    //Count to check total number of possible playable moves
  for(int i=0;i<3;i++)              //The 2 for loops are for traversing the matrix
    {
      for(int j=0;j<3;j++)
	{
	  if(a[i][j]==0)            //Condition to check if the cell hasn't been played yet 
	    {
	      count++;              //increment count for each playable move option
	      a[i][j]=1;            //Trying out a move. Setting the cell to 1  
	      gain=eval(a);         //Evaluating the grid
	      if(gain==10)          //10 is winning condition for player 1
		{
		  if(depth==1)      //If the depth is 1, meaning that one level above is the main program itself, then return the move
		    return i*3+j;
		  else              //For any other depth return the gain. And reset the move because it hasn't been played yet.
		    {
		      a[i][j]=0;
		      return 10;
		    }
		}
	      else if(gain==0)           //If move is inconclusive for current depth, we need to go one level lower
		{
		  int temp;      
		  depth++;          //Increment depth to go down one level
		  temp=p2_dec(a);   //One level below is player2's move
		  depth--;          //Decrement depth after coming out
		  a[i][j]=0;        //Reset the move
		  if(temp>=ref)     //If the gain returned is greater than the reference value, set it as the new reference.
		    {
		      ref=temp;
		      move=i*3+j;     //Hold the move associated with the new value of gain
		    }
		}
	      else if(gain==-10)    //If move ensures opponents win, ignore it and reset the move 
		{
		  a[i][j]=0;
		}
	    }
	}
    }
  if(count==0)           //If no moves are possible return a gain of 0
    return 0;
  else                   //If no winning moves available return either
    if(depth==1)          
      return move;       //The move held previously 
    else
      return ref;        //Its gain
}
	      
		  
int p2_dec(int**a)
{
  int gain,ref=10,count=0;
  for(int i=0;i<3;i++)       //2 for loops for traversing the matrix
    {
      for(int j=0;j<3;j++)
	{
	  if(a[i][j]==0)         //Condition for blank cell/an unplayed move
	    {
	      count++;       
	      a[i][j]=2;     
	      gain=eval(a);
	      if(gain==-10)      //For player 2, the winning condition has been assinged a weight of -10
		{
		  a[i][j]=0;         //Reset the move
		  return -10;        //Return the gain. Note this function will never be at depth=1.
		}
	      else if(gain==0)   //Prepare to go one level deeper
		{
		  int temp;
		  depth++;
		  temp=p1_dec(a);    //Now its again the first players move
		  depth--;
		  a[i][j]=0;         //Resetting the move
		  if(temp<=ref)    
		    {
		      ref=temp;
		    }
		}
	      else if(gain==10)    //A move ensuring the 1st players win is to be ignored in this function
		a[i][j]=0;             //Resetting the move.
	    }
	}
    }
  if(count==0)                 //Again if no move is left, return 0
    return 0;
  else
    return ref;
}



//Validation code		     
int eval(int **a)
{

  //Prints the matrix each time. Used for debugging purposes
  /*for(int i=0;i<3;i++)
    {
      for(int j=0;j<3;j++)
	{
	  cout<<a[i][j]<<" ";
	}
      cout<<endl;
    }
    cout<<endl;*/

  
  for(int i=0;i<3;i++)
    { //First if-construct checks winning condition for every row
      if((a[i][0]==a[i][1])&&(a[i][1]==a[i][2]))
	{
	  //Checks winning condition for which player
	  if(a[i][0]==1)
	    return 10;
	  else if(a[i][0]==2)
	    return -10;
	}
      //This checks the winning condition for every column
      if((a[0][i]==a[1][i])&&(a[1][i]==a[2][i]))
	{
	  if(a[0][i]==1)
	    return 10;
	  else if(a[0][i]==2)
	    return -10;
	}
    }
  //Checks winning condition for main diagonal 
  if((a[1][1]==a[0][0])&&(a[0][0]==a[2][2]))
    {
      if(a[0][0]==1)
	return 10;
      else if(a[0][0]==2)
	return -10;
    }
  //Checks winning condition for anti-diagonal
  else if((a[0][2]==a[1][1])&&(a[1][1]==a[2][0]))
    {
      if(a[1][1]==1)
	return 10;
      else if(a[1][1]==2)
	return -10;
    }
  return 0;   //If program reaches here, that means no winning conditions are encountered. Hence return 0
}

bool isfull(int **a)            //Function to check if no moves are left
{
  for(int i=0;i<3;i++)
    {
      for(int j=0;j<3;j++)
	{
	  if(a[i][j]==0)        //If an empty cell is obtained return false
	    return false;
	}
    }
  cout<<"Game end\n";
  return true;
}

This snippet took 0.01 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).