这段时间,熟悉了c++ class后,我决定可以开始写一个走迷宫游戏了。
准备开始
首先是流程:1.获得用户名称。2.让用户自定义迷宫地图。3.生成地图。4.接受用户输入,移动小人。5.判断是否到达目的地。
流程图:
我们将所有文件放入Mazeman-text文件夹中,下面分析一下文件结构:
接下来就是着手实现了。
实现MAN类库
打开man.h文件夹,将基本内容写好
#ifndef MAN_H #define MAN_H #endif
为了防止重名,可以在其中在加上一个namespace。
namespace MAN { }
接着编写类:man。
这个类首先需要两大类:public以及private。
public中含有构造函数与成员函数,private含有该类所需的数据。
来看private中,需要三个数据:坐标,显示的样子,与已走步数。
存储坐标,最好自定义一个结构体专门存放x,y坐标。在namespace中添加POS结构体。
struct POS { int x; int y; };
显示的样子,因为我们使用一个字符代表一个人,所以char类型是最好的。而已走步数,不用说,就是int类型,因为步数不可能是几点几形式的小数。
实现该类中的private:
class man { public: private: POS org; char name; int step = 0;// step从0开始计数 };
然后可以编写public中所需的成员函数。
第一点,构造函数,是必不可少的,其中可以设置坐标、样式。
其二,要有移动操作,可以设置坐标,。
最后,需要有两个分别获得坐标、步数的函数。
man(int x_,int y_,char name_); bool move(int x_,int y_); POS getPos(); int getStep();
这下,整个.h文件算是完成了,全部代码如下:
#ifndef MAN_H #define MAN_H namespace MAN { struct POS { int x; int y; }; class man { public: man(int x_,int y_,char name_); bool move(int x_,int y_); POS getPos(); int getStep(); private: POS org; char name; int step = 0; }; } #endif
然后编写man.cpp。
引入头文件,并使用命名空间为MAN。定义全局变量与数组,MAP_SIZE、map[MAP_SIZE][MAP_SIZE]。然后是一个update()函数。
#include <iostream> #include <cstring> #include "man.h" using namespace MAN; const int MAP_SIZE = 10; static char map[MAP_SIZE][MAP_SIZE]; void update();
实现update函数,这个函数是为了刷新屏幕,显示迷宫状态。而map数组就是为了存放迷宫的。第一步,为了是图像看起来是动的,需要清屏,调用系统命令。
system("clear");// 为mac或linux system("cls")// 为windows
接着就是遍历map,输出每一项值。就可以使用双层for循环。
for (int i = 0 ; i < MAP_SIZE ; i++) { for (int j = 0 ; j < MAP_SIZE ; j++){ std::cout << map[i][j] << " "; } std::cout << std::endl; }
注意了,此时应用的是命名空间MAN,而非std,所以cout、endl前std::是必不可少的。
然后将目光转向class:man的构造函数,查看前面写的,该函数有三个参数:int x_,int y_,char name_。首先,查看地图上这个位置是否为空,为了输入、输出方便,地图上的空地使用"."表示。
if (map[y_][x_] == '.') { // 进行设置 }
为对象设置基本属性,并update。
name = name_; org.x = x_; org.y = y_; map[org.y][org.x] = name; update();
接着,move函数要闪亮登场了,首先判断,x,y是否合法:
if (y_ >= 10 || y_ < 0 || x_ >= 10 || x_ < 0){ std::cout << "Can't move!" << std::endl; return false; } if (map[y_][x_] != '.'){ std::cout << "Can't move!" << std::endl; return false; }
然后移动,并将之前的位置设为空位置。
map[org.y][org.x] = '.'; org.x = x_; org.y = y_; map[org.y][org.x] = name;
在测试时,我们发现,这样好像仍然无法移动,这是为什么呢?是因为我们忘了update。
再添加代码:
update();
不过,我们还忘了一件事,忘记将已走步数增加一了,所以在update();与map[org.y][org.x] = name;之间,再添加一行代码:
step++;
然后编写两个get函数,都十分简单,共计只有六行代码:
int man::getStep(){ return step; } POS man::getPos(){ return org; }
全部代码:
#include <iostream> #include <cstring> #include "man.h" using namespace MAN; const int MAP_SIZE = 10; static char map[MAP_SIZE][MAP_SIZE]; void update(); void update() { system("clear"); for (int i = 0 ; i < MAP_SIZE ; i++) { for (int j = 0 ; j < MAP_SIZE ; j++) { std::cout << map[i][j] << " "; } std::cout << std::endl; } } man::man(int x_,int y_,char name_){ if (map[y_][x_] == '.'){ name = name_; org.x = x_; org.y = y_; map[org.y][org.x] = name; update(); } } bool man::move(int x_,int y_){ if (y_ >= 10 || y_ < 0 || x_ >= 10 || x_ < 0){ std::cout << "Can't move!" << std::endl; return false; } if (map[y_][x_] != '.'){ std::cout << "Can't move!" << std::endl; return false; } map[org.y][org.x] = '.'; org.x = x_; org.y = y_; map[org.y][org.x] = name; step++; update(); } int man::getStep(){ return step; } POS man::getPos(){ return org; }
这第二步也终于完成了,可以将目光返回到main.cpp中了。
现在也不早了,明天再更。
[未完待续]