服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - 老程序员教你一天时间完成C++俄罗斯方块游戏

老程序员教你一天时间完成C++俄罗斯方块游戏

2021-12-14 15:31Linux猿 C/C++

俄罗斯方块游戏大家应该非常熟悉,非常经典的一款游戏,本文来详细讲解下俄罗斯方块游戏的制作过程,赶紧来看下吧!希望能给你带来帮助

首先,看下效果图:

 

 
老程序员教你一天时间完成C++俄罗斯方块游戏

 

 

图1 游戏运行过程

 

下面详细讲解下制作过程。

 

一、主要文件

文件包含三个:tetris.cpp、tetris.h、main.cpp,各个文件的用途如下:

tetris.cpp 文件:函数实现;

tetris.h : 类和函数声明;

main.cpp : 主函数;

 

二、界面设计

bool vis[100][100]; // 用于标记坐标
int Co[100][100]; // 坐标的颜色

其中:

vis[100][100] 用于标记界面坐标,true表示有内容,false 表示空;

Co[100][100] 用于标记界面坐标的颜色;

设置框架函数,如下所示:

//设置框架
void setFrame()
{
 color(5);
 getCoord(30 ,1);
 cout<<"    < 俄罗斯方块游戏 >"<<endl<<endl;
 color(10);

 // 主要框架
 int x = LF_up_x ,y = 3; 
 //横向边上下两条边
 for(int i = 0; i < 30; ++i) {
     getCoord(x ,2);  vis[x][2] = true;  cout<<"□";
     getCoord(x ,23); vis[x][23] = true; cout<<"□";
     x += 2;
 }

 //竖向两条边和小框左边竖线
 for(int i = 0; i < 21; ++i) {
     getCoord(LF_up_x ,y) ; vis[LF_up_x][y] = true ; cout<<"□" ;
     getCoord(71 ,y) ;      vis[71][y] = true ; cout<<"□" ;
     getCoord(51 ,y) ;      vis[51][y] = true ; cout<<"□" ;
     y += 1 ;
 }

 //小框架中间横线
 for(int i = 53 ;i <= 69 ; i += 2) {
     getCoord(i ,11);
     vis[i][11] = true;
     cout<<"□";
 }

 //小框内容
 color(10);
 getCoord(53 ,3);  cout<<" Next Block : " ;
 color(11) ;
 getCoord(54 ,13) ; cout<<"开始 :  Enter 键" ;
 getCoord(54 ,15) ; cout<<"暂停 :  T 键" ;
 getCoord(54 ,17) ; cout<<"退出 :  Q 键" ;
 getCoord(54 ,19) ;  cout<<"Score:" ;
 getCoord(54 ,21) ; cout<<"Rank :" ;
 T_Box::staticNum(0) ;
}

设置整体的界面,如下图所示:

 

 
老程序员教你一天时间完成C++俄罗斯方块游戏

 

 

图2 界面图

 

 

三、方块设计

表示方块的类,如下所示:

class T_Box
{
  static int Score ;
  static int Rank ;
  private :
           int x ,y ; // 坐标
           int type ; // 类型
           int fg ; // 某个图形的第 fg 个变化的图形
  public :
           T_Box(int sx = 31 ,int sy = 3 ,int st = 0 ,int f = 0);
           static void staticNum(int num);
           void setValue(int sx = 31 ,int sy = 3 ,int st = 0 ,int f = 0) ;
           void Move(int stepA ,int stepB);
           bool Stop();
           void printBox();
           void eraseBox();
           void Mark();
           void Pause();
           void nextBox(T_Box temp);
           void Transform();
           bool Judge();
};

各种方块的设计函数如下所示:

class Coord
{
  public :
          int x;
          int y;
          int Col;
}G[10][10][10];

其中:

x,y 是相对坐标;

Col 是方块颜色;

G[10][10][10] :一维表示方块类型,二维表示方块内的方格,三维表示方块的第几种表示形式;

来看下各个方块的设计,如下所示:

