C++实现俄罗斯方块

写在卸载之前

一个蒟蒻无力的挣扎

如果你是在阅读本人的博文来实现俄罗斯方块

在实现俄罗斯方块之前 本人建议先左转贪吃蛇

正式开始

本来还是想秉持拿来主义 像贪吃蛇一样从网上随随便便找一个拿来写写

但是由于网上的俄罗斯方块 实在是要么看不懂要么运行不了这话好像已经说过了

所以没有办法 只好自己手写一个轻描淡写的一句话 背后是逝去的头发

同时由于我所使用的是exe显示 所以为了舒适看着顺眼 最好手动调节一下显示exe的比例和字体大小

捕获.PNG

捕获2.PNG

大致写出来就是这样

捕获2.PNG

这里添加了黑暗模式也就是盲打俄罗斯方块 如果有想玩但是网上找不到的朋友可以试试

并且理解代码之后 你发现你甚至可以通过修改参数来在开头生成残块

tmp1.gif

tmp1.gif

俄罗斯方块的写法跟贪吃蛇硬件类似 软件不同

这里的我有很多都用到了贪吃蛇里面的代码 例如Windows API

1.初始化游戏设置

跟贪吃蛇类似

class GameSetting
{
  public:
    static const int window_height=22;
    static const int window_width=28;
  public:
    static void GameInit()
    {//调节屏幕尺寸
      char buffer[32];
      sprintf(buffer,"mode con cols=%d lines=%d",window_width,window_height);
      system(buffer);
     //隐藏光标
      HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
      CONSOLE_CURSOR_INFO cursor;
      GetConsoleCursorInfo(handle,&cursor);
      cursor.bVisible=false;
      SetConsoleCursorInfo(handle,&cursor);
     //随机种子
      srand((unsigned int)time((int)(998244353==19260817)));
    }	
    static void GameStart()
    {//开始游戏界面
      system("cls");
      for(int i=1;i<=window_width;++i) putchar('#');
      putchar('\n');
      for(int i=2;i<window_height;++i)
      {
        for(int j=1;j<=window_width;++j)
        if(j==1||j==window_width) putchar('#');
        else putchar(' ');
        putchar('\n');
      }
      for(int i=1;i<=window_width;++i) putchar('#');
      gotoxy(7,9);printf("俄罗斯方块");
      gotoxy(7,11);printf("方向键控制");
      gotoxy(7,13);printf("请选择模式:");
      gotoxy(4,15);printf("↑:正常    ↓:黑暗"); 
    }
    static void GameOver(int score)
    {//游戏结束界面
      for(int i=3;i<=17;++i)
      for(int j=7;j<=13;++j)
      gotoxy(i,j),putchar(' ');
      gotoxy(7,9);printf("游戏结束!");
      gotoxy(5,11);printf("当前分数为:%03d",score);
    }
};

2.打印相关的游戏信息

