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

利用c++实现游戏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中。

没有更多推荐了,返回首页