/*************************************************************\
Written By: Jabbar Ganji ganji_j@yahoo.com http://g99.blogfa.com
\*************************************************************/
#include <conio.h>
#include <dos.h>
#include <stdlib.h>
#include <time.h>
typedef unsigned char byte;
typedef byte SHAPE;
enum { ON, OFF };
enum DIREC { LEFT, RIGHT, DOWN };
enum { END=-3, ESHGHAL=-2, OUT=-1, OK=0 };
const int i0=5, j0=3, IMAX=15, JMAX=21;
const byte ESC=27, goRI=77, goLE=75, goUP=72, goDW=80;
byte shape[7]= { ' ', 2, 3, 4, 5, 6, 'X' }; // ascii codes
byte tbl[IMAX][JMAX]={0}, bkt[IMAX][JMAX]={0};
int score=0, stage=0;
void drawTable()
{
int i, j;
for(i=0; i<IMAX; i++)
for(j=0; j<JMAX; j++)
{
gotoxy(i0+i, j0+j);
textattr(tbl[i][j]+1);
putch(shape[tbl[i][j]]);
}
}
void beep(int freq=1000, int dly=400)
{
sound(freq);
delay(dly);
nosound();
}
///-------------------------------------------------------------------------/
class cell
{
public:
cell (byte* =0, int=0, int=0);
byte elem [3];
int ri, rj;
void draw (byte);
int move (DIREC);
void set (byte =ON);
void rotate ();
};
cell :: cell(byte* rm, int i, int j)
{
elem[0]=elem[1]=elem[2]=0;
ri=i;
rj=j;
if(rm)
{
elem[0]=rm[0];
elem[1]=rm[1];
elem[2]=rm[2];
}
}
void cell:: rotate()
{
byte tmp=elem[0];
elem[0]=elem[1];
elem[1]=elem[2];
elem[2]=tmp;
set();
}
void cell:: set(byte on_off)
{
if(on_off==ON)
{
tbl[ri][rj+0]=elem[0];
tbl[ri][rj+1]=elem[1];
tbl[ri][rj+2]=elem[2];
}
else
tbl[ri][rj]=tbl[ri][rj+1]=tbl[ri][rj+2]=0;
}
void cell:: draw(byte on_off=ON)
{
int j;
for(j=0; j<3; j++)
{
gotoxy(i0+ri, j0+rj+j);
textattr(elem[j]+1);
putch(on_off==ON ? shape[elem[j]] : ' ');
}
}
int cell:: move(DIREC d)
{
int ti=ri, tj=rj;
draw(OFF);
set(OFF);
if(d==LEFT)
ri--;
else
if(d==RIGHT)
ri++;
else
rj++;
if(ri<0 || ri>=IMAX || rj<0)
{
ri=ti;
rj=tj;
set(ON);
draw();
return OUT;
}
if(rj>=JMAX-2 || tbl[ri][rj+2] && d==DOWN)
{
ri=ti;
rj=tj;
set(ON);
draw();
return END;
}
if(tbl[ri][rj] || tbl[ri][rj+1] || tbl[ri][rj+2])
{
ri=ti;
rj=tj;
set(ON);
draw();
return ESHGHAL;
}
tbl[ti][tj]=0;
tbl[ti][tj+1]=0;
tbl[ti][tj+2]=0;
set(ON);
draw();
return OK;
}
cell curCell, nextCell;
///-------------------------------------------------------------------------/
byte check()
{
int i, j, k=0, m, n;
byte flag=0;
if(curCell.elem[0]==6) // XXX
{
byte del;
j=curCell.rj+3;
curCell.set(OFF);
if(j>=JMAX)
{
curCell=cell();
return 1;
}
del=tbl[curCell.ri][j];
for(i=0; i<IMAX; i++)
for(j=0; j<JMAX; j++)
{
if(tbl[i][j]!=del)
continue;
gotoxy(i0+i, j0+j);
textattr(0x70);
putch('#');
}
beep(500, 450); beep(300, 300);
for(i=0; i<IMAX; i++)
for(j=JMAX-1; j>=0 && tbl[i][j]; j--)
while(tbl[i][j]==del)
for(k=j; k>0 && tbl[i][k]; k--)
tbl[i][k]=tbl[i][k-1];
drawTable();
curCell=cell();
return 1;
}
for(j=0; j<JMAX; j++)
{
for(i=0; i<IMAX-1; i++)
{
k=0;
while(i<IMAX-1 && tbl[i][j] && tbl[i][j]==tbl[i+1][j])
{
k++;
i++;
}
if(k>=2)
{
textattr(0x0f);
flag=1;
for(m=i; m > i-k-1 ;m--)
{
bkt[m][j]=1;
gotoxy(i0+m, j0+j);
putch(shape[tbl[i][j]]);
}
beep();
score += k+1;
}
}
}
for(i=0; i<IMAX; i++)
{
for(j=0; j<JMAX-1; j++)
{
k=0;
while(j<JMAX-1 && tbl[i][j] && tbl[i][j]==tbl[i][j+1])
{
k++;
j++;
}
if(k>=2)
{
textattr(0x0f);
flag=1;
for(m=j; m > j-k-1 ;m--)
{
bkt[i][m]=1;
gotoxy(i0+i, j0+m);
putch(shape[tbl[i][j]]);
}
beep();
score += k+1;
}
}
}
for(n=-JMAX+1; n<IMAX; n++)
for(i=0; i<IMAX-1; i++) // i-j == n
{
j=i-n;
if(j < 0 || j >JMAX-2)
continue;
k=0;
while(j<JMAX-1 && i<IMAX-1 && tbl[i][j] && tbl[i][j]==tbl[i+1][j+1])
{
i++;
j++;
k++;
}
if(k>=2)
{
textattr(0x0f);
flag=1;
for(m=i; m > i-k-1 ;m--)
{
bkt[m][m-n]=1;
gotoxy(i0+m, j0+m-n);
putch(shape[tbl[m][m-n]]);
}
beep();
score += k+1;
}
}
for(n=0; n<IMAX+JMAX-1; n++)
for(i=0; i<IMAX-1; i++) // i+j == n
{
j=n-i;
if(j < 1 || j >=JMAX)
continue;
k=0;
while(j>0 && i<IMAX-1 && tbl[i][j] && tbl[i][j]==tbl[i+1][j-1])
{
i++;
j--;
k++;
}
if(k>=2)
{
textattr(0x0f);
flag=1;
for(m=i; m > i-k-1 ;m--)
{
bkt[m][n-m]=1;
gotoxy(i0+m, j0+n-m);
putch(shape[tbl[m][n-m]]);
}
beep();
score += k+1;
}
}
for(j=JMAX-1; j>=0; j--)
for(i=0; i<IMAX; i++)
if(bkt[i][j])
{
for(k=j; k>0; k--)
{
tbl[i][k]=tbl[i][k-1]; tbl[i][k-1]=0;
bkt[i][k]=bkt[i][k-1]; bkt[i][k-1]=0;
}
i=0;
j=JMAX-1;
}
drawTable();
delay(50);
return flag;
}
///-------------------------------------------------------------------------/
void Delay()
{
clock_t st=clock();
while(!kbhit() && clock()-st<CLK_TCK-2-2*stage)
;
}
//-------------------------------------------------------------------------
void drawFrame()
{
int i, j;
textmode(C40);
textattr(0x1e);
clrscr();
gotoxy(i0-1,j0-1);
textattr(0x0e);
putch('ع');
for(j=0; j<IMAX; j++)
putch('ؤ');
putch('؟');
for(i=0; i<JMAX; i++)
{
gotoxy(i0-1, j0+i);
putch('³');
for(j=0; j<IMAX; j++)
putch(' ');
putch('³');
}
gotoxy(i0-1, j0+i);
putch('ہ');
for(j=0; j<IMAX; j++)
putch('ؤ');
putch('ظ');
gotoxy(25, 2);
textattr(0x1f);
cprintf("SCORE:");
textattr(0x1e);
cprintf("%d", score);
gotoxy(25, 4);
textattr(0x1f);
cprintf("STAGE:");
textattr(0x1e);
cprintf("%d", stage);
}
///-------------------------------------------------------------------------/
void main()
{
textattr(0x1e);
clrscr();
cprintf("\n\n\n\n Jewelry Tetris Game ");
textattr(0x1c);
cprintf("\n\n\n\n\r Author : J. Ganji ");
beep(300);
beep(0, 200);
beep(400);
beep(0, 200);
beep(600, 700);
textattr(0x9f);
cprintf("\n\r\n\n Hit A Key... ");
getch();
int i, j, s=0;
byte flag=0;
char in, stageUp=0;
byte rm0[3];
cell tmpCell;
randomize();
rm0[0]=rand()%5+1;
rm0[1]=rand()%5+1;
rm0[2]=rand()%5+1;
nextCell=cell(rm0, IMAX/2, 1);
drawFrame();
for(s=0; ; s++)
{
if(s==50)
{
s=0;
stageUp=1;
if(stage++ > 7)
break;
}
curCell=nextCell;
if(stageUp)
{
stageUp=0;
rm0[0]=rm0[1]=rm0[2]=6;
}
else
{
rm0[0]=rand()%5+1;
rm0[1]=rand()%5+1;
rm0[2]=rand()%5+1;
}
if(tbl[IMAX/2][2])
break;
nextCell=cell(rm0, IMAX/2, 1);
tmpCell=cell(rm0, -3, -1);
tmpCell.draw();
for ( ; ; )
{
if(curCell.move(DOWN)==END)
break;
while(kbhit())
switch(getch())
{
case '\r':
curCell.rotate();
curCell.draw();
break;
case '+':
getch(); // PAUSE
break;
case goRI:
curCell.move(RIGHT);
break;
case goLE:
curCell.move(LEFT);
break;
case ' ':
while(curCell.move(DOWN)==OK)
;
break;
case goDW:
while(kbhit() && getch()== ' ' && curCell.move(DOWN)==OK)
delay(50);
break;
case 'q':
case ESC:
textmode(C80);
return;
}
Delay();
}
do{
flag=check();
} while(flag);
gotoxy(25, 2);
textattr(0x1f);
cprintf("SCORE:");
textattr(0x1e);
cprintf("%d", score);
gotoxy(25, 4);
textattr(0x1f);
cprintf("STAGE:");
textattr(0x1e);
cprintf("%d", stage);
}
gotoxy(25, 5);
textattr(0x86);
cprintf("GAME OVER");
getch();
textmode(C80);
}