/* 

1
****
2 
**
**
3
*
***
4
*
***
5
*
***
6
**
**
7
**
**

*/ 
class PrintInfo
{
  public:
    static void DrawMap()
    {//打印初始版面
      system("cls");
      for(int i=1;i<=GameSetting::window_width;++i) putchar('#');
      putchar('\n');
      for(int i=2;i<GameSetting::window_height;++i)
      {
      for(int j=1;j<=GameSetting::window_width;++j)
      if(i==11&&j>=12) putchar('#');
      else if(j==1||j==GameSetting::window_width||j==12) putchar('#');
      else putchar(' ');
      putchar('\n');
      }
      for(int i=1;i<=GameSetting::window_width;++i) putchar('#');	
      for(int i=1;i<=20;++i) {gotoxy(i,21);nowhave[i][21]=1;} 
    }
    static void DrawNext(int knd)
    {//俄罗斯方块需要有下一个的提示 所以我们需要在右上角显示下一个方块的信息
      gotoxy(13,2);printf("Next:");
      switch(knd)
      {//具体为什么会这么打印 跟上面的对应吧
        case 1:
          gotoxy(14+2,3+2);putchar('*');
          gotoxy(15+2,3+2);putchar('*');
          gotoxy(16+2,3+2);putchar('*');
          gotoxy(17+2,3+2);putchar('*');
          break;	
        case 2:
          gotoxy(14+2,3+2);putchar('*');
          gotoxy(15+2,3+2);putchar('*');
          gotoxy(14+2,4+2);putchar('*');
          gotoxy(15+2,4+2);putchar('*');
          break;	
        case 3:
          gotoxy(15+2,3+2);putchar('*');
          gotoxy(14+2,4+2);putchar('*');
          gotoxy(15+2,4+2);putchar('*');
          gotoxy(16+2,4+2);putchar('*');
          break;
        case 4:
          gotoxy(14+2,3+2);putchar('*');
          gotoxy(14+2,4+2);putchar('*');
          gotoxy(15+2,4+2);putchar('*');
          gotoxy(16+2,4+2);putchar('*');
          break;	
        case 5:
          gotoxy(16+2,3+2);putchar('*');
          gotoxy(14+2,4+2);putchar('*');
          gotoxy(15+2,4+2);putchar('*');
          gotoxy(16+2,4+2);putchar('*');
          break;	
        case 6:
          gotoxy(14+2,3+2);putchar('*');
          gotoxy(15+2,3+2);putchar('*');
          gotoxy(15+2,4+2);putchar('*');
          gotoxy(16+2,4+2);putchar('*');
          break;	
        case 7:
          gotoxy(15+2,3+2);putchar('*');
          gotoxy(16+2,3+2);putchar('*');
          gotoxy(14+2,4+2);putchar('*');
          gotoxy(15+2,4+2);putchar('*');
          break;					
      }
    }
    static void ClearNext()
    {//每一次打印完之后为了防止覆盖下一个 我们需要清理
      gotoxy(14+2,3+2);putchar(' ');
      gotoxy(15+2,3+2);putchar(' ');
      gotoxy(16+2,3+2);putchar(' ');
      gotoxy(17+2,3+2);putchar(' ');
      gotoxy(14+2,4+2);putchar(' ');
      gotoxy(15+2,4+2);putchar(' ');
      gotoxy(16+2,4+2);putchar(' ');
    }
    static void DrawScore(int hard,int line,int score)
    {//显示当前游戏信息
      gotoxy(13,13);printf("游戏等级:%02d\n",hard);
      gotoxy(13,15);printf("消灭行数:%03d\n",line);
      gotoxy(13,17);printf("玩家分数:%03d\n",score);
      gotoxy(13,19);printf("作者:破晓晨光");
    }
    static void DrawNowHave()
    {//打印下方已经存在还没有消去的块
      for(int i=1;i<=20;++i)
      for(int j=1;j<=10;++j)
      {
        gotoxy(j,i);
        putchar(nowhave[j][i] ? '*':' ');
      }
    }
};

3.关于方块