// 设置各种图形
void setBox()
{
  // 1 正方形
  for(int i = 0 ;i < 4 ; ++i)
  {
     G[0][0][i].x = 0 ;  G[0][0][i].y = 0 ;  G[0][0][i].Col = 14 ;
     G[0][1][i].x = 0 ;  G[0][1][i].y = 1 ;  G[0][1][i].Col = 14 ;
     G[0][2][i].x = 2 ;  G[0][2][i].y = 0 ;  G[0][2][i].Col = 14 ;
     G[0][3][i].x = 2 ;  G[0][3][i].y = 1 ;  G[0][3][i].Col = 14 ;
  }

  // 2  竖条
  G[1][0][0].x = 0 ; G[1][0][0].y = 0 ; G[1][0][0].Col = 3 ;
  G[1][1][0].x = 0 ; G[1][1][0].y = 1 ; G[1][1][0].Col = 3 ;
  G[1][2][0].x = 0 ; G[1][2][0].y = 2 ; G[1][2][0].Col = 3 ;
  G[1][3][0].x = 0 ; G[1][3][0].y = 3 ; G[1][3][0].Col = 3 ;

  G[1][0][1].x = 0 ; G[1][0][1].y = 0 ; G[1][0][1].Col = 3 ;
  G[1][1][1].x = 2 ; G[1][1][1].y = 0 ; G[1][1][1].Col = 3 ;
  G[1][2][1].x = 4 ; G[1][2][1].y = 0 ; G[1][2][1].Col = 3 ;
  G[1][3][1].x = 6 ; G[1][3][1].y = 0 ; G[1][3][1].Col = 3 ;

  G[1][0][2].x = 0 ; G[1][0][2].y = 0 ; G[1][0][2].Col = 3 ;
  G[1][1][2].x = 0 ; G[1][1][2].y = 1 ; G[1][1][2].Col = 3 ;
  G[1][2][2].x = 0 ; G[1][2][2].y = 2 ; G[1][2][2].Col = 3 ;
  G[1][3][2].x = 0 ; G[1][3][2].y = 3 ; G[1][3][2].Col = 3 ;

  G[1][0][3].x = 0 ; G[1][0][3].y = 0 ; G[1][0][3].Col = 3 ;
  G[1][1][3].x = 2 ; G[1][1][3].y = 0 ; G[1][1][3].Col = 3 ;
  G[1][2][3].x = 4 ; G[1][2][3].y = 0 ; G[1][2][3].Col = 3 ;
  G[1][3][3].x = 6 ; G[1][3][3].y = 0 ; G[1][3][3].Col = 3 ;

  // 3
  G[2][0][0].x = 0 ; G[2][0][0].y = 0 ; G[2][0][0].Col = 4 ;
  G[2][1][0].x = 0 ; G[2][1][0].y = 1 ; G[2][1][0].Col = 4 ;
  G[2][2][0].x = 2 ; G[2][2][0].y = 1 ; G[2][2][0].Col = 4 ;
  G[2][3][0].x = 2 ; G[2][3][0].y = 2 ; G[2][3][0].Col = 4 ;
  G[2][0][1].x = 0 ; G[2][0][1].y = 0 ; G[2][0][1].Col = 4 ;
  G[2][1][1].x = 2 ; G[2][1][1].y = 0 ; G[2][1][1].Col = 4 ;
  G[2][2][1].x = 0 ; G[2][2][1].y = 1 ; G[2][2][1].Col = 4 ;
  G[2][3][1].x = -2 ; G[2][3][1].y = 1 ; G[2][3][1].Col = 4 ;
  G[2][0][2].x = 0 ; G[2][0][2].y = 0 ; G[2][0][2].Col = 4 ;
  G[2][1][2].x = 0 ; G[2][1][2].y = 1 ; G[2][1][2].Col = 4 ;
  G[2][2][2].x = 2 ; G[2][2][2].y = 1 ; G[2][2][2].Col = 4 ;
  G[2][3][2].x = 2 ; G[2][3][2].y = 2 ; G[2][3][2].Col = 4 ;
  G[2][0][3].x = 0 ; G[2][0][3].y = 0 ; G[2][0][3].Col = 4 ;
  G[2][1][3].x = 2 ; G[2][1][3].y = 0 ; G[2][1][3].Col = 4 ;
  G[2][2][3].x = 0 ; G[2][2][3].y = 1 ; G[2][2][3].Col = 4 ;
  G[2][3][3].x = -2 ; G[2][3][3].y = 1 ; G[2][3][3].Col = 4 ;
  // 4
  G[3][0][0].x = 0 ; G[3][0][0].y = 0 ; G[3][0][0].Col = 5 ;
  G[3][1][0].x = 0 ; G[3][1][0].y = 1 ; G[3][1][0].Col = 5 ;
  G[3][2][0].x = -2 ; G[3][2][0].y = 1 ; G[3][2][0].Col = 5 ;
  G[3][3][0].x = 2 ; G[3][3][0].y = 1 ; G[3][3][0].Col = 5 ;
  G[3][0][1].x = 0 ; G[3][0][1].y = 0 ; G[3][0][1].Col = 5 ;
  G[3][1][1].x = 0 ; G[3][1][1].y = 1 ; G[3][1][1].Col = 5 ;
  G[3][2][1].x = 2 ; G[3][2][1].y = 1 ; G[3][2][1].Col = 5 ;
  G[3][3][1].x = 0 ; G[3][3][1].y = 2 ; G[3][3][1].Col = 5 ;
  G[3][0][2].x = 0 ; G[3][0][2].y = 0 ; G[3][0][2].Col = 5 ;
  G[3][1][2].x = 2 ; G[3][1][2].y = 0 ; G[3][1][2].Col = 5 ;
  G[3][2][2].x = 2 ; G[3][2][2].y = 1 ; G[3][2][2].Col = 5 ;
  G[3][3][2].x = 4 ; G[3][3][2].y = 0 ; G[3][3][2].Col = 5 ;
  G[3][0][3].x = 0 ; G[3][0][3].y = 0 ; G[3][0][3].Col = 5 ;
  G[3][1][3].x = 0 ; G[3][1][3].y = 1 ; G[3][1][3].Col = 5 ;
  G[3][2][3].x = -2 ; G[3][2][3].y = 1 ; G[3][2][3].Col = 5 ;
  G[3][3][3].x = 0 ; G[3][3][3].y = 2 ; G[3][3][3].Col = 5 ;

  // 5
  G[4][0][0].x = 0 ; G[4][0][0].y = 0 ; G[4][0][0].Col = 6 ;
  G[4][1][0].x = 0 ; G[4][1][0].y = 1 ; G[4][1][0].Col = 6 ;
  G[4][2][0].x = 0 ; G[4][2][0].y = 2 ; G[4][2][0].Col = 6 ;
  G[4][3][0].x = 2 ; G[4][3][0].y = 2 ; G[4][3][0].Col = 6 ;
  G[4][0][1].x = 0 ; G[4][0][1].y = 0; G[4][0][1].Col = 6 ;
  G[4][1][1].x = 0 ; G[4][1][1].y = 1 ; G[4][1][1].Col = 6 ;
  G[4][2][1].x = 2 ; G[4][2][1].y = 0 ; G[4][2][1].Col = 6 ;
  G[4][3][1].x = 4 ; G[4][3][1].y = 0 ; G[4][3][1].Col = 6 ;
  G[4][0][2].x = 0 ; G[4][0][2].y = 0 ; G[4][0][2].Col = 6 ;
  G[4][1][2].x = 2 ; G[4][1][2].y = 0 ; G[4][1][2].Col = 6 ;
  G[4][2][2].x = 2 ; G[4][2][2].y = 1 ; G[4][2][2].Col = 6 ;
  G[4][3][2].x = 2 ; G[4][3][2].y = 2 ; G[4][3][2].Col = 6 ;
  G[4][0][3].x = 0 ; G[4][0][3].y = 0; G[4][0][3].Col = 6 ;
  G[4][1][3].x = 0 ; G[4][1][3].y = 1 ; G[4][1][3].Col = 6 ;
  G[4][2][3].x = -2 ; G[4][2][3].y = 1 ; G[4][2][3].Col = 6 ;
  G[4][3][3].x = -4 ; G[4][3][3].y = 1 ; G[4][3][3].Col = 6 ;

  // 6
  G[5][0][0].x = 0 ; G[5][0][0].y = 0 ; G[5][0][0].Col = 9 ;
  G[5][1][0].x = 0 ; G[5][1][0].y = 1 ; G[5][1][0].Col = 9 ;
  G[5][2][0].x = 0 ; G[5][2][0].y = 2 ; G[5][2][0].Col = 9 ;
  G[5][3][0].x = -2 ; G[5][3][0].y = 2 ; G[5][3][0].Col = 9 ;
  G[5][0][1].x = 0 ; G[5][0][1].y = 0 ; G[5][0][1].Col = 9 ;
  G[5][1][1].x = 0 ; G[5][1][1].y = 1 ; G[5][1][1].Col = 9 ;
  G[5][2][1].x = 2 ; G[5][2][1].y = 1 ; G[5][2][1].Col = 9 ;
  G[5][3][1].x = 4 ; G[5][3][1].y = 1 ; G[5][3][1].Col = 9 ;
  G[5][0][2].x = 0 ; G[5][0][2].y = 0 ; G[5][0][2].Col = 9 ;
  G[5][1][2].x = 2 ; G[5][1][2].y = 0 ; G[5][1][2].Col = 9 ;
  G[5][2][2].x = 0 ; G[5][2][2].y = 1 ; G[5][2][2].Col = 9 ;
  G[5][3][2].x = 0 ; G[5][3][2].y = 2 ; G[5][3][2].Col = 9 ;
  G[5][0][3].x = 0 ; G[5][0][3].y = 0 ; G[5][0][3].Col = 9 ;
  G[5][1][3].x = 2 ; G[5][1][3].y = 0 ; G[5][1][3].Col = 9 ;
  G[5][2][3].x = 4 ; G[5][2][3].y = 0 ; G[5][2][3].Col = 9 ;
  G[5][3][3].x = 4 ; G[5][3][3].y = 1 ; G[5][3][3].Col = 9 ;
}

