用c++实现游戏2048---前三步(1)

写在前面

在知乎上偶尔看到有人利用写这种小程序练手,正好最近刚考完期末考试,所以就花了一个晚上写了一下,也简单的写了一个2048.

以下是效果图


2048游戏

之前没有用c++写过比较大型的内容,对c++的理解也不是很深。所以经过这一次编写,对游戏算法的理解以及c++多文件之间的调用有了更深刻的理解。

在写之前,我先简单的构思了以下整个游戏会分成哪几个部分,私以为可以简单的分为六个部分:

  1. 初始化游戏地图
  2. 在游戏地图内格子随机生成一个数字
  3. 在屏幕上显示出地图
  4. 玩家输入操控指令
  5. 程序对玩家的指令进行相应移动与合并
  6. 判断游戏是否结束,若没有结束就跳到2,否则跳出

我发现这六点当中,只有第5点最有难度,也就是如何去移动整个表盘中的元素,如何判别是否可以合并,四个方向上的移动合并有什么共同点和差别,如何合并等内容。其他5点就很简单了,基本上没有这么复杂的逻辑。

下面我就以这6点分别进行讲解。

主程序

将主程序放在单独的一个文件内

//source.cpp
#include <iostream>
#include <Windows.h>
#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.hParameter.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 <cstdlib>
#include <ctime>

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中。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,099评论 18 139
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    X先生_未知数的X阅读 15,937评论 3 118
  • 到商代,中国的青铜文明已走向了繁荣时期。 商代的青铜器种类繁多,按用途分为礼器、兵器、工具、乐器、车马器及杂器。礼...
    阿建w阅读 869评论 2 3
  • 我不知道我为什么会对端午节有这么浓厚的感情,大概是因为从儿时开始记事起,每到这天早上起来洗脸发现脸盆里多了那几株艾...
    冷冬京阅读 220评论 0 0
  • 这几年移动互联网站在了浪潮之巅,行业发展的速度远大于“人才”养成的速度。创业公司如雨后春笋般野蛮生长,几乎所有的互...
    馒头石头木头阅读 29,069评论 11 135