class Square
{
  private:
    vector<Node> NowL,tmp;//存储当前下降方块的坐标 以及用于临时存储的vector
    int NowKnd,nowdir;//当前方框的种类和朝向
    int NextKnd;//下一个方块的种类
  public:
    Square()
    {//初始构造函数
      NowKnd=rand()%7+1;nowdir=0;
      NextKnd=rand()%7+1;
      NowL.clear();
      switch(NowKnd)
      {//初始的方块所在显示屏幕的位置
        case 1:
          NowL.push_back((Node){4,0});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 2:
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){6,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          break;
        case 3:
          NowL.push_back((Node){6,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 4:
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 5:
          NowL.push_back((Node){7,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 6:
          NowL.push_back((Node){4,-1});
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          break;
        case 7:
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){6,-1});
          NowL.push_back((Node){4,0});
          NowL.push_back((Node){5,0});
          break;						
      } 
    }	
    void getNew()
    {//获取新的下降方块 其种类就是当前的下一个的种类
      NowKnd=NextKnd;nowdir=0;NowL.clear();
      NextKnd=rand()%7+1; 
      switch(NowKnd)
      {
        case 1:
          NowL.push_back((Node){4,0});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 2:
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){6,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          break;
        case 3:
          NowL.push_back((Node){6,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 4:
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 5:
          NowL.push_back((Node){7,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 6:
          NowL.push_back((Node){4,-1});
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          break;
        case 7:
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){6,-1});
          NowL.push_back((Node){4,0});
          NowL.push_back((Node){5,0});
          break;						
      } 
    }
    void listen_keyboard()
    {//监听键盘 
      char ch;
      if(_kbhit())
      {
        ch=_getch(); 
        ch=_getch();//72向上 80向下 75向左 77向右 
        int maxn=-1,minn=35;
        bool okay=1;
        for(int i=0;i<4;++i)
        {//我们分别判断左移 右移 加速下降是否合法
          minn=min(minn,NowL[i].xx),maxn=max(maxn,NowL[i].xx);
          for(int j=1;j<=3;++j)
          if(NowL[i].yy+j>20||nowhave[NowL[i].xx][NowL[i].yy+j]) okay=0;
        } 
        if(ch==75&&minn>1) 
        {
          for(int i=0;i<4;++i) NowL[i].xx--;
        }
        if(ch==77&&maxn<10)
        {
          for(int i=0;i<4;++i) NowL[i].xx++;
        }
        if(ch==80&&okay)
        {
          for(int i=0;i<4;++i) NowL[i].yy+=3;
        }
        if(ch==72)
        {//最复杂的旋转操作 建议看代码的同时自己手动模拟 以便理解
          tmp.clear();
          switch(NowKnd)
          {
            case 1:
              if(nowdir==0)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx,nowy-1});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy+1});
                tmp.push_back((Node){nowx,nowy+2});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else 
              {
              int nowx=NowL[1].xx,nowy=NowL[1].yy;
              bool flag=1;
              tmp.push_back((Node){nowx-1,nowy});
              tmp.push_back((Node){nowx,nowy});
              tmp.push_back((Node){nowx+1,nowy});
              tmp.push_back((Node){nowx+2,nowy});
              for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
              if(flag)
              {
              	NowL.clear();
              	for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
              }
              } 
              nowdir=(nowdir+1)%2;
              break;
            case 2:
            break;
            case 3:
              if(nowdir==0)
              {
                int nowx=NowL[2].xx,nowy=NowL[2].yy;
                bool flag=1;
                tmp.push_back((Node){nowx,nowy-1});
                tmp.push_back((Node){nowx+1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy+1});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
                }
              else if(nowdir==1)
              {
                int nowx=NowL[2].xx,nowy=NowL[2].yy;
                bool flag=1;
                tmp.push_back((Node){nowx+1,nowy});
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy+1});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                    NowL.clear();
                    for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==2)
              {
                int nowx=NowL[2].xx,nowy=NowL[2].yy;
                bool flag=1;
                tmp.push_back((Node){nowx,nowy-1});
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy+1});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==3)
              {
                int nowx=NowL[2].xx,nowy=NowL[2].yy;
                bool flag=1;
                tmp.push_back((Node){nowx+1,nowy});
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy-1});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                    NowL.clear();
                    for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              nowdir=(nowdir+1)%4;
              break;
            case 4:
              if(nowdir==0)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx+1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy+1});
                tmp.push_back((Node){nowx,nowy+2});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                     NowL.clear();
                      for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==1)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx,nowy+1});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx-2,nowy});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                   NowL.clear();
                   for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==2)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy-1});
                tmp.push_back((Node){nowx,nowy-2});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                    NowL.clear();
                    for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==3)
              {
              int nowx=NowL[1].xx,nowy=NowL[1].yy;
              bool flag=1;
              tmp.push_back((Node){nowx,nowy-1});
              tmp.push_back((Node){nowx,nowy});
              tmp.push_back((Node){nowx+1,nowy});
              tmp.push_back((Node){nowx+2,nowy});
              for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
              if(flag)
              {
              	NowL.clear();
              	for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
              }
              }
              nowdir=(nowdir+1)%4;
              break;
            case 5:
              if(nowdir==0)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx+1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy-1});
                tmp.push_back((Node){nowx,nowy-2});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==1)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx,nowy+1});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx+1,nowy});
                tmp.push_back((Node){nowx+2,nowy});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==2)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy+1});
                tmp.push_back((Node){nowx,nowy+2});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==3)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx,nowy-1});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx-2,nowy});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              nowdir=(nowdir+1)%4;
              break;
            case 6:
              if(nowdir==0)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx,nowy-1});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx-1,nowy+1});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else 
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy+1});
                tmp.push_back((Node){nowx+1,nowy+1});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              } 
              nowdir=(nowdir+1)%2;
              break;
            case 7:
            if(nowdir==0)
            {
              int nowx=NowL[0].xx,nowy=NowL[0].yy;
              bool flag=1;
              tmp.push_back((Node){nowx,nowy});
              tmp.push_back((Node){nowx,nowy+1});
              tmp.push_back((Node){nowx-1,nowy});
              tmp.push_back((Node){nowx-1,nowy-1});
              for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
              if(flag)
              {
              	NowL.clear();
              	for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
              }
            }
            else 
            {
              int nowx=NowL[0].xx,nowy=NowL[0].yy;
              bool flag=1;
              tmp.push_back((Node){nowx,nowy});
              tmp.push_back((Node){nowx+1,nowy});
              tmp.push_back((Node){nowx-1,nowy+1});
              tmp.push_back((Node){nowx,nowy+1});
              for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
              if(flag)
              {
              	NowL.clear();
              	for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
              }
            } 
            nowdir=(nowdir+1)%2;
            break;
          }
        }
      }
    }
    int getNext(){return NextKnd;}//获取下一个方块的种类
    bool CanMove()
    {//判断当前下降方块是否可以下降
      for(int i=0;i<4;++i)
      {
        int nowx=NowL[i].xx,nowy=NowL[i].yy;
        if(nowhave[nowx][nowy+1]||nowy+1>20) return 0; 
      }
      return 1;
    }
    void Move()
    {//向下移动
      listen_keyboard();
      if(CanMove())
      for(int i=0;i<4;++i) ++NowL[i].yy;
    }
    void MapChange()
    {//更新下方存在没有消去的方块
      for(int i=0;i<4;++i) nowhave[NowL[i].xx][NowL[i].yy]=1;
    }
    void Draw()
    {//打印下方存在没有消去的方块
      for(int i=0;i<4;++i)
      {
        if(NowL[i].xx>=1&&NowL[i].xx<=10&&NowL[i].yy>=1&&NowL[i].yy<=20)
        {
          gotoxy(NowL[i].xx,NowL[i].yy);putchar('*');
        }
      }
    }
    void print()
    {//打印下降方块的二维坐标
      for(int i=0;i<4;++i) printf("%d %d\n",NowL[i].xx,NowL[i].yy);
    }
    void ClearL()
    {//在显示屏幕上消除下降方块
      for(int i=0;i<4;++i)
      {
        if(NowL[i].xx>=1&&NowL[i].xx<=10&&NowL[i].yy>=1&&NowL[i].yy<=20)
        {
          gotoxy(NowL[i].xx,NowL[i].yy);putchar(' ');
        }
      }
    }
    bool HaveBeenOver()
    {//如果当前下降方块还没有开始下降便已经无法下降 就代表游戏结束
      for(int i=0;i<4;++i) if(NowL[i].yy<=0) return 1;
      return 0;
    }
};

