#include <graphics.h>
#include <stdlib.h>
#include <bios.h>
#include <time.h>

#define  ESC      0x001b
#define  LEFT     0x4b00
#define  RIGHT    0x4d00
#define  UP       0x4800
#define  SPACE    32
#define  FKSIZE   15 /*方块大小*/
#define  GFKSIZE  (FKSIZE+2)/*方块列距大小*/
#define  PSIZE1   1
#define  PSIZE2   (GFKSIZE+1)
#define  PSIZE3   (2*GFKSIZE+1)
#define  PSIZE4   (3*GFKSIZE+1)
#define  WTOP     50   /*游戏区域Y坐标起始值*/
#define  WLEFT    180  /*游戏区域X坐标起始值*/
#define  ROW      15   /*游戏区最大行数据*/
#define  COLUNM   10   /*游戏区最大列数据*/
/*方块矢量位置(4个) */
int begin0[4]={PSIZE1,PSIZE2,PSIZE3,PSIZE4};
int GFKColor[7]={2,3,12,5,6,10,11};/*方块颜色列表*/
/*
方块形状共7种
方块坠落形态共19种(用如下方式表示)
1:
   fk10[]“口”(x:位于列号[0,0,0,0] y:位于行号[0,1,2,3])

   口  0  0 0
   口  0  0 0
   口  0  0 0
   口  0  0 0
*/
int fk10[8]={0,0,0,0,0,1,2,3};
int fk11[8]={0,1,2,3,0,0,0,0};
int fk20[8]={0,0,1,1,0,1,0,1};
int fk30[8]={0,1,1,2,1,0,1,1};
int fk31[8]={0,0,0,1,0,1,2,1};
int fk32[8]={0,1,1,2,0,0,1,0};
int fk33[8]={0,1,1,1,1,0,1,2};
int fk40[8]={0,0,1,1,0,1,1,2};
int fk41[8]={0,1,1,2,1,0,1,0};
int fk50[8]={0,0,1,1,1,2,0,1};
int fk51[8]={0,1,1,2,0,0,1,1};
int fk60[8]={0,1,1,1,0,0,1,2};
int fk61[8]={0,1,2,2,1,1,0,1};
int fk62[8]={0,0,0,1,0,1,2,2};
int fk63[8]={0,0,1,2,0,1,0,0};
int fk70[8]={0,0,0,1,0,1,2,0};
int fk71[8]={0,1,2,2,0,0,0,1};
int fk72[8]={0,1,1,1,2,0,1,2};
int fk73[8]={0,0,1,2,0,1,1,1};
int *GFKP[19]={fk10,fk11,fk20,fk30,fk31,fk32,fk33,fk40,fk41,
         fk50,fk51,fk60,fk61,fk62,fk63,fk70,fk71,fk72,fk73};
