(更新中……)
一、游戏背景
-
思路很简单的游戏:
-
试玩截图:
-
游戏的本质是根据玩家键盘(或其他)输入的值对一个 4 * 4 的二维矩阵进行移动、合并、检查等操作。
-
编译环境:Dev C++ 和 EGE图形库(网上自己搜索一下,有详细的安装流程的)
-
编程语言:C++
-
丰富的图形只是数据的映射,编程语言只是思想实例化的工具,关键还是在于数据处理
-
环境准备:
-
定义数据:
- 4*4矩阵
- 空格数
- 方向
#include
using namespace std; int grid[4][4];// 4*4矩阵 int EmptyBlock = 16;//空格数 int dir;//方向 int main() { return 0; } -
调试函数(为了方便给 grid 赋了初值)
-
打印函数-PrintGrid()
!要注意一点:二维数组遍历的时候图形上是(j, i)对应到数组取值上是grid/[i/]/[j/]
这一点要是不注意会在后面的代码翻大车!!!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Jyim40o-1635691298108)(https://cdn.jsdelivr.net/gh/Qi-China/Picture-PicX@master/2048/打印函数说明.4kgd084mupi0.png)]
-
计算空格函数-CalculateEmpty()
#include
using namespace std; int grid[4][4]= {{0,1,2,3}, {0,1,2,3}, {0,1,2,3}, {0,1,2,3},};// 4*4矩阵 int EmptyBlock = 16;//空格数 int dir;//方向 //1. 打印函数-PrintGrid() void PrintGrid() { for(int i=0; i<4; i++)//行 { for(int j=0; j<4; j++)//列 { cout << grid[i][j] << "t"; } cout << endl; } cout<< endl; } //2. 计算空格函数-CalculateEmpty() int CalculateEmpty() { int cnt = 0; for(int i=0; i<4; i++) for(int j=0; j<4; j++) if(grid[i][j]==0) cnt++; return cnt; } int main() { PrintGrid(); cout << "EmptyBlock = " << CalculateEmpty() << endl; return 0; } -
-
-
各模块的实现
1、根据流程图可以把其分为以下几个模块:
-
1-根据 dir 的值对 grid 进行操作
-
2-键盘输入
-
3-在随机位置添加数值
-
4-游戏结束检测
2、实现细节
-
1-根据 dir 的值对 grid 进行操作
-
(1) 根据 dir 的值对 grid 进行遍历
假想我们要对以下左边矩阵进行向左滑(dir=0)的操作,矩阵会变成右边的样子
{{0,1,2,3}, {{1,2,3,0}, {0,1,2,3}, {1,2,3,0}, {0,1,2,3}, {1,2,3,0}, {0,1,2,3},}; {1,2,3,0},}; 我们遍历的起点 (x0,y0) 是(0,0),同理,向上滑,向左滑, 向下滑的遍历起点分别是(0,0)、(3,0)、(0,3)
把 x0 , y0 的值分开存储,另外,我们定义两组偏转数组(具体解释如图):
static int x0[4] = {0, 0, 3, 0}; static int y0[4] = {0, 0, 0, 3}; static int firstOffset[4][2] = {{1,0},{0,1},{-1,0},{0,-1}}; static int secondOffset[4][2] = {{0,1},{1,0},{0,1} ,{1,0}};
-
-
具体代码如下(承接上一个代码):
#includeusing namespace std; int grid[4][4] = { {0,1,2,3}, {0,1,2,3}, {0,1,2,3}, {0,1,2,3} }; int EmptyBlock = 16; void PrintGrid() { for(int i=0; i<4; i++) { for(int j=0; j<4; j++) cout << grid[i][j] << " "; cout << endl; } cout << endl; } int CalculateEmpty() { int cnt = 0; for(int i=0; i<4; i++) for(int j=0; j<4; j++) if(grid[i][j]==0) cnt++; return cnt; } int dir; static int x0[4] = {0, 0, 3, 0}; static int y0[4] = {0, 0, 0, 3}; static int firstOffset[4][2] = {{1,0},{0,1},{-1,0},{0,-1}}; static int secondOffset[4][2] = {{0,1},{1,0},{0,1} ,{1,0}}; void Move(int dir) { int tx, ty; for(int i=0; i<4; i++) { tx = x0[dir] + i*secondOffset[dir][0]; ty = y0[dir] + i*secondOffset[dir][1]; for(int j=0; j<4; j++) { cout << "(" << tx << ", " << ty << ")" << "t"; tx += firstOffset[dir][0]; ty += firstOffset[dir][1]; } cout << endl; } } int main(){ PrintGrid(); cout<< "EmptyBlock = " << CalculateEmpty() << endl; Move(0); return 0; }
上面是运行结果,也可以试试把 dir 改为 1、2、3,分别对应着相应方向的遍历顺序 - (2)遍历的时候,利用前后指针比较进行相应操作 在上面第二个循环中,(tx,ty)值的遍历代表 grid 的一行或一列,移动合并等操作在逻辑上可以降为一维 我们另外建立一个 test 程序来说明一维数组中的合并移动: ```c++ #include四、优化 五、总结using namespace std; int arr[10] = {0,1,1,2,3,3,1,1,0,0}; void Print() { for(int i=0; i<10; i++) cout << arr[i] << " "; cout << endl; } void Merge() { int left, right; for(left=0,right=1; right<10; right++) { if(arr[right]!=0)//找到一个非空格子 { if(arr[left]==0)//left 是空格,right值前移至空格 { arr[left] = arr[right]; arr[right] = 0; } else if(arr[left]==arr[right])//两个相同,合并 { arr[left] *= 2; arr[right] = 0; left++; } else if(left+1 != right)//两数不同,中间有空格,移动至left下一个空格 { arr[left+1] = arr[right]; arr[right] = 0; left++; } else//最后的情况是两个数不同,并且相邻,不移动 { left++; } } } } int main() { Print(); Merge(); Print(); return 0; } ```