4.消去方块

int Speed=500,Score,cnt=1,tot,resline;
void CheckScore()
{
  bool flag=0;int tottmp=0;

  for(int j=20;j;--j)
  {
    flag=1;
    for(int i=1;i<=10;++i) if(nowhave[i][j]==0) {flag=0;break;}
    if(flag) solo[++tottmp]=j;//存在可以消去的整行
  }
  if(tottmp==0) return;//如果没有可以消去的整行
  memset(nowtmp,0,sizeof nowtmp);
  for(int j=20,x=1,y=20;j;--j)
  {//这里的话 使用了一个移动指针法来让没有被消去的重新积累在一起
    if(x<=tottmp&&j==solo[x]) ++x;
    else
    {
    for(int i=1;i<=10;++i) nowtmp[i][y]=nowhave[i][j];
    --y;
    }

  }
  if(eyeflag)
  {//正常模式下先删除过去的
    for(int j=20;j;--j)
    for(int i=1;i<=10;++i)
    {gotoxy(i,j);putchar(' ');}	
  }
  for(int j=20;j;--j)
  for(int i=1;i<=10;++i)
  nowhave[i][j]=nowtmp[i][j];
  if(eyeflag)
  {//然后在打印出新的
    for(int j=20;j;--j)
    for(int i=1;i<=10;++i)
    {gotoxy(i,j);putchar(nowhave[i][j] ? '*':' ');}  
  }	
  tot+=tottmp;resline+=tottmp;//这里也是我自定义的计分制度 不适应的可以自定义
  if(resline>=50) ++cnt,resline%=50,Speed=Speed*4/5;
  if(tottmp==1) Score+=tottmp*cnt;
  if(tottmp==2) Score+=(tottmp*cnt)*5/4;
  if(tottmp==3) Score+=(tottmp*cnt)*4/3;
  if(tottmp==4) Score+=(tottmp*cnt)*3/2;

}

5.主函数

我们把上面的拼在一起

bool Choice()
{
  char ch;
  ch=_getch(); 
  ch=_getch();
  if(ch==72) return 1;
  else return 0;
}
int main()
{
  GameSetting newset;
  PrintInfo print_info;
  Square nowL;
  newset.GameInit();newset.GameStart();//游戏初始化,载入开始界面
  eyeflag=Choice();//上下键选择模式(可视化还是不可视)
  print_info.DrawMap();//打印初始版面
  while(true)
  {
    print_info.DrawScore(cnt,tot,Score);//打印游戏信息
    print_info.ClearNext();//先清理旧的下一个块
    print_info.DrawNext(nowL.getNext());//再打印当前的下一个块
    if(eyeflag) print_info.DrawNowHave();//如果正常 打印已经存在且没有被消去的块
    if(nowL.CanMove()==0)
    {//如果不可以移动的话
      if(nowL.HaveBeenOver())
      {//判断游戏是否结束
        newset.GameOver(Score);
        break;
      } 
      nowL.MapChange();//更新已经存在且没有被消去的块
      CheckScore();//更新成绩
      nowL.getNew();//更新下降的块
      continue;
    } 
    nowL.Move();nowL.Draw();//下降的块的移动和打印
    Sleep(Speed);
    nowL.ClearL();//再在显示屏幕上删除下降的块
  }
  return 0;
}

其实从这里 我们可以发现 算法在现实中也是具有较大作用的