int index[7]={2,1,4,2,2,4,4};/*7种形状每种包括几种形态索引列表*/
int nextstyle[2]; /*保存形状([0])形态([1])*/
int nextrect[2][4];/*保存将要输出的方块*/
int newrectstyle[2]; /*新的形状形态*/
int drawrect[2][4]; /*游戏区输出方块*/
int hiderect[2][4]; /*游戏区清除方块*/
int GameTable[ROW][COLUNM];/*游戏区域*/
int FKColor[ROW][COLUNM];/*方块颜色缓存区*/
int RectColor;/*记录方块颜色*/
int ncolor=0;/*记录下一个方块颜色*/
int brow; /*动态行号*/
int bcol; /*动态列号*/
int score=0; /*记录成绩*/
int beginG=0;/*进入游戏标记*/
int speed=5;/*下落速度*/
int activesd;
char Mat[][24]={
  0x11,0x00,0x11,0x00,0x20,0x80,0x20,0x80,
  0x40,0x40,0xBF,0xA0,0x08,0x80,0x08,0x80,
  0x10,0x80,0x20,0x80,0xC7,0x00,0x00,0x00,
  0x95,0x00,0x59,0x00,0xFD,0xE0,0x32,0x40,
  0x5A,0x40,0x95,0x40,0x21,0x40,0xFC,0x80,
  0x48,0x80,0x39,0x40,0xC6,0x20,0x00,0x00,
  0x00,0x40,0xFF,0xE0,0x04,0x00,0x04,0x00,
  0x07,0x00,0x04,0x80,0x04,0x40,0x04,0x00,
  0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x40,0xFF,0xE0,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x04,0x00,0x0A,0x00,0x11,0x00,0x24,0x80,
  0xC4,0x60,0x04,0x00,0x04,0x00,0x04,0x00,
  0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,
  0x04,0x00,0x02,0x40,0xFF,0xE0,0x08,0x00,
  0x0F,0x80,0x08,0x80,0x08,0x80,0x10,0x80,
  0x10,0x80,0x20,0x80,0xC7,0x00,0x00,0x00,
  0x42,0x00,0x42,0x00,0x4F,0xC0,0xF2,0x40,
  0x42,0x40,0x42,0x40,0x5F,0xE0,0x42,0x00,
  0xF5,0x00,0x88,0x80,0x30,0x60,0x00,0x00,
  0x82,0x00,0x5F,0xE0,0x42,0x00,0x0F,0xC0,
  0xCA,0x40,0x4F,0xC0,0x43,0x00,0x46,0x80,
  0x5A,0x40,0xA2,0x00,0x9F,0xE0,0x00,0x00,
  0x02,0x00,0x7F,0xE0,0x48,0x80,0x7F,0xE0,
  0x48,0x80,0x4F,0x80,0x40,0x00,0x5F,0x80,
  0x45,0x00,0x87,0x00,0xB8,0xE0,0x00,0x00,
  0x20,0x40,0x2F,0xE0,0x42,0x40,0x92,0x80,
  0xE2,0xC0,0x42,0x40,0x92,0x40,0xE5,0x40,
  0x14,0x80,0xE9,0x40,0x16,0x20,0x00,0x00,
  0x7C,0x20,0x44,0x20,0x45,0x20,0x7D,0x20,
  0x11,0x20,0x11,0x20,0xFD,0x20,0x25,0x20,
  0x25,0x20,0x44,0x20,0x98,0xE0,0x00,0x00,
  0x20,0x00,0x27,0xE0,0xF1,0x20,0x11,0x20,
  0x29,0x20,0x71,0x20,0xAA,0x20,0x22,0x20,
  0x22,0x20,0x24,0x40,0x29,0xC0,0x00,0x00,
  0x04,0x00,0x04,0x00,0x7F,0xC0,0x44,0x40,
  0x44,0x40,0x44,0x40,0x7F,0xC0,0x04,0x00,
  0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,
  0x04,0x00,0xFF,0xE0,0x00,0x00,0x1F,0x80,
  0x10,0x80,0x7F,0xE0,0x40,0x20,0x5F,0x20,
  0x51,0x20,0x5F,0x20,0x40,0xE0,0x00,0x00,
  0x08,0x00,0x08,0x40,0xFF,0xE0,0x08,0x00,
  0x10,0x00,0x1F,0xC0,0x22,0x00,0x22,0x00,
  0x42,0x00,0x82,0x00,0x7F,0xE0,0x00,0x00,
  0x04,0x00,0x04,0x00,0xFF,0xE0,0x08,0x00,
  0x10,0x00,0x1F,0xC0,0x30,0x40,0x50,0x40,
  0x90,0x40,0x1F,0xC0,0x10,0x40,0x00,0x00,
  0x19,0x00,0xE3,0xE0,0x24,0x40,0xFA,0x80,
  0x21,0x00,0x76,0x80,0x69,0xE0,0xA2,0x20,
  0xAD,0x40,0x21,0x80,0x2E,0x00,0x00,0x00,
  0x42,0x00,0x23,0xE0,0xF4,0x00,0x4F,0xE0,
  0x71,0x20,0x55,0x40,0x55,0x00,0x55,0xE0,
  0x55,0x00,0xB7,0x00,0x89,0xE0,0x00,0x00,
  0x21,0x00,0xF9,0x00,0x47,0xE0,0x61,0x00,
  0xA7,0xE0,0xFA,0x00,0x23,0xC0,0x38,0x40,
  0xE0,0x80,0x23,0x00,0x20,0x80,0x00,0x00,
  0x42,0x00,0x42,0x00,0x4F,0xC0,0xE2,0x40,
  0xD2,0x40,0x42,0x40,0x5F,0xE0,0x42,0x00,
  0x45,0x00,0x48,0x80,0x70,0x60,0x00,0x00,
  0x11,0x00,0xFF,0xE0,0x55,0x00,0x27,0x80,
  0x8C,0x80,0x53,0x00,0x24,0x80,0x5F,0xE0,
  0xC8,0x80,0x48,0x80,0x4F,0x80,0x00,0x00,
  0x23,0x00,0x2D,0x40,0x45,0x20,0x5F,0xE0,
  0xC5,0x00,0x47,0x20,0x4D,0x40,0x54,0x80,
  0x44,0xA0,0x45,0x60,0x5C,0x20,0x00,0x00,
  0x7F,0xE0,0x49,0x20,0x49,0x20,0x7F,0xE0,
  0x04,0x00,0x0F,0xC0,0x10,0x80,0x69,0x00,
  0x06,0x00,0x0C,0x00,0xF0,0x00,0x00,0x00,
  0x48,0x60,0xFD,0x80,0x49,0x00,0x79,0x00,
  0x49,0xE0,0x79,0x40,0x49,0x40,0xFD,0x40,
  0x2A,0x40,0x4A,0x40,0x84,0x40,0x00,0x00,
};
/*输出汉字*/
void OutCh(char *mat,int matsize,int x,int y,int color)
{
    int i, j, k, n;
    n = (matsize - 1) / 8 + 1;
    for(j = 0; j < matsize; j++)
    for(i = 0; i < n; i++)
    for(k = 0;k < 8; k++)
    if(mat[j * n + i] & (0x80 >> k))
    putpixel(x + i * 8 + k, y + j, color);
}
/*绘制直线*/
void Line(int x1,int y1,int x2,int y2,int color)
{
    int dr;
    float r,c,k,dx,dy;
    r=y2-y1;c=x2-x1; dx=x1;dy=y1;
    if(abs(r)>abs(c))
    {
    if(r!=0)
    {
        k=c/r;
        if(r>0)
        {
        for(dr=0;dr<=r;dr+=1)
        {
            putpixel(dx+0.5,y1+dr,color);
            dx+=k;
        }}
        if(r<0)
        {
            dx=x2;
            for(dr=0;dr<=-r;dr+=1)
            {
                putpixel(dx+0.5,y2+dr,color);
                dx+=k;
        }}}
        else
        {
        if(c>0)
        {
            for(dr=0;dr<=r;dr+=1)
                putpixel(x1+dr,y1,color);
        }
        if(c<0)
        {
            for(dr=r;dr<=0;dr+=1)
                putpixel(x1+dr,y1,color);
    }}}
    else
    {
    if(c!=0)
    {
        k=r/c;
        if(c>0)
        {
            for(dr=0;dr<=c;dr+=1)
            {
                putpixel(x1+dr,dy+0.5,color);
                dy+=k;
        }}
        if(c<0)
        {
            dy=y2;
            for(dr=0;dr<=-c;dr+=1)
            {
                putpixel(x2+dr,dy+0.5,color);
                dy+=k;
        }}}
        else
        {
        if(r>0)
        {
            for(dr=0;dr<=r;dr+=1)
                putpixel(x1,y1+dr,color);
        }
        if(r<0)
        {
            for(dr=r;dr<=0;dr+=1)
                putpixel(x1,y1+dr,color);
}}}}
/*绘制并填充矩形图*/
void Rect(int x1,int y1,int x2,int y2,int color,int fillmode)
{
    int r,c;

    Line(x1,y1,x2,y1,color);
    Line(x1,y2,x2,y2,color);
    Line(x1,y1,x1,y2,color);
    Line(x2,y1,x2,y2,color);
    r=y2-y1;
    c=x2-x1;
    if(fillmode)
        floodfill(x1+c/2,y1+r/2,color);
}
/*绘制条形栏(高亮在左边)*/
void LBar(int x1,int y1,int x2,int y2)
{
    Rect(x1,y1,x2,y2,6,1);
    Line(x1,y1,x1,y2,15);
    Line(x1,y1,x2,y1,15);
    Line(x2,y1,x2,y2,8);
    Line(x1,y2,x2,y2,8);

}
/*游戏简易区域*/
void GameWind()
{
    int i,j;
    char s[5];
    setfillstyle(1,1);
    Rect(WLEFT-10,WTOP-40,WLEFT+COLUNM*GFKSIZE+100,WTOP-20,1,1);
    Rect(WLEFT-10,WTOP-40,WLEFT+COLUNM*GFKSIZE+100,WTOP+390,9,0);
    Line(WLEFT-9,WTOP-20,WLEFT+COLUNM*GFKSIZE+99,WTOP-20,8);
    for(i=0;i<3;i++)
        OutCh(Mat[i+21],12,WLEFT-5+i*13,WTOP-35,15);
    for(i=0;i<2;i++)
        OutCh(Mat[i+5],12,WLEFT-5+(i+3)*13,WTOP-35,15);
    setfillstyle(1,4);
    LBar(WLEFT+COLUNM*GFKSIZE+68,WTOP-35,WLEFT+COLUNM*GFKSIZE+95,WTOP-25);
    setcolor(15);
    outtextxy(WLEFT+COLUNM*GFKSIZE+70,WTOP-33,"ESC");
    setfillstyle(1,8);
    Rect(WLEFT,WTOP,WLEFT+COLUNM*GFKSIZE,WTOP+ROW*GFKSIZE,8,1);
    for(i=0;i<=COLUNM;i++)
        Line(WLEFT+i*GFKSIZE,WTOP,WLEFT+i*GFKSIZE,WTOP+ROW*GFKSIZE,3);
    for(i=0;i<=ROW;i++)
        Line(WLEFT,WTOP+i*GFKSIZE,WLEFT+COLUNM*GFKSIZE,WTOP+i*GFKSIZE,3);
    setcolor(7);
    for(i=0;i<2;i++)
        OutCh(Mat[i],12,375+i*13,55,7);
    sprintf(s,"%d",score);
    outtextxy(375,75,s);
    for(i=0;i<5;i++)
        OutCh(Mat[i+2],12,375+i*13,105,7);
    for(i=0;i<2;i++)
        OutCh(Mat[i+7],12,375+i*13,205,7);
    sprintf(s,"%d",speed);
    outtextxy(375,225,s);
    for(i=0;i<2;i++)
        OutCh(Mat[i+9],12,375+i*13,250,7);
    OutCh(Mat[11],12,375,275,7);
    OutCh(Mat[9],12,388,275,7);
    Rect(200,320,330,410,15,0);
    OutCh(Mat[14],12,210,335,7);
    OutCh(Mat[16],12,235,335,7);
    OutCh(Mat[15],12,210,350,7);
    OutCh(Mat[16],12,235,350,7);
    OutCh(Mat[17],12,210,365,7);
    OutCh(Mat[18],12,235,365,7);
    OutCh(Mat[19],12,210,380,7);
    OutCh(Mat[20],12,235,380,7);
    outtextxy(250,335," - LEFT");
    outtextxy(250,350," - RIGHT");
    outtextxy(250,365," - UP");
    outtextxy(250,380," - SPACE");
}
/*隐藏方块*/
void HideRect(int r,int c,int rt[2][4])
{
    int j,ry,cx;
    ry=WTOP+r*GFKSIZE;
    cx=WLEFT+c*GFKSIZE;
    setfillstyle(1,8);
    for(j=0;j<4;j++)
    {
        Rect(begin0[rt[0][j]]+cx,begin0[rt[1][j]]+ry,
        begin0[rt[0][j]]+cx+FKSIZE,begin0[rt[1][j]]+ry+FKSIZE,8,1);
        GameTable[r+rt[1][j]][c+rt[0][j]]=0;
        FKColor[r+rt[1][j]][c+rt[0][j]]=0;
    }
}
/*显示方块*/
void ShowRect(int r,int c,int rt[2][4])
{
    int i,j,ry,cx;
    ry=WTOP+r*GFKSIZE;
    cx=WLEFT+c*GFKSIZE;
    setfillstyle(1,RectColor);
    for(j=0;j<4;j++)
    {
        LBar(begin0[rt[0][j]]+cx,begin0[rt[1][j]]+ry,begin0[rt[0][j]]
        +cx+FKSIZE,begin0[rt[1][j]]+ry+FKSIZE);
        GameTable[r+rt[1][j]][c+rt[0][j]]=1;
        FKColor[r+rt[1][j]][c+rt[0][j]]=RectColor;
    }
    for(i=0;i<2;i++)
        for(j=0;j<4;j++)
            hiderect[i][j]=rt[i][j];
    for(i=0;i<speed;i++){delay(50000);}/*设置中断时间*/
}
/*获取方块类型索引号*/
int GetIndex(int fki,int fks)
{
    int i,id;

    id=fks;
    if(fki>0)
        for(i=0;i<fki;i++)
            id+=index[i];
    return id;
}