上面设置的是各个方块的相对坐标以及方块的颜色。

 

四、设计思路

先来看下方块的主要类,如下所示:

class T_Box
{
  static int Score ;
  static int Rank ;
  private :
           int x ,y ; // 坐标
           int type ; // 类型
           int fg ; // 某个图形的第 fg 个变化的图形
  public :
           T_Box(int sx = 31 ,int sy = 3 ,int st = 0 ,int f = 0) ;
           static void staticNum(int num) ;
           void setValue(int sx = 31 ,int sy = 3 ,int st = 0 ,int f = 0) ;
           void Move(int stepA ,int stepB) ;
           bool Stop() ;
           void printBox() ;
           void eraseBox() ;
           void Mark() ;
           void Pause() ;
           void nextBox(T_Box temp) ;
           void Transform() ;
           bool Judge() ;
};

其中:

Score : 表示游戏分数;

Rank : 表示游戏等级,等级是根据分数计算的;

各个函数的用途如下:

T_Box :构造函数,初始化坐标类型;

staticNum : 更新分数和等级,显示在右下侧小框内;

setValue : 设置方块的初始坐标、类型以及第几种变化,其中类型和变化是随机值;

Move : 将下落的方块向左、右、下移动;

Stop : 计算游戏是否已结束;

printBox : 输出方块图形到界面;