完整代码CODE:

#include<bits/stdc++.h>
#include<windows.h>
#include<conio.h>
using namespace std;
int Speed=500,Score,cnt=1,tot,resline;
bool nowhave[30][30],nowtmp[30][30];
int solo[40];
bool eyeflag;
struct Node
{
  int xx,yy;
};
void gotoxy(short x, short y) 
{
  COORD coord={x, y}; 
  //COORD是Windows API中定义的一种结构体类型,表示控制台屏幕上的坐标。
  //上面语句是定义了COORD类型的变量coord,并以形参x和y进行初始化。
  SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
  //GetStdHandle(STD_OUTPUT_HANDLE); 获取控制台输出句柄
  //然后用SetConsoleCursorPosition设置控制台(cmd)光标位置
}
class GameSetting
{
  public:
    static const int window_height=22;
    static const int window_width=28;
  public:
    static void GameInit()
    {//调节屏幕尺寸
      char buffer[32];
      sprintf(buffer,"mode con cols=%d lines=%d",window_width,window_height);
      system(buffer);
     //隐藏光标
      HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
      CONSOLE_CURSOR_INFO cursor;
      GetConsoleCursorInfo(handle,&cursor);
      cursor.bVisible=false;
      SetConsoleCursorInfo(handle,&cursor);
     //随机种子
      srand((unsigned int)time((int)(998244353==19260817)));
    }	
    static void GameStart()
    {//开始游戏界面
      system("cls");
      for(int i=1;i<=window_width;++i) putchar('#');
      putchar('\n');
      for(int i=2;i<window_height;++i)
      {
        for(int j=1;j<=window_width;++j)
        if(j==1||j==window_width) putchar('#');
        else putchar(' ');
        putchar('\n');
      }
      for(int i=1;i<=window_width;++i) putchar('#');
      gotoxy(7,9);printf("俄罗斯方块");
      gotoxy(7,11);printf("方向键控制");
      gotoxy(7,13);printf("请选择模式:");
      gotoxy(4,15);printf("↑:正常    ↓:黑暗"); 
    }
    static void GameOver(int score)
    {//游戏结束界面
      for(int i=3;i<=17;++i)
      for(int j=7;j<=13;++j)
      gotoxy(i,j),putchar(' ');
      gotoxy(7,9);printf("游戏结束!");
      gotoxy(5,11);printf("当前分数为:%03d",score);
    }
};
/* 
1
****
2 
**
**
3
*
***
4
*
***
5
*
***
6
**
**
7
**
**
*/ 
class PrintInfo
{
  public:
    static void DrawMap()
    {//打印初始版面
      system("cls");
      for(int i=1;i<=GameSetting::window_width;++i) putchar('#');
      putchar('\n');
      for(int i=2;i<GameSetting::window_height;++i)
      {
      for(int j=1;j<=GameSetting::window_width;++j)
      if(i==11&&j>=12) putchar('#');
      else if(j==1||j==GameSetting::window_width||j==12) putchar('#');
      else putchar(' ');
      putchar('\n');
      }
      for(int i=1;i<=GameSetting::window_width;++i) putchar('#');	
      for(int i=1;i<=20;++i) {gotoxy(i,21);nowhave[i][21]=1;} 
    }
    static void DrawNext(int knd)
    {//俄罗斯方块需要有下一个的提示 所以我们需要在右上角显示下一个方块的信息
      gotoxy(13,2);printf("Next:");
      switch(knd)
      {//具体为什么会这么打印 跟上面的对应吧
        case 1:
          gotoxy(14+2,3+2);putchar('*');
          gotoxy(15+2,3+2);putchar('*');
          gotoxy(16+2,3+2);putchar('*');
          gotoxy(17+2,3+2);putchar('*');
          break;	
        case 2:
          gotoxy(14+2,3+2);putchar('*');
          gotoxy(15+2,3+2);putchar('*');
          gotoxy(14+2,4+2);putchar('*');
          gotoxy(15+2,4+2);putchar('*');
          break;	
        case 3:
          gotoxy(15+2,3+2);putchar('*');
          gotoxy(14+2,4+2);putchar('*');
          gotoxy(15+2,4+2);putchar('*');
          gotoxy(16+2,4+2);putchar('*');
          break;
        case 4:
          gotoxy(14+2,3+2);putchar('*');
          gotoxy(14+2,4+2);putchar('*');
          gotoxy(15+2,4+2);putchar('*');
          gotoxy(16+2,4+2);putchar('*');
          break;	
        case 5:
          gotoxy(16+2,3+2);putchar('*');
          gotoxy(14+2,4+2);putchar('*');
          gotoxy(15+2,4+2);putchar('*');
          gotoxy(16+2,4+2);putchar('*');
          break;	
        case 6:
          gotoxy(14+2,3+2);putchar('*');
          gotoxy(15+2,3+2);putchar('*');
          gotoxy(15+2,4+2);putchar('*');
          gotoxy(16+2,4+2);putchar('*');
          break;	
        case 7:
          gotoxy(15+2,3+2);putchar('*');
          gotoxy(16+2,3+2);putchar('*');
          gotoxy(14+2,4+2);putchar('*');
          gotoxy(15+2,4+2);putchar('*');
          break;					
      }
    }
    static void ClearNext()
    {//每一次打印完之后为了防止覆盖下一个 我们需要清理
      gotoxy(14+2,3+2);putchar(' ');
      gotoxy(15+2,3+2);putchar(' ');
      gotoxy(16+2,3+2);putchar(' ');
      gotoxy(17+2,3+2);putchar(' ');
      gotoxy(14+2,4+2);putchar(' ');
      gotoxy(15+2,4+2);putchar(' ');
      gotoxy(16+2,4+2);putchar(' ');
    }
    static void DrawScore(int hard,int line,int score)
    {//显示当前游戏信息
      gotoxy(13,13);printf("游戏等级:%02d\n",hard);
      gotoxy(13,15);printf("消灭行数:%03d\n",line);
      gotoxy(13,17);printf("玩家分数:%03d\n",score);
      gotoxy(13,19);printf("作者:破晓晨光");
    }
    static void DrawNowHave()
    {//打印下方已经存在还没有消去的块
      for(int i=1;i<=20;++i)
      for(int j=1;j<=10;++j)
      {
        gotoxy(j,i);
        putchar(nowhave[j][i] ? '*':' ');
      }
    }
};
class Square
{
  private:
    vector<Node> NowL,tmp;//存储当前下降方块的坐标 以及用于临时存储的vector
    int NowKnd,nowdir;//当前方框的种类和朝向
    int NextKnd;//下一个方块的种类
  public:
    Square()
    {//初始构造函数
      NowKnd=rand()%7+1;nowdir=0;
      NextKnd=rand()%7+1;
      NowL.clear();
      switch(NowKnd)
      {//初始的方块所在显示屏幕的位置
        case 1:
          NowL.push_back((Node){4,0});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 2:
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){6,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          break;
        case 3:
          NowL.push_back((Node){6,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 4:
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 5:
          NowL.push_back((Node){7,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 6:
          NowL.push_back((Node){4,-1});
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          break;
        case 7:
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){6,-1});
          NowL.push_back((Node){4,0});
          NowL.push_back((Node){5,0});
          break;						
      } 
    }	
    void getNew()
    {//获取新的下降方块 其种类就是当前的下一个的种类
      NowKnd=NextKnd;nowdir=0;NowL.clear();
      NextKnd=rand()%7+1; 
      switch(NowKnd)
      {
        case 1:
          NowL.push_back((Node){4,0});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 2:
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){6,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          break;
        case 3:
          NowL.push_back((Node){6,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 4:
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 5:
          NowL.push_back((Node){7,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          NowL.push_back((Node){7,0});
          break;
        case 6:
          NowL.push_back((Node){4,-1});
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){5,0});
          NowL.push_back((Node){6,0});
          break;
        case 7:
          NowL.push_back((Node){5,-1});
          NowL.push_back((Node){6,-1});
          NowL.push_back((Node){4,0});
          NowL.push_back((Node){5,0});
          break;						
      } 
    }
    void listen_keyboard()
    {//监听键盘 
      char ch;
      if(_kbhit())
      {
        ch=_getch(); 
        ch=_getch();//72向上 80向下 75向左 77向右 
        int maxn=-1,minn=35;
        bool okay=1;
        for(int i=0;i<4;++i)
        {//我们分别判断左移 右移 加速下降是否合法
          minn=min(minn,NowL[i].xx),maxn=max(maxn,NowL[i].xx);
          for(int j=1;j<=3;++j)
          if(NowL[i].yy+j>20||nowhave[NowL[i].xx][NowL[i].yy+j]) okay=0;
        } 
        if(ch==75&&minn>1) 
        {
          for(int i=0;i<4;++i) NowL[i].xx--;
        }
        if(ch==77&&maxn<10)
        {
          for(int i=0;i<4;++i) NowL[i].xx++;
        }
        if(ch==80&&okay)
        {
          for(int i=0;i<4;++i) NowL[i].yy+=3;
        }
        if(ch==72)
        {//最复杂的旋转操作 建议看代码的同时自己手动模拟 以便理解
          tmp.clear();
          switch(NowKnd)
          {
            case 1:
              if(nowdir==0)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx,nowy-1});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy+1});
                tmp.push_back((Node){nowx,nowy+2});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else 
              {
              int nowx=NowL[1].xx,nowy=NowL[1].yy;
              bool flag=1;
              tmp.push_back((Node){nowx-1,nowy});
              tmp.push_back((Node){nowx,nowy});
              tmp.push_back((Node){nowx+1,nowy});
              tmp.push_back((Node){nowx+2,nowy});
              for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
              if(flag)
              {
              	NowL.clear();
              	for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
              }
              } 
              nowdir=(nowdir+1)%2;
              break;
            case 2:
            break;
            case 3:
              if(nowdir==0)
              {
                int nowx=NowL[2].xx,nowy=NowL[2].yy;
                bool flag=1;
                tmp.push_back((Node){nowx,nowy-1});
                tmp.push_back((Node){nowx+1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy+1});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
                }
              else if(nowdir==1)
              {
                int nowx=NowL[2].xx,nowy=NowL[2].yy;
                bool flag=1;
                tmp.push_back((Node){nowx+1,nowy});
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy+1});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                    NowL.clear();
                    for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==2)
              {
                int nowx=NowL[2].xx,nowy=NowL[2].yy;
                bool flag=1;
                tmp.push_back((Node){nowx,nowy-1});
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy+1});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==3)
              {
                int nowx=NowL[2].xx,nowy=NowL[2].yy;
                bool flag=1;
                tmp.push_back((Node){nowx+1,nowy});
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy-1});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                    NowL.clear();
                    for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              nowdir=(nowdir+1)%4;
              break;
            case 4:
              if(nowdir==0)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx+1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy+1});
                tmp.push_back((Node){nowx,nowy+2});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                     NowL.clear();
                      for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==1)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx,nowy+1});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx-2,nowy});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                   NowL.clear();
                   for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==2)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy-1});
                tmp.push_back((Node){nowx,nowy-2});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                    NowL.clear();
                    for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==3)
              {
              int nowx=NowL[1].xx,nowy=NowL[1].yy;
              bool flag=1;
              tmp.push_back((Node){nowx,nowy-1});
              tmp.push_back((Node){nowx,nowy});
              tmp.push_back((Node){nowx+1,nowy});
              tmp.push_back((Node){nowx+2,nowy});
              for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
              if(flag)
              {
              	NowL.clear();
              	for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
              }
              }
              nowdir=(nowdir+1)%4;
              break;
            case 5:
              if(nowdir==0)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx+1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy-1});
                tmp.push_back((Node){nowx,nowy-2});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==1)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx,nowy+1});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx+1,nowy});
                tmp.push_back((Node){nowx+2,nowy});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==2)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy+1});
                tmp.push_back((Node){nowx,nowy+2});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else if(nowdir==3)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx,nowy-1});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx-2,nowy});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              nowdir=(nowdir+1)%4;
              break;
            case 6:
              if(nowdir==0)
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx,nowy-1});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx-1,nowy+1});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              }
              else 
              {
                int nowx=NowL[1].xx,nowy=NowL[1].yy;
                bool flag=1;
                tmp.push_back((Node){nowx-1,nowy});
                tmp.push_back((Node){nowx,nowy});
                tmp.push_back((Node){nowx,nowy+1});
                tmp.push_back((Node){nowx+1,nowy+1});
                for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
                if(flag)
                {
                  NowL.clear();
                  for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
                }
              } 
              nowdir=(nowdir+1)%2;
              break;
            case 7:
            if(nowdir==0)
            {
              int nowx=NowL[0].xx,nowy=NowL[0].yy;
              bool flag=1;
              tmp.push_back((Node){nowx,nowy});
              tmp.push_back((Node){nowx,nowy+1});
              tmp.push_back((Node){nowx-1,nowy});
              tmp.push_back((Node){nowx-1,nowy-1});
              for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
              if(flag)
              {
              	NowL.clear();
              	for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
              }
            }
            else 
            {
              int nowx=NowL[0].xx,nowy=NowL[0].yy;
              bool flag=1;
              tmp.push_back((Node){nowx,nowy});
              tmp.push_back((Node){nowx+1,nowy});
              tmp.push_back((Node){nowx-1,nowy+1});
              tmp.push_back((Node){nowx,nowy+1});
              for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
              if(flag)
              {
              	NowL.clear();
              	for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
              }
            } 
            nowdir=(nowdir+1)%2;
            break;
          }
        }
      }
    }
    int getNext(){return NextKnd;}//获取下一个方块的种类
    bool CanMove()
    {//判断当前下降方块是否可以下降
      for(int i=0;i<4;++i)
      {
        int nowx=NowL[i].xx,nowy=NowL[i].yy;
        if(nowhave[nowx][nowy+1]||nowy+1>20) return 0; 
      }
      return 1;
    }
    void Move()
    {//向下移动
      listen_keyboard();
      if(CanMove())
      for(int i=0;i<4;++i) ++NowL[i].yy;
    }
    void MapChange()
    {//更新下方存在没有消去的方块
      for(int i=0;i<4;++i) nowhave[NowL[i].xx][NowL[i].yy]=1;
    }
    void Draw()
    {//打印下方存在没有消去的方块
      for(int i=0;i<4;++i)
      {
        if(NowL[i].xx>=1&&NowL[i].xx<=10&&NowL[i].yy>=1&&NowL[i].yy<=20)
        {
          gotoxy(NowL[i].xx,NowL[i].yy);putchar('*');
        }
      }
    }
    void print()
    {//打印下降方块的二维坐标
      for(int i=0;i<4;++i) printf("%d %d\n",NowL[i].xx,NowL[i].yy);
    }
    void ClearL()
    {//在显示屏幕上消除下降方块
      for(int i=0;i<4;++i)
      {
        if(NowL[i].xx>=1&&NowL[i].xx<=10&&NowL[i].yy>=1&&NowL[i].yy<=20)
        {
          gotoxy(NowL[i].xx,NowL[i].yy);putchar(' ');
        }
      }
    }
    bool HaveBeenOver()
    {//如果当前下降方块还没有开始下降便已经无法下降 就代表游戏结束
      for(int i=0;i<4;++i) if(NowL[i].yy<=0) return 1;
      return 0;
    }
};
void CheckScore()
{
  bool flag=0;int tottmp=0;

  for(int j=20;j;--j)
  {
    flag=1;
    for(int i=1;i<=10;++i) if(nowhave[i][j]==0) {flag=0;break;}
    if(flag) solo[++tottmp]=j;//存在可以消去的整行
  }
  if(tottmp==0) return;//如果没有可以消去的整行
  memset(nowtmp,0,sizeof nowtmp);
  for(int j=20,x=1,y=20;j;--j)
  {//这里的话 使用了一个移动指针法来让没有被消去的重新积累在一起
    if(x<=tottmp&&j==solo[x]) ++x;
    else
    {
    for(int i=1;i<=10;++i) nowtmp[i][y]=nowhave[i][j];
    --y;
    }

  }
  if(eyeflag)
  {//正常模式下先删除过去的
    for(int j=20;j;--j)
    for(int i=1;i<=10;++i)
    {gotoxy(i,j);putchar(' ');}	
  }
  for(int j=20;j;--j)
  for(int i=1;i<=10;++i)
  nowhave[i][j]=nowtmp[i][j];
  if(eyeflag)
  {//然后在打印出新的
    for(int j=20;j;--j)
    for(int i=1;i<=10;++i)
    {gotoxy(i,j);putchar(nowhave[i][j] ? '*':' ');}  
  }	
  tot+=tottmp;resline+=tottmp;//这里也是我自定义的计分制度 不适应的可以自定义
  if(resline>=50) ++cnt,resline%=50,Speed=Speed*4/5;
  if(tottmp==1) Score+=tottmp*cnt;
  if(tottmp==2) Score+=(tottmp*cnt)*5/4;
  if(tottmp==3) Score+=(tottmp*cnt)*4/3;
  if(tottmp==4) Score+=(tottmp*cnt)*3/2;

}
bool Choice()
{
  char ch;
  ch=_getch(); 
  ch=_getch();
  if(ch==72) return 1;
  else return 0;
}
int main()
{
  GameSetting newset;
  PrintInfo print_info;
  Square nowL;
  newset.GameInit();newset.GameStart();//游戏初始化,载入开始界面
  eyeflag=Choice();//上下键选择模式(可视化还是不可视)
  print_info.DrawMap();//打印初始版面
  while(true)
  {
    print_info.DrawScore(cnt,tot,Score);//打印游戏信息
    print_info.ClearNext();//先清理旧的下一个块
    print_info.DrawNext(nowL.getNext());//再打印当前的下一个块
    if(eyeflag) print_info.DrawNowHave();//如果正常 打印已经存在且没有被消去的块
    if(nowL.CanMove()==0)
    {//如果不可以移动的话
      if(nowL.HaveBeenOver())
      {//判断游戏是否结束
        newset.GameOver(Score);
        break;
      } 
      nowL.MapChange();//更新已经存在且没有被消去的块
      CheckScore();//更新成绩
      nowL.getNew();//更新下降的块
      continue;
    } 
    nowL.Move();nowL.Draw();//下降的块的移动和打印
    Sleep(Speed);
    nowL.ClearL();//再在显示屏幕上删除下降的块
  }
  return 0;
}
原文地址:https://www.cnblogs.com/tcswuzb/p/14513524.html