/*获取下个方块*/
void GetNextRect()
{
    int i,c,rts,id;
    srand(time(0));
    rts=rand()%7;
    id=rand()%index[rts];
    ncolor=GFKColor[rts];
    nextstyle[0]=rts;
    nextstyle[1]=id;
    id=GetIndex(rts,id);
    if(beginG)/*游戏已开始清除方块*/
    {
        setfillstyle(1,0);
        for(i=0;i<4;i++)
            Rect(begin0[nextrect[0][i]]+375,begin0[nextrect[1][i]]+120,
            begin0[nextrect[0][i]]+375+FKSIZE,begin0[nextrect[1][i]]+120+FKSIZE,0,1);
    }
    for(c=0;c<4;c++)/*获取下一个方块数据*/
    {
        nextrect[0][c]=GFKP[id][c];
        nextrect[1][c]=GFKP[id][4+c];
    }
    setfillstyle(1,ncolor); /*显示新方块*/
    for(i=0;i<4;i++)
        LBar(begin0[nextrect[0][i]]+375,begin0[nextrect[1][i]]+120,
        begin0[nextrect[0][i]]+375+FKSIZE,begin0[nextrect[1][i]]+120+FKSIZE);
}
/*获取游戏方块数据*/
void GetRectData()
{
    int i,j;
    for(i=0;i<2;i++)
    {
        newrectstyle[i]=nextstyle[i];
        for(j=0;j<4;j++)
            drawrect[i][j]=nextrect[i][j];
    }
    RectColor=ncolor;
}
/*获取最大值*/
int GetMax(int tm[4])
{
    int i,max;
    max=tm[0];
    for(i=1;i<4;i++)
        if(tm[i]>max)
            max=tm[i];
    return max;
}
/*判断向左称条件*/
int LMove()
{
    int i,j,t,mr,tm;
    mr=GetMax(drawrect[1]);
    t=0;
    for(i=0;i<=mr;i++)
    {
        for(j=3;j>=0;j--)
        {
            if(drawrect[1][j]==i)
                tm=drawrect[0][j];
         }
         /*检测左接触面方块的上一列缓存空间有无方块*/
         if(!GameTable[brow+i][bcol+tm-1])
             t++;
     }
     if(t==mr+1) return 1;
     else  return 0;
}
/*判断向右移条件*/
int RMove()
{
    int i,j,t,mr,tm;
    mr=GetMax(drawrect[1]);
    t=0;
    for(i=0;i<=mr;i++)
    {
        for(j=0;j<4;j++)
        {
            if(drawrect[1][j]==i)
                tm=drawrect[0][j];
         }
         /*检测右侧接触面方块的下一列缓存空间有无方块*/
         if(!GameTable[brow+i][bcol+tm+1])
             t++;
     }
     if(t==mr+1) return 1;
     else  return 0;
}
/*判断自由下落条件*/
int BMove()
{
    int i,j,t,mc,tm;
    mc=GetMax(drawrect[0]);
    t=0;
    for(i=0;i<=mc;i++)
    {
        for(j=0;j<4;j++)
        {
            if(drawrect[0][j]==i)
                tm=drawrect[1][j];
        }
        /*检测位于最下面方块的下一行是否有空的缓存空间*/
        if(brow+tm+1<ROW&&!GameTable[brow+tm+1][bcol+i])
            t++;
    }
    if(t==mc+1) return 1;
    else  return 0;
}
/*方块初始化*/
void Rectinit()
{
    int c,rts,id;
    newrectstyle[0]=5;
    newrectstyle[1]=2;
    id=GetIndex(5,2);
    RectColor=6;
    activesd=speed;
    for(c=0;c<4;c++)
    {
        drawrect[0][c]=GFKP[id][c];
        drawrect[1][c]=GFKP[id][4+c];
    }
}
/*清除满方块行*/
void ClearRect()
{
    int i,j,k,cl,l,h;
    char s[100];
    for(i=ROW-1;i>=0;i--)
    {
        k=0;
        for(j=0;j<COLUNM;j++)
        {
            if(GameTable[i][j])/*计算行中各列是否有方块*/
                k++;
            else
                break;
        }
        if(k==COLUNM)/*满行*/
        {
            setfillstyle(1,8);
            for(cl=0;cl<COLUNM;cl++) /*清除一行方块*/
            {
                Rect(WLEFT+1+cl*GFKSIZE,WTOP+1+i*GFKSIZE,WLEFT+
                1+cl*GFKSIZE+FKSIZE,WTOP+1+i*GFKSIZE+FKSIZE,8,1);
                GameTable[i][cl]=0; /*清空游戏区域缓存*/
                FKColor[i][cl]=0;
            }
            /*输出成绩(分数)*/
            sprintf(s,"%d",score);
            setcolor(0);
            outtextxy(375,75,s);
            score+=100;
            sprintf(s,"%d",score);
            setcolor(7);
            outtextxy(375,75,s);
            /*据条件改变速度和级别*/
            if(speed>1&&score>0&&score%5000==0)
            {
                setcolor(0);
                sprintf(s,"%d",speed);
                outtextxy(375,225,s);
                speed--;
                setcolor(7);
                sprintf(s,"%d",speed);
                outtextxy(375,225,s);
                if(speed>3)
                {
                    OutCh(Mat[11],12,375,275,0);
                    OutCh(Mat[12],12,375,275,7);
                }
                else
                {
                    OutCh(Mat[12],12,375,275,0);
                    OutCh(Mat[13],12,375,275,7);
                }
            }
            for(l=i;l>0;l--) /*上面的方块下移一行*/
            {
                for(h=0;h<COLUNM;h++)
                {
                    if(GameTable[l-1][h])
                    {
                        setfillstyle(1,FKColor[l-1][h]);
                        LBar(WLEFT+1+h*GFKSIZE,WTOP+1+l*GFKSIZE,WLEFT+1
                        +h*GFKSIZE+FKSIZE,WTOP+1+l*GFKSIZE+FKSIZE);
                        GameTable[l][h]=1;/*方块存入清空的缓存区*/
                        FKColor[l][h]=FKColor[l-1][h];/*方块颜色写入缓存*/
                        setfillstyle(1,8);
                        Rect(WLEFT+1+h*GFKSIZE,WTOP+1+(l-1)*GFKSIZE,WLEFT+1
                        +h*GFKSIZE+FKSIZE,WTOP+1+(l-1)*GFKSIZE+FKSIZE,8,1);
                        GameTable[l-1][h]=0;/*把原来的缓存区清空*/
                        FKColor[l-1][h]=0;/*把原来的颜色变为背景色*/
                    }
                }
            }
            ClearRect();/*函数递归*/
        }
    }
}
/*判断游戏是否结束条件*/
int GameOver()
{
    int i;

    for(i=0;i<4;i++)
    {
        if(GameTable[brow+drawrect[1][i]][bcol+drawrect[0][i]])/*检测游戏区域空间是否够容纳输出的新方块*/
            return 0;
    }
    return 1;
}
/*有键按下*/
void KeyDown(int key)
{
    int id,i,tm[2][4],w,h,mr,wb,wr,j,k=1;
    if(key<<8)
        key=key&0xff;
    switch(key)
    {
        case ESC:
            closegraph();
            exit(0);
            break;
        case LEFT:  /*方块左移*/
            if(bcol>0)
            {
                if(LMove()&&!GameTable[brow][bcol-1])/*左移条件*/
                {
                    HideRect(brow,bcol,hiderect);/*清除原来的方块区域(图像和缓存)*/
                    bcol-=1;
                    ShowRect(brow,bcol,drawrect);/*在新的位置显示方块(图像和保存行列号)*/
                }
            }
            break;
        case RIGHT: /*方块右移*/
            w=GetMax(drawrect[0]);
            if(bcol+w<COLUNM-1)
            {
                if(RMove()&&!GameTable[brow][bcol+1])
                {
                    HideRect(brow,bcol,hiderect);
                    bcol+=1;
                    ShowRect(brow,bcol,drawrect);
                }
            }
            break;
       case UP: /*变换方块坠落形态*/
           mr=newrectstyle[1];
           mr++;
           if(mr==index[newrectstyle[0]])
               mr=0;
           id=GetIndex(newrectstyle[0],mr);
           for(i=0;i<4;i++)
           {
               tm[0][i]=GFKP[id][i];
               tm[1][i]=GFKP[id][4+i];
           }
           w=GetMax(tm[0]);
           h=GetMax(tm[1]);
           if(bcol+w<=COLUNM-1&&brow+h<=ROW-1)
           {
               wb=GetMax(drawrect[0]);
               if(wb>w)
                   wr=wb;
               else
                   wr=w;
               HideRect(brow,bcol,hiderect);
               for(i=0;i<=h;i++)
                   for(j=0;j<=wr;j++)
                   {
                       /*检测方块变换空间如果在变换方块的行宽和列
                         高范围内有方块本次操作变换失败*/
                       if(GameTable[brow+i][bcol+j])
                           k=0;
                   }
               if(k)
               {
                   newrectstyle[1]=mr;
                   for(i=0;i<4;i++)
                   {
                       drawrect[0][i]=GFKP[id][i];
                       drawrect[1][i]=GFKP[id][4+i];
                   }
               }
               ShowRect(brow,bcol,drawrect);
           }
           break;
       case SPACE:/*快速下落*/
           activesd=speed;
           speed=0;
           break;
      default: break;
    }
}
/*游戏入口*/
void Game()
{
    int i,key,mend=1;
    GetNextRect();
    brow=0;
    bcol=4;
    Rectinit();
    ShowRect(brow,bcol,drawrect);
    getch();
    while(1)
    {
        key=0;
        if(mend==0)
        {
            beginG=1;
            GetRectData();
            GetNextRect();
            brow=0;
            bcol=4;
            speed=activesd;
            ClearRect();
            if(GameOver())
            {
                ShowRect(brow,bcol,drawrect);
                mend=1;
            }
            else
            {
                printf("Game over!");
                break;
            }

        }
        HideRect(brow,bcol,hiderect);
        if(bioskey(1))
            key=bioskey(0);
        KeyDown(key);
        if(!key)/*方块自由下落*/
        {
            if(BMove())
                brow++;
            else
                mend=0;
            ShowRect(brow,bcol,drawrect);
        }
     }
}
/*初始化Win-TC图形模式*/
void init()
{
    int dr=0,dm;
    registerbgidriver(EGAVGA_driver);
    initgraph(&dr, &dm, "");
}
void main()
{
    init();
    GameWind();
    Game();
    getch();
    closegraph();
}#include <graphics.h>
#include <stdlib.h>
#include <bios.h>
#include <time.h>

