#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 circlesconstint midx[9]={50,100,150,50,100,150,50,100,150};
constint midy[9]={150,150,150,200,200,200,250,250,250};
constchar label[9][2]={"1","2","3","4","5","6","7","8","9"};
// ENUMERATED DATATYPESenum turn { human1, human2};
enumbool { false, true};
// FUNCTIONS USEDvoid IllegalMove(int type); // validates the entered cell no.void DeclareWinner(turn player); // declare the winnervoid 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 movesint p2[9]; // cells marked with player2 moves
turn player; // human1 / human2 / machine to play nextint p1_turns; // number of turns p1 hadint p2_turns; // number of turns p2 hadpublic:
Board(); // constructorbool IsWin(void); // is there a win in this position?bool IsLegal(int pos); // is the move legal?void MakeMove(int pos); // make a movevoid SetPlayer(turn p); // swap player1 and player2
turn WhoPlays(void); // returns the player currently playingint GetTurn(void); // get the turn player is takingvoid plot_board(void); // displays the boardvoid fill_cell(constint pos, constint player); // displays boards statusvoid 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 arrayelse
ptr=p2;
// check for 3 in a Row or 3 in a Columnif( (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]);
returntrue;
}
returnfalse;
}// end IsWin()bool Board::IsLegal(int pos)
{
if(p1[pos-1]==empty && p2[pos-1]==empty)
returntrue;
returnfalse;
}// 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 GetTurnvoid 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 circlefor(int i=0,j=0; i<9,j<9; i++,j++)
circle(midx[i],midy[i],radius);
// fill the circles with black colourfor(i=0,j=0; i<9,j<9; i++,j++)
{
setfillstyle(SOLID_FILL,WHITE);
floodfill(midx[i],midy[i],BLUE);
}// end for// label each circlefor(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(constint pos, constint 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);
elseif(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 notint count; // counts total number of movesconst xcoord[5]={57,60,63,66,69}; // coordinates where player is gonnaconst ycoord[2]={13,16}; // enter the cell no.int p_turn; // no. of turns player hadint cell_no=0; // cell no. entered by userint x,y;
// request auto detectionint 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 askingwhile(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 gameif(p_turn>=2)
if(Board1.IsWin())
{
DeclareWinner(Turn);
count=10;
}
// swap playersif(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 drawif(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()