C++ Programming Blog

 
 
 
#include<iostream.h>
#include<graphics.h>
#include<stdlib.h>
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<dos.h>

// MACROS USED
#define full 1
#define empty 0
#define radius 15
#define OutOfRange 1
#define OccupiedCell 2

// CONSTANTS ... x,y coordinates and labels for circles
const int midx[9]={50,100,150,50,100,150,50,100,150};
const int midy[9]={150,150,150,200,200,200,250,250,250};
const char label[9][2]={\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"};

// ENUMERATED DATATYPES
enum turn { human1, human2};
enum bool { false, true};

// FUNCTIONS USED
void IllegalMove(int type);        // validates the entered cell no.
void DeclareWinner(turn player);    // declare the winner

void IllegalMove(int type)
{
   int x;
   x=getmaxx();
   setcolor(BLACK);

   settextjustify(CENTER_TEXT, CENTER_TEXT);
   settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);

   outtextxy(x/2-10,375,\"Illegal Move !!! Enter Again ...\");
   if(type==OutOfRange)
      outtextxy(x/2-10,400,\"Invalid Cell Number\");
   else
      outtextxy(x/2-10,400,\"Cell Is Pre-occupied\");
   while(!kbhit())
   {
      setcolor(BROWN);
      outtextxy(x/2-10,375,\"Illegal Move !!! Enter Again ...\");
      if(type==OutOfRange)
     outtextxy(x/2-10,400,\"Invalid Cell Number\");
      else
     outtextxy(x/2-10,400,\"Cell Is Pre-occupied\");
      sound(2000);    delay(20);     nosound();
   }
   setcolor(BLACK);
   outtextxy(getmaxx()/2-10,375,\"Illegal Move !!! Enter Again ...\");
   if(type==OutOfRange)
      outtextxy(x/2-10,400,\"Invalid Cell Number\");
   else
      outtextxy(x/2-10,400,\"Cell Is Pre-occupied\");
}// end IllegalMove()

void DeclareWinner(turn player)
{
   setcolor(WHITE);

   settextjustify(CENTER_TEXT, CENTER_TEXT);
   settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);

   if(player==human1)
      outtextxy(getmaxx()/2-10,375,\"P L A Y E R - 1  is the  W I N N E R !!!\");
   else
      outtextxy(getmaxx()/2-10,375,\"P L A Y E R - 2  is the  W I N N E R !!!\");
   sound(5000); sleep(2); nosound();
}// end DeclareWinner()

//**************************************************************************
// CLASS Board
//**************************************************************************
class Board{
   private:
      int p1[9];        // cells marked with player1 moves
      int p2[9];        // cells marked with player2 moves
      turn player;        // human1 / human2 / machine to play next
      int p1_turns;        // number of turns p1 had
      int p2_turns;        // number of turns p2 had

   public:
      Board();            // constructor
      bool IsWin(void);        // is there a win in this position?
      bool IsLegal(int pos);    // is the move legal?
      void MakeMove(int pos);    // make a move
      void SetPlayer(turn p);    // swap player1 and player2
      turn WhoPlays(void);    // returns the player currently playing
      int GetTurn(void);    // get the turn player is taking
      void plot_board(void);    // displays the board
      void fill_cell(const int pos, const int player); // displays boards status
      void ResetAll(void);       // resets everything
};// end class Board

Board::Board()
{
   for(int i=0; i<9; i++)
   {
      p1[i]=empty;          // reset all cells to empty
      p2[i]=empty;
   }

   player=human1;        // set 1st player as human1

   // set initial turns of p1 and p2 to 0 (zero)
   p1_turns=0;
   p2_turns=0;
}// end Board()

bool Board::IsWin()
{
   int *ptr;

   if(player==human1)
      ptr=p1;                // point to appropriate array
   else
      ptr=p2;

   // check for 3 in a Row or 3 in a Column
   if( (ptr[0] && ptr[1] && ptr[2]) ||    // horizontal
       (ptr[3] && ptr[4] && ptr[5]) ||
       (ptr[6] && ptr[7] && ptr[8]) ||
       (ptr[0] && ptr[3] && ptr[6]) ||    // vertical
       (ptr[1] && ptr[4] && ptr[7]) ||
       (ptr[2] && ptr[5] && ptr[8]) ||
       (ptr[0] && ptr[4] && ptr[8]) ||    // diagonal
       (ptr[2] && ptr[4] && ptr[6]) )
   {
      setcolor(BLACK);
      setlinestyle(SOLID_LINE,1,THICK_WIDTH);

      if(ptr[0] && ptr[1] && ptr[2])
     line(midx[0],midy[0],midx[2],midy[2]);
      if(ptr[3] && ptr[4] && ptr[5])
     line(midx[3],midy[3],midx[5],midy[5]);
      if(ptr[6] && ptr[7] && ptr[8])
     line(midx[6],midy[6],midx[8],midy[8]);

      if(ptr[0] && ptr[3] && ptr[6])
     line(midx[0],midy[0],midx[6],midy[6]);
      if(ptr[1] && ptr[4] && ptr[7])
     line(midx[1],midy[1],midx[7],midy[7]);
      if(ptr[2] && ptr[5] && ptr[8])
     line(midx[2],midy[2],midx[8],midy[8]);

      if(ptr[0] && ptr[4] && ptr[8])
     line(midx[0],midy[0],midx[8],midy[8]);
      if(ptr[2] && ptr[4] && ptr[6])
     line(midx[2],midy[2],midx[6],midy[6]);

      return true;
   }
   return false;
}// end IsWin()

bool Board::IsLegal(int pos)
{
   if(p1[pos-1]==empty && p2[pos-1]==empty)
      return true;
   return false;
}// end IsLegal()

void Board::MakeMove(int pos)
{
   if(player==human1)
   {
      p1[pos-1]=full;
      p1_turns++;
      fill_cell(pos-1,human1);
   }
   else
   {
      p2[pos-1]=full;
      p2_turns++;
      fill_cell(pos-1,2);
   }
}// end MakeMove()

void Board::SetPlayer(turn p)
{
   player=p;
}// end SetPlayer()

turn Board::WhoPlays(void)
{
   return player;
}// end WhoPlays()

int Board::GetTurn()
{
   if(player==human1)
      return p1_turns;
   return p2_turns;
}// end GetTurn

void Board::plot_board()
{
   int maxx,maxy;
   setcolor(BLUE);

   // draw the border
   setlinestyle(SOLID_LINE,1,NORM_WIDTH);
   rectangle(15,115,185,285);
   setfillstyle(SOLID_FILL,BROWN);
   floodfill(30,130,BLUE);

   setlinestyle(SOLID_LINE,1,NORM_WIDTH);
   rectangle(20,120,180,280);
   setfillstyle(SOLID_FILL,YELLOW);
   floodfill(30,130,BLUE);

   setlinestyle(SOLID_LINE,1,THICK_WIDTH);
   rectangle(25,125,175,275);
   setfillstyle(SOLID_FILL,MAGENTA);
   floodfill(30,130,BLUE);

   setlinestyle(SOLID_LINE,1,NORM_WIDTH);

   // draw 9 circle
   for(int i=0,j=0; i<9,j<9; i++,j++)
      circle(midx[i],midy[i],radius);

   // fill the circles with black colour
   for(i=0,j=0; i<9,j<9; i++,j++)
   {
      setfillstyle(SOLID_FILL,WHITE);
      floodfill(midx[i],midy[i],BLUE);
   }// end for

   // label each circle
   for(i=0,j=0; i<9,j<9; i++,j++)
   {
      setcolor(BLUE);
      settextjustify(CENTER_TEXT, CENTER_TEXT);
      settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
      outtextxy(midx[i],midy[i],label[i]);
   }// end for

   // cursor positions where moves will be made
   {
      int px,p1y,p2y;
      maxx=getmaxx();
      maxy=getmaxy();
      setcolor(YELLOW);
      settextjustify(CENTER_TEXT, CENTER_TEXT);
      settextstyle(SANS_SERIF_FONT, HORIZ_DIR, 1);
      outtextxy(maxx/2-10, maxy/2-100, \"M O V E S . . .\");
      setcolor(RED);
      outtextxy(maxx/2+80, maxy/2-40, \"Player1 : |\");

      px=maxx/2+135; p1y=maxy/2-40;
      for(i=1; i<=5; i++)
      {
     outtextxy(px, p1y, \"_|\");
     px += 23;
      }// end for

      setcolor(GREEN);
      outtextxy(maxx/2+80, maxy/2+9, \"Player2 : |\");

      px=maxx/2+135; p2y=maxy/2+9;
      for(i=1; i<=5; i++)
      {
     outtextxy(px, p2y, \"_|\");
     px += 23;
      }// end for
   }
}// end plot_board()

void Board::fill_cell(const int pos, const int player)
{
   int i=pos;
   if(i==3 || i==5 || i==7 || i==8)
   {
      setfillstyle(SOLID_FILL,BLUE);
      floodfill(midx[i]+10,midy[i]+10,BLUE);

      setfillstyle(SOLID_FILL,WHITE);
      floodfill(midx[i]+10,midy[i]+10,MAGENTA);

      setlinestyle(SOLID_LINE,1,NORM_WIDTH);
      setcolor(BLUE);
      circle(midx[i],midy[i],radius);

      if(player==human1)
     setfillstyle(SOLID_FILL,RED);
      else
     setfillstyle(SOLID_FILL,GREEN);

      floodfill(midx[i]+10,midy[i]+10,BLUE);

      settextjustify(CENTER_TEXT, CENTER_TEXT);
      settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
      outtextxy(midx[i],midy[i],label[i]);
   }
   else
   {
      if(player==human1)
     setfillstyle(SOLID_FILL,RED);
      else if(player==2)
     setfillstyle(SOLID_FILL,GREEN);
      floodfill(midx[i]+10,midy[i]+10,BLUE);
   }
}// end fill_cell()

void Board::ResetAll(void)
{
   for(int i=0; i<9; i++)
   {
      p1[i]=empty;          // reset all cells to empty
      p2[i]=empty;
   }

   player=human1;        // set 1st player as human1

   // set initial turns of p1 and p2 to 0 (zero)
   p1_turns=0;
   p2_turns=0;
}// end ResetAll()

//**************************************************************************
// FUNCTION main()
//**************************************************************************
void main(void)
{
   void main_menu(void);

   Board Board1;    // object of class Board
   turn  Turn;        // whos turn is it (human1, human2)
   char ans=\'y\';    // users choice .. continue play or not
   int count;        // counts total number of moves

   const xcoord[5]={57,60,63,66,69};  // coordinates where player is gonna
   const ycoord[2]={13,16};          // enter the cell no.

   int p_turn;        // no. of turns player had
   int cell_no=0;    // cell no. entered by user

   int x,y;

   // request auto detection
   int gmode,gdriver=DETECT,errorcode;

   // initialize graphics and local variables
   initgraph(&gdriver,&gmode,\"\\\\tc\\\\BGI\");

   // read result of initialization
   errorcode = graphresult();
   if (errorcode != grOk)      // an error occurred
   {
      cout<<\"Graphics error: %s\\n\"<< grapherrormsg(errorcode);
      cout<<\"Press any key to exit:\";
      getch();
      exit(1);             // terminate with an error code
   }

   while(tolower(ans)!=\'n\')
   {
      // clear the device (screen)
      cleardevice();

      setcolor(YELLOW);
      settextstyle(DEFAULT_FONT,HORIZ_DIR,1);
      outtextxy(getmaxx()/2-90,4,\"TIC - TAC - TOE\");
      outtextxy(getmaxx()/2-90,16,\"***************\");

      Board1.plot_board();
      count=1;

      while(count<=9)
      {
     Turn=Board1.WhoPlays();
     p_turn=Board1.GetTurn();

     if(Turn==human1)
     {
        setcolor(BLACK);
        settextjustify(CENTER_TEXT, CENTER_TEXT);
        settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
        outtextxy(getmaxx()/2-12,350,\" Player 2\'s Turn . . .\");
        setcolor(YELLOW);
        outtextxy(getmaxx()/2-12,350,\" Player 1\'s Turn . . .\");
        sound(500); delay(50); nosound();
     }
     else
     {
        setcolor(BLACK);
        settextjustify(CENTER_TEXT, CENTER_TEXT);
        settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
        outtextxy(getmaxx()/2-12,350,\" Player 1\'s Turn . . .\");
        setcolor(YELLOW);
        outtextxy(getmaxx()/2-12,350,\" Player 2\'s Turn . . .\");
        sound(1000); delay(50); nosound();
     }

     // get cell number from the player
     gotoxy(xcoord[p_turn],ycoord[Turn]);
     cell_no=getch()-\'0\';

     // check if valid cell no. is entered if not keep on asking
     while(cell_no<1 || cell_no>9)
     {
        IllegalMove(OutOfRange);
        gotoxy(xcoord[p_turn],ycoord[Turn]);
        cell_no=getch()-\'0\';
     }

     // check if the entered cell_no is legal (is not pre-occupied)
     while(Board1.IsLegal(cell_no) == false)
     {
        IllegalMove(OccupiedCell);
        gotoxy(xcoord[p_turn],ycoord[Turn]);
        cell_no=getch()-\'0\';
     }

     // display the cell no at proper position
     gotoxy(xcoord[p_turn],ycoord[Turn]);
     cout<<cell_no;

     // if not fill the cell
     Board1.MakeMove(cell_no);

     // if number of turns of a player exceeds 2 then check if this move
     // made him win or not as atleast 3 moves are required for a player
     // to win this game
     if(p_turn>=2)
        if(Board1.IsWin())
        {
           DeclareWinner(Turn);
           count=10;
        }

     // swap players
     if(Turn==human1)
        Board1.SetPlayer(human2);
     else
        Board1.SetPlayer(human1);

     // increment count
     count++;
      }// end while(count<=9)

      // count = 10 means there is no winner ... game is a draw
      if(count==10)
      {
     setcolor(WHITE);
     outtextxy(getmaxx()/2-10,375,\"I T  I S  A   D R A W !!!\");
     sound(5000); sleep(2); nosound();
      }// end if

      // clear the device (screen)
      cleardevice();

      // ask the user if he wnts to continue
      setcolor(YELLOW);
      settextjustify(CENTER_TEXT, CENTER_TEXT);
      settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
      outtextxy(getmaxx()/2,getmaxy()/2-7,\"DO YOU WANT TO PLAY MORE : (y / n) : \");
      gotoxy(60,15);
      ans=getch();

      while(tolower(ans)!=\'y\' && tolower(ans)!=\'n\')
      {
     setcolor(BLACK);
     settextjustify(CENTER_TEXT, CENTER_TEXT);
     settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
     outtextxy(getmaxx()/2,getmaxy()/2-7,\"DO YOU WANT TO PLAY MORE : (y / n) :   \");
     setcolor(YELLOW);
     outtextxy(getmaxx()/2,getmaxy()/2-7,\"DO YOU WANT TO PLAY MORE : (y / n) : \");
     gotoxy(60,15);
     ans=getch();
      }

      gotoxy(60,15);
      cout<<ans;
      getch();

      if(tolower(ans)==\'y\')
     Board1.ResetAll();
      else
      {
     y=350;
     int bk=getbkcolor();
     for(int i=640;;i--)
     {
        setcolor(BROWN);
        outtextxy(i,y,\"THANK YOU ... HAVE NICE TIME\");
        delay(5);
        if(i==330)
           break;
        else
        {
           setcolor(bk);
           outtextxy(i,y,\"THANK YOU ... HAVE NICE TIME\");
        }
     }// end for
      }// end if(ans==\'y\')
   }// end while(tolower(ans)!=\'n\')

   // get user end key stroke
   getch();

   // clean up ... close the graph
   closegraph();
}// end main()

 
 
Didn't find what you were looking for? Find more on Tic-Tac-Toe game