#define  ESC      0x001b
#define  LEFT     0x4b00
#define  RIGHT    0x4d00
#define  UP       0x4800
#define  SPACE    32
#define  FKSIZE   15 /*方块大小*/
#define  GFKSIZE  (FKSIZE+2)/*方块列距大小*/
#define  PSIZE1   1
#define  PSIZE2   (GFKSIZE+1)
#define  PSIZE3   (2*GFKSIZE+1)
#define  PSIZE4   (3*GFKSIZE+1)
#define  WTOP     50   /*游戏区域Y坐标起始值*/
#define  WLEFT    180  /*游戏区域X坐标起始值*/
#define  ROW      15   /*游戏区最大行数据*/
#define  COLUNM   10   /*游戏区最大列数据*/
/*方块矢量位置(4个) */
int begin0[4]={PSIZE1,PSIZE2,PSIZE3,PSIZE4};
int GFKColor[7]={2,3,12,5,6,10,11};/*方块颜色列表*/
/*
方块形状共7种
方块坠落形态共19种(用如下方式表示)
1:
   fk10[]“口”(x:位于列号[0,0,0,0] y:位于行号[0,1,2,3])

   口  0  0 0
   口  0  0 0
   口  0  0 0
   口  0  0 0
*/
int fk10[8]={0,0,0,0,0,1,2,3};
int fk11[8]={0,1,2,3,0,0,0,0};
int fk20[8]={0,0,1,1,0,1,0,1};
int fk30[8]={0,1,1,2,1,0,1,1};
int fk31[8]={0,0,0,1,0,1,2,1};
int fk32[8]={0,1,1,2,0,0,1,0};
int fk33[8]={0,1,1,1,1,0,1,2};
int fk40[8]={0,0,1,1,0,1,1,2};
int fk41[8]={0,1,1,2,1,0,1,0};
int fk50[8]={0,0,1,1,1,2,0,1};
int fk51[8]={0,1,1,2,0,0,1,1};
int fk60[8]={0,1,1,1,0,0,1,2};
int fk61[8]={0,1,2,2,1,1,0,1};
int fk62[8]={0,0,0,1,0,1,2,2};
int fk63[8]={0,0,1,2,0,1,0,0};
int fk70[8]={0,0,0,1,0,1,2,0};
int fk71[8]={0,1,2,2,0,0,0,1};
int fk72[8]={0,1,1,1,2,0,1,2};
int fk73[8]={0,0,1,2,0,1,1,1};
int *GFKP[19]={fk10,fk11,fk20,fk30,fk31,fk32,fk33,fk40,fk41,
         fk50,fk51,fk60,fk61,fk62,fk63,fk70,fk71,fk72,fk73};
