C++实战(一):走出迷宫

尼采说,当你凝望深渊良久,深渊亦回望于你。我凝望C++也良久了,现在它终于回望于我,并对我说,别tm看了,赶紧动手多写写代码吧。所以,现在,我开始了C++的实战之路。

本期实践目标

通过让游戏角色自动寻路,走出下图所示的迷宫,来练习C++面向对象之封装的基本知识。

maze

走出迷宫的正确姿势

首先我们得把游戏角色带到迷宫的入口。来到入口之后,伸出右手,就这样一直保持右手扶墙向前走,游戏角色是一定能走到出口。关于这一点,希望没有及时明白过来的读者用鼠标在图上模拟下。当然,能走到出口的前提是迷宫有出口,不然游戏角色会在迷宫里兜一圈,又走回入口点。

姿势太抽象,来点代码能实现的

这又是“伸出右手”,又是”扶墙”的,难道真要画个游戏角色出来,动动手,动动脚么。Of course not.

从代码实践的角度来看,要完成走出迷宫这个目的,需要明确下面几点:

  1. 画出这个迷宫:由于我们画的二维空间的迷宫,所以用一个二维数组存储代表墙和路的字符就OK了。这里我们用字符’H’代表墙,用空格符代表路。charmaze
  2. 定义一个走迷宫的人Mazer:Mazer是我们的游戏角色,显示上我们将用字符’o’来表示,Mazer可以向各个方向移动
  3. Mazer走迷宫的原则(右手原则):优先向右走,其次向前走,再次向左走,若三个方向均无路,则掉头向后走。(读者也可以试试用左手原则来实现,道理是一样的)

写控制台程序的利器

正式开始代码之前,向大家介绍一个写控制台程序非常有用的函数:FillConsoleOutputCharacter

调用FillConsoleOutputCharacter实际上是调用了FillConsoleOutputCharacterW

hConsoleOutput:控制台屏幕缓冲区的句柄

cCharacter:要向控制台缓冲区写入的字符

nLength:要写入字符的长度

dwWriteCoord:一个COORD结构,它指定了要写入的字符的单元格坐标

lpNumberOfCharsWritten:指定接受实际写入到控制台缓冲区的字符数的变量的指针

用代码说话

首先我们定义一个地图类来处理迷宫地图的相关事情(MazeMap.h)

接下来是地图类的具体实现(MazeMap.cpp)

有了地图,我们还需要一个走迷宫的游戏角色Mazer,那么看看Mazer类如何定义(Mazer.h)

ps:除非是专门说明,否则,所有关于上、下、左、右的描述均是电脑屏幕上的上下左右。

Mazer类的具体实现如下(Mazer.cpp):

一切准备就绪,游戏开始(main.cpp)

至此,走出迷宫小游戏完成。为了照顾初学者,代码中我添加了尽可能详细的注释,若废话太多,望见谅。

在 “C++实战(一):走出迷宫” 上有 29 条评论

    1. 根据左手原则或者右手原则,如果地图上没有出口(或者无法到达出口),Mazer最后会走回到入口。也就说不存在走不来的情况

  1. 你好,
    FillConsoleOutputCharacter(handle,m_cPerson,1,m_coorPersonCurrentPos,NULL);
    这一句我是这样写的,但是调试时提示“写入位置 0x00000000 时发生访问冲突”
    这个是什么原因呢?

    1. 不好意思,文章对这个函数的解释带有几个错别字(现已更正)
      FillConsoleOutputCharacter最后一个参数接受实际写入到控制台缓冲区的字符数的变量的指针,你可以申明一个unsigned long变量,然后传入该变量的指针

  2. 博主,你的析构函数中的“delete m_pMap[i];”感觉应该要“delete [] m_pMap[i];”这样写,不然会造成内存的泄露

    1. c++的学习曲线确实相对较陡,所以需要花费更多的精力去学习和练习。我觉得半年时间对c++并不算长,如果你真的对c++很感兴趣,我觉得你肯定能学好,要对自己有信心。c++非常需要漫长的时间积累,加油。
      ps:我也在入门阶段,欢迎交流

  3. m_heroCurrentPosition.X = x;
    m_heroCurrentPosition.Y = y;

    为什么用类成员访问X和Y,并且X,Y不是类成员?

    我脑子里是应该对象访问类成员的呀?

    类成员可以访问其他参数吗?

    1. 我觉得你很有必要先搞清楚什么是类,什么是对象。推荐参考书《C++ primer》(第五版)
      m_heroCurrentPosition的类型是COORD, COORD是win32 api中定义的一个数据结构(参阅https://msdn.microsoft.com/en-us/library/windows/desktop/ms682119(v=vs.85).aspx)
      COORD有两个成员变量,x和y, 通常用来存储坐标信息。

  4. 如果在linux下做同样的操作, 找不到windows.h 这个头文件,怎么办? 您了解在linux哪些头文件可以包含COORD 等需要的信息吗?

  5. class MazeMap
    {
    public:
    MazeMap(char wall);
    MazeMap::~MazeMap(); //总是只提示error: extra qualification ‘MazeMap::’ on member . ‘MazeMap’ [-fpermissive]|
    void setWallChar(char wall);

    求解?

  6. 这样设计会有BUG吧,例如下面这种:
    HHHHHH
    H. H
    HHH. H
    H
    HHHHHHHH
    这样走进去就出不来了,一直在右上角徘徊。

  7. 博主,这个网页是你自己写的吗?刚刚还想注册一个的,emmmmm
    等我把C++学完了,我也要写一个网站给自己用

发表评论

电子邮件地址不会被公开。 必填项已用*标注