目录
全局变量
程序的模块化之 MVC
关于俄罗斯方块的代码实现要点
使用数组表示背景和方块
方块表示及其初始化
要让游戏动起来
方块自动下落
全局变量
简而言之, 定义在函数外的变量, 就是全局变量.
所有的函数都可以引用和修改全局变量 (共享).
全局变量被分配在内存的全局区域, 可以调试看地址验证.
基础问题:
可否有两个同名的全局变量 (不可以)
全局变量可否在另一个文件定义, 这个文件使用 (可以, 但是要讲究技巧)
全局变量的定义, 与普通变量没有区别.
此外, 全局变量还可以声明, 而不定义, 方法是使用 extern 关键字.
声明, 告诉编译器 "有这个全局变量, 但是不在我这个 c 文件中"
工程中的使用惯例:
将全局变量定义在. c 文件中
将全局变量的声明写在. h 文件中
程序的模块化之 MVC
程序的模块化有利于代码维护.
MVC 是一种模块划分的依据, 其实是: Model,View,Control.
Model: 模型, 即数据
View:UI, 即数据如何显示
Control:Control 是用于连接 Model 和 View 的手段, 比如用户操作
我们的俄罗斯方块游戏, 将遵循 MVC 模式开发. 也就是我们会创建多个 cpp 文件, 分
工 Model 和 View.
因为我们的俄罗斯方块游戏较为简单, 所以就不再单独设立 Control.
关于俄罗斯方块的代码实现要点
创建 model.cpp,view.cpp 及其头文件
记得在头文件中加入:
#pragma once
使用数组表示背景和方块
- void InitBackground()
- {
- for (size_t nRow = 0; nRow <GAME_ROWS; nRow++)
- {
- for (size_t nCol = 0; nCol < GAME_COLS; nCol++)
- {
- if (nRow == GAME_ROWS - 1
- || nCol == 0
- || nCol == GAME_COLS - 1)
- {
- g_chBackground[nRow][nCol] = 1;
- }
- else
- {
- g_chBackground[nRow][nCol] = 0;
- }
- }
- }
- }
并在 view 中显示出来.
方块表示及其初始化
我们使用一个 4*4 的数组, 存储方块.
对于生成一个方块的算法:
先使用一个大数组, 保存所有的方块形状
需要新方块时, 从存储了所有方块形状的大叔组中, 随机取一个
因为决定形状和朝向的东西其实就是 g_chBrcikPool 中的起始行数, 所以, 定义两个变
量来存储:
- int g_nShape = 0; // 是长条还是方块, 系数为 16
- int g_nRotate = 0; // 朝向, 系数为 4
可以用 sizeof 优化代码
int nShapeCount = sizeof(g_chBrickPool) / sizeof(g_chBrickPool[0]) /16;
因为 printf 输出后, 光标会自动后移. 所以, 如果先输出背景, 再输出砖, 已经来不及了.
采取的算法逻辑是:
先在内存中合并背景和砖
再输出合并后的结果
再分离背景和砖
要让游戏动起来
因为游戏要长期运行, 程序内部一定需要一个长期运行的循环结构.
我们将实现一个循环结构, 在循环结构中, 接受用户的输入, 并改变游戏的行为.
- while (1)
- {
- clkEnd = clock();
- if (clkEnd - clkStart> 1000)
- {
- clkStart = clkEnd;
- OnDown();
- }
- if (_kbhit() != 0)
- {
- chTnput = _getch();
- }
- switch (chTnput)
- {
- case 'a':
- OnLeft();
- break;
- case 'w':
- OnUp();
- break;
- case'd':
- OnRight();
- break;
- case 's':
- OnDown();
- break;
- default:
- break;
- }
- chTnput = 0;
- }
- return 0;
- }
封装上下左右的响应函数因为需要做碰撞检查等, 所以我们封装对应的函数. 使得代码结构更清晰.
怎么进行碰撞检测
我们可以先假设方块移动, 然后判断方块与背景是否有重合.
如果有重合, 则不能移动
如果没有重合, 则可以移动
旋转的实现
依据我们取方块的逻辑, 所谓的旋转, 就是在形状不变的基础上, 朝向加 1.
是否能够旋转的逻辑, 类似于移动, 就是先假设旋转, 然后看是否与背景重叠.
如何省略掉回车
C 标准库中没有方法解决. 不过 Windows 中提供了_kbhit() 函数, 检测键盘是否按下.
int _kbhit( void );
当键盘有按下时, 这个函数会返回非 0 值, 并且, 按下的内容, 可以通过_getch 获取.
这样配合, 省掉了回车.
方块自动下落
铺垫知识: 标准库中, 提供了 clock 函数, 可以返回当前程序运行的时间 (单位是毫
秒).
我们准备两个时刻, 一个代表当前时间段的开始, 一个代表当前时刻. 当两个时刻的
差值大于一定时间, 则自动下落.
来源: http://www.bubuko.com/infodetail-3340292.html