int index[7]={2,1,4,2,2,4,4};/*7种形状每种包括几种形态索引列表*/
int nextstyle[2]; /*保存形状([0])形态([1])*/
int nextrect[2][4];/*保存将要输出的方块*/
int newrectstyle[2]; /*新的形状形态*/
int drawrect[2][4]; /*游戏区输出方块*/
int hiderect[2][4]; /*游戏区清除方块*/
int GameTable[ROW][COLUNM];/*游戏区域*/
int FKColor[ROW][COLUNM];/*方块颜色缓存区*/
int RectColor;/*记录方块颜色*/
int ncolor=0;/*记录下一个方块颜色*/
int brow; /*动态行号*/
int bcol; /*动态列号*/
int score=0; /*记录成绩*/
int beginG=0;/*进入游戏标记*/
int speed=5;/*下落速度*/
int activesd;
char Mat[][24]={
  0x11,0x00,0x11,0x00,0x20,0x80,0x20,0x80,
  0x40,0x40,0xBF,0xA0,0x08,0x80,0x08,0x80,
  0x10,0x80,0x20,0x80,0xC7,0x00,0x00,0x00,
  0x95,0x00,0x59,0x00,0xFD,0xE0,0x32,0x40,
  0x5A,0x40,0x95,0x40,0x21,0x40,0xFC,0x80,
  0x48,0x80,0x39,0x40,0xC6,0x20,0x00,0x00,
  0x00,0x40,0xFF,0xE0,0x04,0x00,0x04,0x00,
  0x07,0x00,0x04,0x80,0x04,0x40,0x04,0x00,
  0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x40,0xFF,0xE0,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x04,0x00,0x0A,0x00,0x11,0x00,0x24,0x80,
  0xC4,0x60,0x04,0x00,0x04,0x00,0x04,0x00,
  0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,
  0x04,0x00,0x02,0x40,0xFF,0xE0,0x08,0x00,
  0x0F,0x80,0x08,0x80,0x08,0x80,0x10,0x80,
  0x10,0x80,0x20,0x80,0xC7,0x00,0x00,0x00,
  0x42,0x00,0x42,0x00,0x4F,0xC0,0xF2,0x40,
  0x42,0x40,0x42,0x40,0x5F,0xE0,0x42,0x00,
  0xF5,0x00,0x88,0x80,0x30,0x60,0x00,0x00,
  0x82,0x00,0x5F,0xE0,0x42,0x00,0x0F,0xC0,
  0xCA,0x40,0x4F,0xC0,0x43,0x00,0x46,0x80,
  0x5A,0x40,0xA2,0x00,0x9F,0xE0,0x00,0x00,
  0x02,0x00,0x7F,0xE0,0x48,0x80,0x7F,0xE0,
  0x48,0x80,0x4F,0x80,0x40,0x00,0x5F,0x80,
  0x45,0x00,0x87,0x00,0xB8,0xE0,0x00,0x00,
  0x20,0x40,0x2F,0xE0,0x42,0x40,0x92,0x80,
  0xE2,0xC0,0x42,0x40,0x92,0x40,0xE5,0x40,
  0x14,0x80,0xE9,0x40,0x16,0x20,0x00,0x00,
  0x7C,0x20,0x44,0x20,0x45,0x20,0x7D,0x20,
  0x11,0x20,0x11,0x20,0xFD,0x20,0x25,0x20,
  0x25,0x20,0x44,0x20,0x98,0xE0,0x00,0x00,
  0x20,0x00,0x27,0xE0,0xF1,0x20,0x11,0x20,
  0x29,0x20,0x71,0x20,0xAA,0x20,0x22,0x20,
  0x22,0x20,0x24,0x40,0x29,0xC0,0x00,0x00,
  0x04,0x00,0x04,0x00,0x7F,0xC0,0x44,0x40,
  0x44,0x40,0x44,0x40,0x7F,0xC0,0x04,0x00,
  0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,
  0x04,0x00,0xFF,0xE0,0x00,0x00,0x1F,0x80,
  0x10,0x80,0x7F,0xE0,0x40,0x20,0x5F,0x20,
  0x51,0x20,0x5F,0x20,0x40,0xE0,0x00,0x00,
  0x08,0x00,0x08,0x40,0xFF,0xE0,0x08,0x00,
  0x10,0x00,0x1F,0xC0,0x22,0x00,0x22,0x00,
  0x42,0x00,0x82,0x00,0x7F,0xE0,0x00,0x00,
  0x04,0x00,0x04,0x00,0xFF,0xE0,0x08,0x00,
  0x10,0x00,0x1F,0xC0,0x30,0x40,0x50,0x40,
  0x90,0x40,0x1F,0xC0,0x10,0x40,0x00,0x00,
  0x19,0x00,0xE3,0xE0,0x24,0x40,0xFA,0x80,
  0x21,0x00,0x76,0x80,0x69,0xE0,0xA2,0x20,
  0xAD,0x40,0x21,0x80,0x2E,0x00,0x00,0x00,
  0x42,0x00,0x23,0xE0,0xF4,0x00,0x4F,0xE0,
  0x71,0x20,0x55,0x40,0x55,0x00,0x55,0xE0,
  0x55,0x00,0xB7,0x00,0x89,0xE0,0x00,0x00,
  0x21,0x00,0xF9,0x00,0x47,0xE0,0x61,0x00,
  0xA7,0xE0,0xFA,0x00,0x23,0xC0,0x38,0x40,
  0xE0,0x80,0x23,0x00,0x20,0x80,0x00,0x00,
  0x42,0x00,0x42,0x00,0x4F,0xC0,0xE2,0x40,
  0xD2,0x40,0x42,0x40,0x5F,0xE0,0x42,0x00,
  0x45,0x00,0x48,0x80,0x70,0x60,0x00,0x00,
  0x11,0x00,0xFF,0xE0,0x55,0x00,0x27,0x80,
  0x8C,0x80,0x53,0x00,0x24,0x80,0x5F,0xE0,
  0xC8,0x80,0x48,0x80,0x4F,0x80,0x00,0x00,
  0x23,0x00,0x2D,0x40,0x45,0x20,0x5F,0xE0,
  0xC5,0x00,0x47,0x20,0x4D,0x40,0x54,0x80,
  0x44,0xA0,0x45,0x60,0x5C,0x20,0x00,0x00,
  0x7F,0xE0,0x49,0x20,0x49,0x20,0x7F,0xE0,
  0x04,0x00,0x0F,0xC0,0x10,0x80,0x69,0x00,
  0x06,0x00,0x0C,0x00,0xF0,0x00,0x00,0x00,
  0x48,0x60,0xFD,0x80,0x49,0x00,0x79,0x00,
  0x49,0xE0,0x79,0x40,0x49,0x40,0xFD,0x40,
  0x2A,0x40,0x4A,0x40,0x84,0x40,0x00,0x00,
};
/*输出汉字*/
void OutCh(char *mat,int matsize,int x,int y,int color)
{
    int i, j, k, n;
    n = (matsize - 1) / 8 + 1;
    for(j = 0; j < matsize; j++)
    for(i = 0; i < n; i++)
    for(k = 0;k < 8; k++)
    if(mat[j * n + i] & (0x80 >> k))
    putpixel(x + i * 8 + k, y + j, color);
}
/*绘制直线*/
void Line(int x1,int y1,int x2,int y2,int color)
{
    int dr;
    float r,c,k,dx,dy;
    r=y2-y1;c=x2-x1; dx=x1;dy=y1;
    if(abs(r)>abs(c))
    {
    if(r!=0)
    {
        k=c/r;
        if(r>0)
        {
        for(dr=0;dr<=r;dr+=1)
        {
            putpixel(dx+0.5,y1+dr,color);
            dx+=k;
        }}
        if(r<0)
        {
            dx=x2;
            for(dr=0;dr<=-r;dr+=1)
            {
                putpixel(dx+0.5,y2+dr,color);
                dx+=k;
        }}}
        else
        {
        if(c>0)
        {
            for(dr=0;dr<=r;dr+=1)
                putpixel(x1+dr,y1,color);
        }
        if(c<0)
        {
            for(dr=r;dr<=0;dr+=1)
                putpixel(x1+dr,y1,color);
    }}}
    else
    {
    if(c!=0)
    {
        k=r/c;
        if(c>0)
        {
            for(dr=0;dr<=c;dr+=1)
            {
                putpixel(x1+dr,dy+0.5,color);
                dy+=k;
        }}
        if(c<0)
        {
            dy=y2;
            for(dr=0;dr<=-c;dr+=1)
            {
                putpixel(x2+dr,dy+0.5,color);
                dy+=k;
        }}}
        else
        {
        if(r>0)
        {
            for(dr=0;dr<=r;dr+=1)
                putpixel(x1,y1+dr,color);
        }
        if(r<0)
        {
            for(dr=r;dr<=0;dr+=1)
                putpixel(x1,y1+dr,color);
}}}}
/*绘制并填充矩形图*/
void Rect(int x1,int y1,int x2,int y2,int color,int fillmode)
{
    int r,c;

    Line(x1,y1,x2,y1,color);
    Line(x1,y2,x2,y2,color);
    Line(x1,y1,x1,y2,color);
    Line(x2,y1,x2,y2,color);
    r=y2-y1;
    c=x2-x1;
    if(fillmode)
        floodfill(x1+c/2,y1+r/2,color);
}
/*绘制条形栏(高亮在左边)*/
void LBar(int x1,int y1,int x2,int y2)
{
    Rect(x1,y1,x2,y2,6,1);
    Line(x1,y1,x1,y2,15);
    Line(x1,y1,x2,y1,15);
    Line(x2,y1,x2,y2,8);
    Line(x1,y2,x2,y2,8);

}
/*游戏简易区域*/
void GameWind()
{
    int i,j;
    char s[5];
    setfillstyle(1,1);
    Rect(WLEFT-10,WTOP-40,WLEFT+COLUNM*GFKSIZE+100,WTOP-20,1,1);
    Rect(WLEFT-10,WTOP-40,WLEFT+COLUNM*GFKSIZE+100,WTOP+390,9,0);
    Line(WLEFT-9,WTOP-20,WLEFT+COLUNM*GFKSIZE+99,WTOP-20,8);
    for(i=0;i<3;i++)
        OutCh(Mat[i+21],12,WLEFT-5+i*13,WTOP-35,15);
    for(i=0;i<2;i++)
        OutCh(Mat[i+5],12,WLEFT-5+(i+3)*13,WTOP-35,15);
    setfillstyle(1,4);
    LBar(WLEFT+COLUNM*GFKSIZE+68,WTOP-35,WLEFT+COLUNM*GFKSIZE+95,WTOP-25);
    setcolor(15);
    outtextxy(WLEFT+COLUNM*GFKSIZE+70,WTOP-33,"ESC");
    setfillstyle(1,8);
    Rect(WLEFT,WTOP,WLEFT+COLUNM*GFKSIZE,WTOP+ROW*GFKSIZE,8,1);
    for(i=0;i<=COLUNM;i++)
        Line(WLEFT+i*GFKSIZE,WTOP,WLEFT+i*GFKSIZE,WTOP+ROW*GFKSIZE,3);
    for(i=0;i<=ROW;i++)
        Line(WLEFT,WTOP+i*GFKSIZE,WLEFT+COLUNM*GFKSIZE,WTOP+i*GFKSIZE,3);
    setcolor(7);
    for(i=0;i<2;i++)
        OutCh(Mat[i],12,375+i*13,55,7);
    sprintf(s,"%d",score);
    outtextxy(375,75,s);
    for(i=0;i<5;i++)
        OutCh(Mat[i+2],12,375+i*13,105,7);
    for(i=0;i<2;i++)
        OutCh(Mat[i+7],12,375+i*13,205,7);
    sprintf(s,"%d",speed);
    outtextxy(375,225,s);
    for(i=0;i<2;i++)
        OutCh(Mat[i+9],12,375+i*13,250,7);
    OutCh(Mat[11],12,375,275,7);
    OutCh(Mat[9],12,388,275,7);
    Rect(200,320,330,410,15,0);
    OutCh(Mat[14],12,210,335,7);
    OutCh(Mat[16],12,235,335,7);
    OutCh(Mat[15],12,210,350,7);
    OutCh(Mat[16],12,235,350,7);
    OutCh(Mat[17],12,210,365,7);
    OutCh(Mat[18],12,235,365,7);
    OutCh(Mat[19],12,210,380,7);
    OutCh(Mat[20],12,235,380,7);
    outtextxy(250,335," - LEFT");
    outtextxy(250,350," - RIGHT");
    outtextxy(250,365," - UP");
    outtextxy(250,380," - SPACE");
}
/*隐藏方块*/
void HideRect(int r,int c,int rt[2][4])
{
    int j,ry,cx;
    ry=WTOP+r*GFKSIZE;
    cx=WLEFT+c*GFKSIZE;
    setfillstyle(1,8);
    for(j=0;j<4;j++)
    {
        Rect(begin0[rt[0][j]]+cx,begin0[rt[1][j]]+ry,
        begin0[rt[0][j]]+cx+FKSIZE,begin0[rt[1][j]]+ry+FKSIZE,8,1);
        GameTable[r+rt[1][j]][c+rt[0][j]]=0;
        FKColor[r+rt[1][j]][c+rt[0][j]]=0;
    }
}
/*显示方块*/
void ShowRect(int r,int c,int rt[2][4])
{
    int i,j,ry,cx;
    ry=WTOP+r*GFKSIZE;
    cx=WLEFT+c*GFKSIZE;
    setfillstyle(1,RectColor);
    for(j=0;j<4;j++)
    {
        LBar(begin0[rt[0][j]]+cx,begin0[rt[1][j]]+ry,begin0[rt[0][j]]
        +cx+FKSIZE,begin0[rt[1][j]]+ry+FKSIZE);
        GameTable[r+rt[1][j]][c+rt[0][j]]=1;
        FKColor[r+rt[1][j]][c+rt[0][j]]=RectColor;
    }
    for(i=0;i<2;i++)
        for(j=0;j<4;j++)
            hiderect[i][j]=rt[i][j];
    for(i=0;i<speed;i++){delay(50000);}/*设置中断时间*/
}
/*获取方块类型索引号*/
int GetIndex(int fki,int fks)
{
    int i,id;

    id=fks;
    if(fki>0)
        for(i=0;i<fki;i++)
            id+=index[i];
    return id;
}

