在知乎上偶尔看到有人利用写这种小程序练手,正好最近刚考完期末考试,所以就花了一个晚上写了一下,也简单的写了一个2048.
之前没有用c++写过比较大型的内容,对c++的理解也不是很深。所以经过这一次编写,对游戏算法的理解以及c++多文件之间的调用有了更深刻的理解。
在写之前,我先简单的构思了以下整个游戏会分成哪几个部分,私以为可以简单的分为六个部分:
我发现这六点当中,只有第5点最有难度,也就是如何去移动整个表盘中的元素,如何判别是否可以合并,四个方向上的移动合并有什么共同点和差别,如何合并等内容。其他5点就很简单了,基本上没有这么复杂的逻辑。
下面我就以这6点分别进行讲解。
将主程序放在单独的一个文件内
//source.cpp
#include
#include
#include "OperateMap.h"
#include "Parameter.h"
using namespace std;
int main() {
//游戏地图
int MAP[MAP_SIZE][MAP_SIZE];
//初始化地图
Initlize(MAP);
bool isFull = false;
int score = 0;
while (!isFull) {
//刷新窗口
system("cls");
//生成数字
Generate(MAP);
//显示地图
ShowMap(MAP, score);
//输入指令
char command;
cin >> command;
//移动地图
MoveMap(MAP, command, score);
//是否结束?
isFull = IsOver(MAP);
}
system("pause");
return 0;
}
可以看出我引用了两个自定义的文件,即OperateMap.h和Parameter.h。
OperateMap.h定义了主函数中所用到的Initlize(), Generate(), ShowMap(), MoveMap(), IsOver()等函数。
Parameter.h则定义了一些重要的参数,诸如地图大小MAP_SIZE。
程序的逻辑比较容易看懂,就是很简单的判断isFull是否为ture,也就是地图满了没,如果满了,那就是游戏结束。
初始化地图所用到的函数为Initlize(),具体实现过程如下
void Initlize(int(&MAP)[MAP_SIZE][MAP_SIZE]) {
/*初始化地图MAP*/
cerr << "-----Initlize Finish!" << endl;
for (int i = 0; i < MAP_SIZE; i++) {
for (int j = 0; j < MAP_SIZE; j++) {
MAP[i][j] = 0;
}
}
}
也就是通过引用传递MAP将其内所有元素设置为0.
在上面已经将地图初始化了,但是全部格点都是0,在呈现给玩家看之前就需要先随机生成一个点,这一步就是解决这一个问题的。
在刚开始的时候,我是从整个地图中随机生成一个坐标,然后赋值2或者4。但是这样子会让程序效率十分低下,因为在后期格子只有少数几个为0的情况下,随机很难直接随机到那几个点,所以会导致不断的生成坐标点,效率极其低下。
为此做的对应的修改就是,首先将地图遍历一遍,记录当前为0的格点,然后从这些格点当中抽出一个赋值为2或4即可。
对应的代码如下
void Generate(int(&MAP)[MAP_SIZE][MAP_SIZE]) {
/*在地图中生成随机数*/
//判断生成2还是4
int randNum[2] = { 2, 4 };
int chose24;
if (Rand021() <= 0.5) chose24 = 2;
else chose24 = 4;
int noZeroMAP[MAP_SIZE*MAP_SIZE][2], noZeroNum = 0;
//将不是0的格子保存下来, 从中选出一个生成
for (int i = 0; i < MAP_SIZE; i++) {
for(int j = 0; j < MAP_SIZE; j++) {
if (MAP[i][j] != 0) {
noZeroMAP[noZeroNum][0] = i;
noZeroMAP[noZeroNum][1] = j;
noZeroNum++;
}
}
}
int generatePos = RandA2B(0, noZeroNum-1);
MAP[noZeroMAP[noZeroNum][0]][noZeroMAP[noZeroNum][1]] = chose24;
}
这里用到的Rand021()是随机生成0到1之间的随机浮点数,和RandA2B()是随机生成A到B之间的随机整数,具体定义如下
//Rand.cpp
#include
#include
double Rand021() {
srand((int)time(0));
return rand() / double(RAND_MAX);
}
int RandA2B(int A, int B) {
srand((int)time(0));
return rand() % (B - A + 1) + A;
}
显示地图相当于没什么技术含量了,就是简单粗暴的直接输出就好。不过为了地图更好看,将0替换成-进行输出。
void ShowMap(int(&MAP)[MAP_SIZE][MAP_SIZE], int score) {
/*输出地图*/
cout << "Now Your Game Map is: " << endl;
cout << "---------------------------------" << endl;
for (int i = 0; i < MAP_SIZE; i++) {
for (int j = 0; j < MAP_SIZE; j++) {
if (MAP[i][j] == 0) cout << " " << "-";
else cout << " " << MAP[i][j];
}
cout << endl;
}
cout << "---------------------------------" << endl;
cout << "Now Your Score is: " << score << endl;
cout << "Plase Move Map(up:w down:s left:a right:d): ";
}
下一部分就是移动地图的内容了,内容比较多,所以我放在下一篇文章中进行讲解。
如果有帮助的话还麻烦点个关注点个赞噢~
全部代码放在我的GitHub中。