#include
#include
#include
#include
#include
#define NUM_OF_BLCKS 30
// Symbolic Constants
const int Sys_MAXX=640,Sys_MAXY=480;
const int EMPTY=-1,TRUE=1,FALSE=0;
// Global Variables
int driver=DETECT,mode,error;
// Structure and Class Declarations
class Window;
class Tetris;
class Window
{
private:
int xleft,ytop,xright,ybottom;
int Win_MAXX_Span,Win_MAXY_Span;
int linecolor,bgcolor;
public:
Window()
{
// NULL CONSTRUCTOR
// Assigning in the Sequence :
// Upper_Left(UL) , Lower_Right(LR)
xleft=ytop=0;
xright=Sys_MAXX;ybottom=Sys_MAXY;
Win_MAXX_Span=Sys_MAXX;
Win_MAXY_Span=Sys_MAXY;
linecolor=WHITE;
bgcolor=BLACK;
}
void set_window_par(int[],int,int);
void draw_window(void);
void putstring(char*,int,int);
int get_parameter(int);
};
void Window :: set_window_par(int xyco[],int lc=WHITE,int bgc=BLACK)
{
// Assigning in the Sequence :
// Upper_Left(UL) , Lower_Right(LR)
xleft=xyco[0];
ytop=xyco[1];
xright=xyco[2];
ybottom=xyco[3];
Win_MAXX_Span=xright-xleft;
Win_MAXY_Span=ybottom-ytop;
linecolor=lc;
bgcolor=bgc;
}
void Window :: draw_window(void)
{
setcolor(linecolor);
setlinestyle(0,0,1);
rectangle(xleft,ytop,xright,ybottom);
setfillstyle(1,bgcolor);
floodfill(xleft+1,ytop+1,linecolor);
}
void Window :: putstring(char s[],int xco,int yco)
{
moveto(xco,yco);
settextstyle(TRIPLEX_FONT,HORIZ_DIR,0);
setcolor(WHITE);
setusercharsize(1,2,1,2);
outtext(s);
}
int Window :: get_parameter(int Para_id)
{
int Para_value;
switch(Para_id)
{
case 1: Para_value=xleft;
case 2: Para_value=ytop;
case 3: Para_value=xright;
case 4: Para_value=ybottom;
case 5: Para_value=Win_MAXX_Span;break;
case 6: Para_value=Win_MAXY_Span;break;
case 7: Para_value=linecolor;break;
case 8: Para_value=bgcolor;break;
}
return Para_value;
}
class Tetris
{
private:
int SCode,PCode,TCode;
int **tarr,fbsize,boxtype;
int VXCh,HYCh,fillcol;
Window W1; // Main Window
Window W2; // Side Window
Window W3; // Next_Piece Window
Window W4; // Total Score Window
Window W5; // "Total Lines Destroyed" Window
Window W6; // "Lines Remaining for Game Over" Window
Window W7; // "Level" Window
public:
Tetris(){fbsize=10;fillcol=RED;}
void regulate_play(void);
void initialize_windows(void);
void gen_randshape(void);
void draw_shape(int,int,int,Window*);
int verify_vert_movement(int,int);
}Temp;
void Tetris :: regulate_play(void)
{
int i,j,r;
int channel,y=0;
int prevchan,prevy;
initialize_windows();
/*
Looping as many times as user desires .Each time, one Tetris-Block is
produced randomly at the top of Main Window, slides in Free-fall
and settles at floor of the Tetris Window. In the meanwhile, next piece
is produced randomly(displayed in "Next Piece Window"), which is used as
the Falling Tetris-Block in next iteration.
Please note, here:
'T' - the invoking object from main() is object for Tetris Main Window
'Temp' - Is the Object for "Next Piece Window"
*/
for(r=0;r
if(r==0)
// Very 1st Looping
{
// Hence, Generating shape to be used currently/initially by using Next_Piece Object
Temp.gen_randshape();
// Randomly Selecting the FillColor of the Shape that will be drawn in Main Window
do{
fillcol=random(16);
}while(fillcol==WHITE||fillcol==YELLOW||fillcol==BLACK);
}
else
// Subsequent Iterations
{
// Erasing "Next Piece Window" Graphically
W3.draw_window();
// Erasing "Next Piece Window" Logically (i.e. contents of tarr[][] reset)
Temp.draw_shape(3,3,EMPTY,&W3);
}
// Making the Next Piece Obj contents as the Main Window Piece Obj contents
SCode=Temp.SCode;
PCode=Temp.PCode;
TCode=Temp.TCode;
if(r!=0)
fillcol=Temp.fillcol;
// Generating a Random Next-Piece =>
// This will by above assignments become
// the Current Piece in next iteration
Temp.gen_randshape();
// Randomly Selecting the Channel =>
// One of the (45-3) Vertical Channels that the piece can be launched
// into Free-Fall from Top of the Tetris Window
channel=random(VXCh-3);
// Randomly Selecting the FillColor of the Shape that will be drawn in the Next Piece Window
do{
Temp.fillcol=random(16);
}while(Temp.fillcol==WHITE||Temp.fillcol==YELLOW|| Temp.fillcol==BLACK);
// Drawing the Pieces in Main & Next Piece Window respectively
draw_shape(channel,y,fillcol,&W1);
Temp.draw_shape(3,3,Temp.fillcol,&W3);
// Erasing Piece from Main Window
W1.draw_window();draw_shape(channel,y,EMPTY,&W1);
// Iterating for Current Piece for Free-Fall Motion to floor of Tetris Window
// Here:
// 1. 'j' will control the FREE-FALLING Motion of Tetris Block
// 2. 'channel' will control Horizontal/Sideways Motion of Tetris Block
for(j=y;(j
prevchan=channel;
if(channel==0)
// We have reached the LEFTMOST boundary
// Hence, we may either let 'channel' be or Increment it
// We CANNOT and MUST NOT Decrement 'channel'
{
switch(random(2))
{
case 0:break;
case 1:channel++;
}
}
else if((channel==VXCh-2&&boxtype==23) || (channel==VXCh-3&&boxtype==32) ||
(channel==VXCh-1&&boxtype==14) || (channel==VXCh-4&&boxtype==41) ||(channel==VXCh-2&&boxtype==22))
// We have reached the RIGHTMOST boundary
// Hence, we may either let 'channel' be or Decrement it
// We CANNOT and MUST NOT Increment 'channel'
{
switch(random(2))
{
case 0:break;
case 1:channel--;
}
}
else
// We are somewhere in the middle
// Hence, we may move leftwards, rightwards or stay as it is
{
switch(random(3))
{
case 0:channel++;break;
case 1:channel--;break;
case 2:break;
}
}
if(j!=y)
// Executing for all iterations except the 1st one
{
// Erasing contents of Tetris Main Window Graphically
W1.draw_window();
// Erasing contents of Tetris Main Window Logically
// (i.e. contents of tarr[][] are reset)
draw_shape(prevchan,j-1,EMPTY,&W1);
}
// Drawing the Tetris Block with new values of 'channel' & 'j'
draw_shape(channel,j,fillcol,&W1);
// Testing whether further vertical motion is possible or not
// Depending upon that, we either continue or abandon iterating
if(!verify_vert_movement(channel,j))
break;
delay(1000);
}
}
}
void Tetris :: initialize_windows(void)
{
//TESTING Window Drawings
initgraph(&driver,&mode,"\\TC\\BGI");
error=graphresult();
if(error!=grOk)
{
printf("GRAPHICS ERROR!!");
getch();
exit(1);
}
int xy1[4],xy2[4],xy3[4],xy4[4],xy5[4],xy6[4],xy7[4];
// Setting Window Parameters
xy1[0]=10;xy1[1]=10;
xy1[2]=460;xy1[3]=470;
xy2[0]=480;xy2[1]=10;
xy2[2]=630;xy2[3]=470;
xy3[0]=510;xy3[1]=40;
xy3[2]=600;xy3[3]=120;
xy4[0]=495;xy4[1]=160;
xy4[2]=615;xy4[3]=190;
xy5[0]=495;xy5[1]=230;
xy5[2]=615;xy5[3]=260;
xy6[0]=495;xy6[1]=300;
xy6[2]=615;xy6[3]=330;
xy7[0]=495;xy7[1]=370;
xy7[2]=615;xy7[3]=400;
W1.set_window_par(xy1);
W2.set_window_par(xy2);
W3.set_window_par(xy3);
W4.set_window_par(xy4);
W5.set_window_par(xy5);
W6.set_window_par(xy6);
W7.set_window_par(xy7);
// Initializing for the Main Window Tetris Obj 'T/Temp' the following parameters ;
// 1. No. of Vertical Channels or Vertical Span (VXCh)
// 2. No. of Horizontal Channels ot Horizontal Span (HYCh)
// 3. 2D-Array 'tarr' where -
// tarr[i][j] => 10pixel by 10pixel block, 3-4 of which put together forms ONE Tetris Block
VXCh=W1.get_parameter(5)/fbsize;
HYCh=W1.get_parameter(6)/fbsize;
tarr=(int**)malloc((VXCh)*sizeof(int));
for(int i=0;i
for(int j=0;j
// Initializing for the Next Piece Window Tetris Obj 'Temp' the following parameters ;
// 1. No. of Vertical Channels or Vertical Span (HYCh)
// 2. No. of Horizontal Channels ot Horizontal Span (HYCh)
// 3. 2D-Array 'tarr' where -
// tarr[i][j] => 10pixel by 10pixel block, 3-4 of which put together forms ONE Tetris Block
Temp.VXCh=W3.get_parameter(5)/fbsize;
Temp.HYCh=W3.get_parameter(6)/fbsize;
Temp.tarr=(int**)malloc((Temp.VXCh)*sizeof(int));
for(i=0;i
for(j=0;j
// Drawing all the Windows
W1.draw_window();
W2.draw_window();
W3.draw_window();
W4.draw_window();
W5.draw_window();
W6.draw_window();
W7.draw_window();
// Writing String Entries in Windows
W2.putstring("Next Piece :",495,20);
W2.putstring("SCORE :",495,140);
W2.putstring("Tot. Lines Dest. :",495,210);
W2.putstring("Lines Rem. :",495,280);
W2.putstring("LEVEL :",495,350);
}
void Tetris :: gen_randshape(void)
{
SCode=random(7);
// Scode=0 --> L-Shape , Scode=1 --> InvL-Shape
// Scode=2 --> T-Shape , Scode=3 --> Z-Shape
// Scode=4 --> InvZ-Shape , Scode=5 --> I-Shape
// Scode=6 --> Sq-Shape
// Tcode=0 --> L1 , Tcode=1 --> L2 , Tcode=2 --> L3
// Tcode=3 --> L4 , Tcode=4 --> IL1 , Tcode=5 --> IL2
// Tcode=6 --> IL3 , Tcode=7 --> IL4 , Tcode=8 --> T1
// Tcode=9 --> T2 , Tcode=10 --> T3 , Tcode=11 --> T4
// Tcode=12 --> Z1 , Tcode=13 --> Z2 , Tcode=14 --> IZ1
// Tcode=15 --> IZ2 , Tcode=16 --> I1 , Tcode=17 --> I2
// Tcode=18 --> Sq
/*
NOTE:
1. TCode=0 --> L1 => Normal 'L' Shaped Block, i.e. '|_'
Give Anti-Clockwise Rotation to visualize L2, L3 & L4
2. TCode=4 --> IL1 => Inverted 'L' Shaped Block, i.e. '_|'
Give Anti-Clockwise Rotation to visualize IL2, IL3 & IL4
3. TCode=8 --> T1 => '_|_' Shaped Block
Give Anti-Clockwise Rotation to visualize T2, T3 & T4
_
4. TCode=12 -->Z1 => Normal 'Z' Shaped Block, i.e. ' |_'
Give Anti-Clockwise Rotation to visualize Z2
_
5. TCode=14 -->IZ1 => Inverted 'Z' Shaped Block, i.e. '_| '
Give Anti-Clockwise Rotation to visualize IZ2
6. TCode=16 -->I1 => Long Vertically Standing Block
7. TCode=17 -->I2 => Long Horizontally Sleeping Block
8. TCode=18 -->Sq => Sq Block consisting of 2 by 2 fundamental blocks
Each of the above 8 sets consist of 4 Fundamental Blocks
*/
switch(SCode)
{
case 0:
case 1:
case 2: PCode=random(4);TCode=4*SCode+PCode;break;
case 3: PCode=random(2);TCode=12+PCode;break;
case 4: PCode=random(2);TCode=14+PCode;break;
case 5: PCode=random(2);TCode=16+PCode;break;
case 6: PCode=0;TCode=18;
}
}
void Tetris :: draw_shape(int channel,int y,int DMode,Window *W)
{
if(TCode==18)
{
// Boxtype is 2Col by 2Rows (i.e. 2VXPix by 2HYPix)
boxtype=22;
// Drawing the 4 Blocks Logically
tarr[channel][y]=tarr[channel][y+1]=tarr[channel+1][y]=tarr[channel+1][y+1]=DMode;
}
else if(TCode==16)
{
// Boxtype is 1Col by 4Row (i.e. 1VXPix by 4HYPix)
boxtype=14;
// Drawing the 4 Blocks Logically
tarr[channel][y]=tarr[channel][y+1]=tarr[channel][y+2]=tarr[channel][y+3]=DMode;
}
else if(TCode==17)
{
// Boxtype is 4Col by 1Row (i.e. 4VXPix by 1HYPix)
boxtype=41;
// Drawing the 4 Blocks Logically
tarr[channel][y]=tarr[channel+1][y]=tarr[channel+2][y]=tarr[channel+3][y]=DMode;
}
else if(TCode==0||TCode==2||TCode==4||TCode==6||
TCode==9||TCode==11||TCode==13||TCode==15)
{
// Boxtype is 2Col by 3Rows (i.e. 2VXPix by 3HYPix)
boxtype=23;
if(TCode==0||TCode==6||TCode==9)
// Drawing the Common Blocks Logically
tarr[channel][y]=tarr[channel][y+1]=tarr[channel][y+2]=DMode;
else if(TCode==2||TCode==4||TCode==11)
// Drawing the Common Blocks Logically
tarr[channel+1][y]=tarr[channel+1][y+1]=tarr[channel+1][y+2]=DMode;
else if(TCode==13||TCode==15)
// Drawing the Common Blocks Logically
tarr[channel][y+1]=tarr[channel+1][y+1]=DMode;
}
else if(TCode==1||TCode==3||TCode==5||TCode==7||
TCode==8||TCode==10||TCode==12||TCode==14)
{
// Boxtype is 3Col by 2Rows (i.e. 3VXPix by 2HYPix)
boxtype=32;
if(TCode==1||TCode==7||TCode==8)
// Drawing the Common Blocks Logically
tarr[channel][y+1]=tarr[channel+1][y+1]=tarr[channel+2][y+1]=DMode;
else if(TCode==3||TCode==5||TCode==10)
// Drawing the Common Blocks Logically
tarr[channel][y]=tarr[channel+1][y]=tarr[channel+2][y]=DMode;
else if(TCode==12||TCode==14)
// Drawing the Common Blocks Logically
tarr[channel+1][y]=tarr[channel+1][y+1]=DMode;
}
// Drawing the Specialized Xtra Blocks Logically
switch(TCode)
{
case 0: tarr[channel+1][y+2]=DMode;break;
case 1: tarr[channel+2][y]=DMode;break;
case 2: tarr[channel][y]=DMode;break;
case 3: tarr[channel][y+1]=DMode;break;
case 4: tarr[channel][y+2]=DMode;break;
case 5: tarr[channel+2][y+1]=DMode;break;
case 6: tarr[channel+1][y]=DMode;break;
case 7: tarr[channel][y]=DMode;break;
case 8: tarr[channel+1][y]=DMode;break;
case 9: tarr[channel+1][y+1]=DMode;break;
case 10:tarr[channel+1][y+1]=DMode;break;
case 11:tarr[channel][y+1]=DMode;break;
case 12:tarr[channel][y]=DMode;tarr[channel+2][y+1]=DMode;break;
case 13:tarr[channel+1][y]=DMode;tarr[channel][y+2]=DMode;break;
case 14:tarr[channel][y+1]=DMode;tarr[channel+2][y]=DMode;break;
case 15:tarr[channel][y]=DMode;tarr[channel+1][y+2]=DMode;break;
}
// Actually Drawing it Graphically for Window W1
if(W==&W1)
{
for(int i=0;i
{
setcolor(YELLOW);
setlinestyle(0,0,1);
rectangle(fbsize*(i+1),fbsize*(j+1),fbsize*(i+2),fbsize*(j+2));
setfillstyle(1,tarr[i][j]);
floodfill(fbsize*(i+1)+1,fbsize*(j+1)+1,YELLOW);
}
}
else
{
for(int i=0;i
{
setcolor(YELLOW);
setlinestyle(0,0,1);
rectangle(fbsize*(i+51),fbsize*(j+4),fbsize*(i+52) ,fbsize*(j+5));
setfillstyle(1,tarr[i][j]);
floodfill(fbsize*(i+51)+1,fbsize*(j+4)+1,YELLOW);
}
}
}
int Tetris :: verify_vert_movement(int channel,int y)
{
if(TCode==18)
{
if(tarr[channel][y+2]!=EMPTY||tarr[channel+1][y+2]!=EMPTY)
return FALSE;
else
return TRUE;
}
else if(TCode==16)
{
if(tarr[channel][y+4]!=EMPTY)
return FALSE;
else
return TRUE;
}
else if(TCode==17)
{
if(tarr[channel][y+1]!=EMPTY||tarr[channel+1][y+1]!=EMPTY||tarr[channel+2][y+1]!=EMPTY||tarr[channel+3][y+1]!=EMPTY)
return FALSE;
else
return TRUE;
}
else if(TCode==0||TCode==2||TCode==4||TCode==6||
TCode==9||TCode==11||TCode==13||TCode==15)
{
if(TCode==0||TCode==6||TCode==9)
{
// Analysing the Common Blocks Logically
if(tarr[channel][y+3]!=EMPTY)
return FALSE;
}
else if(TCode==2||TCode==4||TCode==11)
{
// Analysing the Common Blocks Logically
if(tarr[channel+1][y+3]!=EMPTY)
return FALSE;
}
else if(TCode==13)
{
// Analysing the Blocks Logically
if(tarr[channel][y+3]!=EMPTY||tarr[channel+1][y+2]!=EMPTY)
return FALSE;
else
return TRUE;
}
else if(TCode==15)
{
// Analysing the Blocks Logically
if(tarr[channel][y+2]!=EMPTY||tarr[channel+1][y+3]!=EMPTY)
return FALSE;
else
return TRUE;
}
}
else if(TCode==1||TCode==3||TCode==5||TCode==7||
TCode==8||TCode==10||TCode==12||TCode==14)
{
if(TCode==1||TCode==7||TCode==8)
{
// Analysing the Common Blocks Logically
if(tarr[channel][y+2]!=EMPTY||tarr[channel+1][y+2]!=EMPTY||tarr[channel+2][y+2]!=EMPTY)
return FALSE;
else
return TRUE;
}
else if(TCode==12)
{
// Analysing the Blocks Logically
if(tarr[channel][y+1]!=EMPTY||tarr[channel+1][y+2]!=EMPTY||tarr[channel+2][y+2]!=EMPTY)
return FALSE;
else
return TRUE;
}
else if(TCode==14)
{
// Analysing the Blocks Logically
if(tarr[channel][y+2]!=EMPTY||tarr[channel+1][y+2]!=EMPTY||tarr[channel+2][y+1]!=EMPTY)
return FALSE;
else
return TRUE;
}
}
// Analysing the Specialized Xtra Blocks Logically
switch(TCode)
{
case 0: if(tarr[channel+1][y+3]!=EMPTY)return FALSE;break;
case 6: if(tarr[channel+1][y+1]!=EMPTY)return FALSE;break;
case 9: if(tarr[channel+1][y+2]!=EMPTY)return FALSE;break;
case 2: if(tarr[channel][y+1]!=EMPTY)return FALSE;break;
case 4: if(tarr[channel][y+3]!=EMPTY)return FALSE;break;
case 11:if(tarr[channel][y+2]!=EMPTY)return FALSE;break;
case 3: if(tarr[channel][y+2]!=EMPTY||tarr[channel+1][y+1]!=EMPTY||tarr[channel+2][y+1]!=EMPTY)return FALSE;break;
case 5: if(tarr[channel][y+1]!=EMPTY||tarr[channel+1][y+1]!=EMPTY||tarr[channel+2][y+2]!=EMPTY)return FALSE;break;
case 10:if(tarr[channel][y+1]!=EMPTY||tarr[channel+1][y+2]!=EMPTY||tarr[channel+2][y+1]!=EMPTY)return FALSE;//break;
}
return TRUE;
}
// Main Prog :
void main()
{
//Seeding the Random Number Generator
randomize();
Tetris T;
printf("\n\nWelcome to Tetris \n\n");
printf("\n\nThis Demo is a glimpse into a preliminary Version and just shows the Movement of Various Tetris Pieces along the Tetris Play Space\n\n");
printf("\n\nUser I/P is NOT Expected\n\n");
printf("\n\n\nPress ENTER to goto Graphics Mode and See the DEMO\n\n\n");
getch();clrscr();
T.regulate_play();
getch();
}
ไม่มีความคิดเห็น:
แสดงความคิดเห็น