/*获取下个方块*/
void GetNextRect()
{
    int i,c,rts,id;
    srand(time(0));
    rts=rand()%7;
    id=rand()%index[rts];
    ncolor=GFKColor[rts];
    nextstyle[0]=rts;
    nextstyle[1]=id;
    id=GetIndex(rts,id);
    if(beginG)/*游戏已开始清除方块*/
    {
        setfillstyle(1,0);
        for(i=0;i<4;i++)
            Rect(begin0[nextrect[0][i]]+375,begin0[nextrect[1][i]]+120,
            begin0[nextrect[0][i]]+375+FKSIZE,begin0[nextrect[1][i]]+120+FKSIZE,0,1);
    }
    for(c=0;c<4;c++)/*获取下一个方块数据*/
    {
        nextrect[0][c]=GFKP[id][c];
        nextrect[1][c]=GFKP[id][4+c];
    }
    setfillstyle(1,ncolor); /*显示新方块*/
    for(i=0;i<4;i++)
        LBar(begin0[nextrect[0][i]]+375,begin0[nextrect[1][i]]+120,
        begin0[nextrect[0][i]]+375+FKSIZE,begin0[nextrect[1][i]]+120+FKSIZE);
}
/*获取游戏方块数据*/
void GetRectData()
{
    int i,j;
    for(i=0;i<2;i++)
    {
        newrectstyle[i]=nextstyle[i];
        for(j=0;j<4;j++)
            drawrect[i][j]=nextrect[i][j];
    }
    RectColor=ncolor;
}
/*获取最大值*/
int GetMax(int tm[4])
{
    int i,max;
    max=tm[0];
    for(i=1;i<4;i++)
        if(tm[i]>max)
            max=tm[i];
    return max;
}
/*判断向左称条件*/
int LMove()
{
    int i,j,t,mr,tm;
    mr=GetMax(drawrect[1]);
    t=0;
    for(i=0;i<=mr;i++)
    {
        for(j=3;j>=0;j--)
        {
            if(drawrect[1][j]==i)
                tm=drawrect[0][j];
         }
         /*检测左接触面方块的上一列缓存空间有无方块*/
         if(!GameTable[brow+i][bcol+tm-1])
             t++;
     }
     if(t==mr+1) return 1;
     else  return 0;
}
/*判断向右移条件*/
int RMove()
{
    int i,j,t,mr,tm;
    mr=GetMax(drawrect[1]);
    t=0;
    for(i=0;i<=mr;i++)
    {
        for(j=0;j<4;j++)
        {
            if(drawrect[1][j]==i)
                tm=drawrect[0][j];
         }
         /*检测右侧接触面方块的下一列缓存空间有无方块*/
         if(!GameTable[brow+i][bcol+tm+1])
             t++;
     }
     if(t==mr+1) return 1;
     else  return 0;
}
/*判断自由下落条件*/
int BMove()
{
    int i,j,t,mc,tm;
    mc=GetMax(drawrect[0]);
    t=0;
    for(i=0;i<=mc;i++)
    {
        for(j=0;j<4;j++)
        {
            if(drawrect[0][j]==i)
                tm=drawrect[1][j];
        }
        /*检测位于最下面方块的下一行是否有空的缓存空间*/
        if(brow+tm+1<ROW&&!GameTable[brow+tm+1][bcol+i])
            t++;
    }
    if(t==mc+1) return 1;
    else  return 0;
}
/*方块初始化*/
void Rectinit()
{
    int c,rts,id;
    newrectstyle[0]=5;
    newrectstyle[1]=2;
    id=GetIndex(5,2);
    RectColor=6;
    activesd=speed;
    for(c=0;c<4;c++)
    {
        drawrect[0][c]=GFKP[id][c];
        drawrect[1][c]=GFKP[id][4+c];
    }
}
/*清除满方块行*/
void ClearRect()
{
    int i,j,k,cl,l,h;
    char s[100];
    for(i=ROW-1;i>=0;i--)
    {
        k=0;
        for(j=0;j<COLUNM;j++)
        {
            if(GameTable[i][j])/*计算行中各列是否有方块*/
                k++;
            else
                break;
        }
        if(k==COLUNM)/*满行*/
        {
            setfillstyle(1,8);
            for(cl=0;cl<COLUNM;cl++) /*清除一行方块*/
            {
                Rect(WLEFT+1+cl*GFKSIZE,WTOP+1+i*GFKSIZE,WLEFT+
                1+cl*GFKSIZE+FKSIZE,WTOP+1+i*GFKSIZE+FKSIZE,8,1);
                GameTable[i][cl]=0; /*清空游戏区域缓存*/
                FKColor[i][cl]=0;
            }
            /*输出成绩(分数)*/
            sprintf(s,"%d",score);
            setcolor(0);
            outtextxy(375,75,s);
            score+=100;
            sprintf(s,"%d",score);
            setcolor(7);
            outtextxy(375,75,s);
            /*据条件改变速度和级别*/
            if(speed>1&&score>0&&score%5000==0)
            {
                setcolor(0);
                sprintf(s,"%d",speed);
                outtextxy(375,225,s);
                speed--;
                setcolor(7);
                sprintf(s,"%d",speed);
                outtextxy(375,225,s);
                if(speed>3)
                {
                    OutCh(Mat[11],12,375,275,0);
                    OutCh(Mat[12],12,375,275,7);
                }
                else
                {
                    OutCh(Mat[12],12,375,275,0);
                    OutCh(Mat[13],12,375,275,7);
                }
            }
            for(l=i;l>0;l--) /*上面的方块下移一行*/
            {
                for(h=0;h<COLUNM;h++)
                {
                    if(GameTable[l-1][h])
                    {
                        setfillstyle(1,FKColor[l-1][h]);
                        LBar(WLEFT+1+h*GFKSIZE,WTOP+1+l*GFKSIZE,WLEFT+1
                        +h*GFKSIZE+FKSIZE,WTOP+1+l*GFKSIZE+FKSIZE);
                        GameTable[l][h]=1;/*方块存入清空的缓存区*/
                        FKColor[l][h]=FKColor[l-1][h];/*方块颜色写入缓存*/
                        setfillstyle(1,8);
                        Rect(WLEFT+1+h*GFKSIZE,WTOP+1+(l-1)*GFKSIZE,WLEFT+1
                        +h*GFKSIZE+FKSIZE,WTOP+1+(l-1)*GFKSIZE+FKSIZE,8,1);
                        GameTable[l-1][h]=0;/*把原来的缓存区清空*/
                        FKColor[l-1][h]=0;/*把原来的颜色变为背景色*/
                    }
                }
            }
            ClearRect();/*函数递归*/
        }
    }
}
/*判断游戏是否结束条件*/
int GameOver()
{
    int i;

    for(i=0;i<4;i++)
    {
        if(GameTable[brow+drawrect[1][i]][bcol+drawrect[0][i]])/*检测游戏区域空间是否够容纳输出的新方块*/
            return 0;
    }
    return 1;
}
/*有键按下*/
void KeyDown(int key)
{
    int id,i,tm[2][4],w,h,mr,wb,wr,j,k=1;
    if(key<<8)
        key=key&0xff;
    switch(key)
    {
        case ESC:
            closegraph();
            exit(0);
            break;
        case LEFT:  /*方块左移*/
            if(bcol>0)
            {
                if(LMove()&&!GameTable[brow][bcol-1])/*左移条件*/
                {
                    HideRect(brow,bcol,hiderect);/*清除原来的方块区域(图像和缓存)*/
                    bcol-=1;
                    ShowRect(brow,bcol,drawrect);/*在新的位置显示方块(图像和保存行列号)*/
                }
            }
            break;
        case RIGHT: /*方块右移*/
            w=GetMax(drawrect[0]);
            if(bcol+w<COLUNM-1)
            {
                if(RMove()&&!GameTable[brow][bcol+1])
                {
                    HideRect(brow,bcol,hiderect);
                    bcol+=1;
                    ShowRect(brow,bcol,drawrect);
                }
            }
            break;
       case UP: /*变换方块坠落形态*/
           mr=newrectstyle[1];
           mr++;
           if(mr==index[newrectstyle[0]])
               mr=0;
           id=GetIndex(newrectstyle[0],mr);
           for(i=0;i<4;i++)
           {
               tm[0][i]=GFKP[id][i];
               tm[1][i]=GFKP[id][4+i];
           }
           w=GetMax(tm[0]);
           h=GetMax(tm[1]);
           if(bcol+w<=COLUNM-1&&brow+h<=ROW-1)
           {
               wb=GetMax(drawrect[0]);
               if(wb>w)
                   wr=wb;
               else
                   wr=w;
               HideRect(brow,bcol,hiderect);
               for(i=0;i<=h;i++)
                   for(j=0;j<=wr;j++)
                   {
                       /*检测方块变换空间如果在变换方块的行宽和列
                         高范围内有方块本次操作变换失败*/
                       if(GameTable[brow+i][bcol+j])
                           k=0;
                   }
               if(k)
               {
                   newrectstyle[1]=mr;
                   for(i=0;i<4;i++)
                   {
                       drawrect[0][i]=GFKP[id][i];
                       drawrect[1][i]=GFKP[id][4+i];
                   }
               }
               ShowRect(brow,bcol,drawrect);
           }
           break;
       case SPACE:/*快速下落*/
           activesd=speed;
           speed=0;
           break;
      default: break;
    }
}
/*游戏入口*/
void Game()
{
    int i,key,mend=1;
    GetNextRect();
    brow=0;
    bcol=4;
    Rectinit();
    ShowRect(brow,bcol,drawrect);
    getch();
    while(1)
    {
        key=0;
        if(mend==0)
        {
            beginG=1;
            GetRectData();
            GetNextRect();
            brow=0;
            bcol=4;
            speed=activesd;
            ClearRect();
            if(GameOver())
            {
                ShowRect(brow,bcol,drawrect);
                mend=1;
            }
            else
            {
                printf("Game over!");
                break;
            }

        }
        HideRect(brow,bcol,hiderect);
        if(bioskey(1))
            key=bioskey(0);
        KeyDown(key);
        if(!key)/*方块自由下落*/
        {
            if(BMove())
                brow++;
            else
                mend=0;
            ShowRect(brow,bcol,drawrect);
        }
     }
}
/*初始化Win-TC图形模式*/
void init()
{
    int dr=0,dm;
    registerbgidriver(EGAVGA_driver);
    initgraph(&dr, &dm, "");
}
void main()
{
    init();
    GameWind();
    Game();
    getch();
    closegraph();
}