eraseBox : 擦除界面上的方块;

Mark : 标记当前位置已有内容了;

Pause : 游戏暂停,等待开始;

nextBox : 在右上侧方格内显示下一个将要降落的方格;

Transform :在方格下落过程中变换方格样式;

Judge : 判断方格是否可以变换样式;

接下来就说下主程序的设计逻辑,代码如下所示:

// 主程序
void Tetris()
{
 srand(time(0)); // 取系统时间
 setBox();    // 设置各种图形
 T_Box  cd ,tempA ,tempB;   // 每个下降的方块的初始值
 tempB.setValue(); // 设置方块初始值
 tempB.nextBox(tempA);
 for(int i = 0;   ; ++i)
 {
     if(!(i%2))   tempA.setValue();
     else         tempB.setValue();
     if(i%2)      tempB.nextBox(tempA) ,cd = tempA;
     else         tempA.nextBox(tempB) ,cd = tempB;
     while(1) {
        cd.printBox(); // 输出图形
        if(cd.Stop())
        {
            color(6);
            getCoord(20 ,10);
            cout<<"   T_T    游戏结束    T_T";
            Exit();
        }
        Sleep(350);
        cd.eraseBox(); //擦除图形
        cd.Move(0 ,1);
        if(kbhit()) // 判断是否有按键按下,如果有则可能是旋转或者加速按键
        {
          char ch = getch();
          switch(ch)
          {
              case 'a' :   cd.Move(-2 ,0) ; break;    //  向左移动一格
              case 'd' :   cd.Move(2 ,0) ;  break;    //  向右移动一格
              case 'w' :   cd.Transform() ; break;                   //  变换方格
              case 's' :   cd.Move(0 ,2) ; break;  //  急降方格
              case 'T' :   cd.Pause() ; break;
              case 'Q' :   Exit();  break;
              default :    break; // 如果都不是则不执行
           }
        }
        if(cd.Stop())  break;
     }
     cd.printBox();
     cd.Mark();
     Check(); // 检查是否可以消除
  }
}

设计思路如下:

1. 首先,设置各种图形以及界面图形;

2. 产生当前方格和下一个方格,下一个方格显示到右上侧方框内;

3. 输出当前下落方格到界面;

4. 判断游戏是否结束;

5. 向下移动方格;

6. 监听用户输入,执行用户输入的操作,包括:移动、急降方格、变换方格样式、退出、暂停等。

7. 检测方格是否降落到底部,循环操作,一直到方格降落到底部;

8. 循环 2 ~ 7,一直到游戏结束;

 

五、总结

C++俄罗斯方块设计的重点在于界面的设计以及游戏的整体逻辑,其中,界面设计主要是获取对应坐标,在对应坐标处输出对应图形,整体逻辑是不断循环产生下落的方格,方格移动是通过擦除当前位置的方格,将方格坐标整体移动一个再次显示来实现的。

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注服务器之家的更多内容!

原文链接:https://blog.csdn.net/nyist_zxp/article/details/119559201
 

延伸 · 阅读

精彩推荐