• 威老的迷宫探险


    最近在学习面向对象的方法,强迫自己用面向对象的方法构建程序,于是便有了这个面向对象的迷宫。

    在设计这个迷宫的初期,一共想到了4对象:点(Point)、组成迷宫的格子(Square)、迷宫(Maze)、探险者(Exploer)。

    后来发现前两个类有点鸡肋了,删掉。剩下两个对象迷宫(Maze)、探险者(Exploer),这样写起来轻松些。

    代码量约有300行,总耗时7、8个小时的样子吧。

     

    好了,现在我们有两个类,开始设计。

    迷宫(Maze):

    首先,迷宫有许多个格子,每个格子不是墙壁就是可行走。我们约定 '0'为可走,'1'为墙壁。

    为了方便,我定死了迷宫的最大长宽。(⊙o⊙)…别揍我啊。。。

    迷宫应该有出入口,一开始我想到了我用数组entrance[2]以及exit[2]来表示,下标为0就是x坐标,下标为1是y坐标。但是这样做的话,语义上相对难理解,所以最终我还是选择了entrance_x,entrance_y,exit_x,exit_y这样的形式。

    接下来是代码,头文件。

    /*maze.h*/

    #include<iostream>
    #include
    <fstream>
    using namespace std;

    /*迷宫*/
    class Maze
    {
    private:
    int height,width; //迷宫的高和宽
    char board[50][50]; //迷宫体,'0'为可走,'1'为墙壁

    int entrance_x,entrance_y; //入口
    int exit_x,exit_y; //出口

    public:
    Maze();
    //默认的构造,随机创建迷宫
    Maze(char txtFileName[]); //从文件流读入(文件必须为文本文档)
    display(); //显示迷宫
    int getSquareType(int x, int y); //根据位置获取格子类型

    int setEntrance(int x, int y){entrance_x = x; entrance_y = y;};//设置入口
    int getEntrance_x();
    int getEntrance_y();

    int setExit(int x, int y){exit_x = x; exit_y = y;}; //设置出口
    int getexit_x();
    int getexit_y();
    void mark(int x, int y, char mk);//标记的位置(x,y) ,标记的符号
    };

     

     

    其中的mark()是为了允许探险者标记迷宫提供的。

    接下来maze.cpp

    Maze()随机建立迷宫还没有实现(日后再说了)。

    约定迷宫以ascii码存储,Maze()动态读取文本的内容。

    /*maze.cpp*/

     

    #include<iostream>
    #include
    <fstream>
    #include
    <string>
    #include
    "maze.h"
    using namespace std;



    Maze::Maze(
    char txtFileName[])
    {
    ifstream
    in(txtFileName);
    char str[50];
    int i,j;
    for(i=0; in>>str; i++) //读入一行
    {
    for(j=0; str[j]!='\0'; j++) //判断是否已经读到行末
    {
    board[i][j]
    =str[j]; //每一个字符存进一个格子
    }
    }
    height
    = i; //设置迷宫的高
    width = j; //设置迷宫的宽
    entrance_x = 1; //设置迷宫的入口x坐标(默认值)
    entrance_y = 1; //设置迷宫的入口y坐标(默认值)
    exit_x = width - 2; //设置迷宫的出口x坐标(默认值)
    exit_y = height - 2; //设置迷宫的出口y坐标(默认值)
    }


    Maze::display()
    {
    for(int i=0; i < height; i++)
    {
    for(int j=0; j < width; j++)
    cout
    <<board[i][j];
    cout
    <<endl;
    }
    }

    int Maze::getSquareType(int x, int y)
    {
    return board[y][x];
    /*
    这里的x,y位置应该相反。
    因为坐标轴上(x,y)的位置在数组中为第y行第x列
    */
    }

    int Maze::getEntrance_x()
    {
    return entrance_x;
    }

    int Maze::getEntrance_y()
    {
    return entrance_y;
    }

    int Maze::getexit_x()
    {
    return exit_x;
    }

    int Maze::getexit_y()
    {
    return exit_y;
    }

    void Maze::mark(int x, int y, char mk)
    {
    board[y][x]
    = mk;
    }

     

     

    迷宫构建完毕!

    接下来就是造访这座迷宫的探险者了。

    功能分得十分细,连检查某个方向都单独做了类,但是对外部只提供了一个函数:goAhead()。我的意思是你只能叫这个人去探险,而不能命令他做其他事情。

    /*explorer.h*/

     

    #include<iostream>
    #include
    "maze.h"
    #include
    <stack>
    using namespace std;

    /*探险家*/
    class Explorer
    {
    private:
    int current_x,current_y;//当前位置。
    Maze * explored_Maze;//被探访的迷宫在探险者大脑里的反映。board中标记为' '(空格)表示走过
    stack<int> memory;//存储自己的行走路线的栈,我这里只记录每次行走的方向。

    bool IsInExit(); //检查是否已经到达终点
    int searchAround(); //搜索四周,以寻找下一个路径点。四个方向东、南、西、北。
                      //分别返回1、2、3、4,无路可走返回-1,到达终点返回0。
    bool IsEastWalkable(); //检查东面是否可行走
    bool IsSouthWalkable(); //检查南面是否可行走
    bool IsWestWalkable(); //检查西面是否可行走
    bool IsNorthWalkable(); //检查北面是否可行走
    bool checkWalkable(int x, int y); //检查指定位置是否可行走
    void walkTowards(int direction); //往某个方向行走,direction为方向
    int walkToNext(); //找到下一个点并移动到下一个点去。
    void walkTo(int x, int y); //行走到某个位置,direction为方向
    void mark(char mark); //在原地做个标记
    bool goBack(); //往回走,返回值表示 往回走 成功或者失败。

    public:
    Explorer(Maze
    * explored_maze)
    {
    explored_Maze
    = explored_maze;
    memory.push(
    0);
    current_x
    = explored_Maze->getEntrance_x();
    current_y
    = explored_Maze->getEntrance_y();
    };
    //构造函数
    int goAhead(); //一路寻路到尽头

    int getPosition_x();
    int getPosition_y();
    };

     

     

    功能分得这么细,我想也不需要太多啰嗦啦。

    /*explorer.cpp*/

     

    #include<iostream>
    #include
    "explorer.h"

    bool Explorer::IsInExit()
    {
    if(current_x == explored_Maze->getexit_x() && current_y==explored_Maze->getexit_y())
    return true;
    else
    return false;
    }

    int Explorer::searchAround()
    {
    if(IsInExit())//已经到出口了
    {
    // cout<<"InExit"<<endl;
    return 0;
    }

    if(IsEastWalkable())
    {
    // cout<<"→";
    return 1;
    }
    else if(IsSouthWalkable())
    {
    // cout<<"↓";
    return 2;}
    else if(IsWestWalkable())
    {
    // cout<<"←";
    return 3;
    }
    else if(IsNorthWalkable())
    {
    // cout<<"↑";
    return 4;
    }
    return -1;
    }

    bool Explorer::IsEastWalkable()
    {
    if(checkWalkable(current_x+1, current_y))
    {
    return true;
    }
    else
    return false;
    }

    bool Explorer::IsSouthWalkable()
    {
    if(checkWalkable(current_x,current_y+1))
    {
    return true;
    }
    else
    return false;
    }

    bool Explorer::IsWestWalkable()
    {
    if(checkWalkable(current_x - 1,current_y))
    {
    return true;
    }
    else
    return false;
    }

    bool Explorer::IsNorthWalkable()
    {
    if(checkWalkable(current_x,current_y-1))
    {
    return true;
    }
    else
    return false;
    }

    bool Explorer::checkWalkable(int x, int y)
    {
    if(explored_Maze->getSquareType(x, y) == '0')
    return true;
    else
    return false;
    }

    void Explorer::walkTowards(int direction)
    {
    int next_x=current_x;
    int next_y=current_y;
    switch(direction)
    {
    case 1: next_x++; break;//
    case 2: next_y++; break;//
    case 3: next_x--; break; //西
    case 4: next_y--; break; //
    }
    walkTo(next_x, next_y);
    //走到下一点
    memory.push(direction);//记住自己走的方向
    }

    void Explorer::walkTo(int next_x, int next_y)
    {
    mark(
    ' '); //做上“走过”(空格)标记
    current_x = next_x;
    current_y
    = next_y;
    mark(
    'c'); //做上“当前位置”(字母c)标记,以代表探险者当前位置
    }

    int Explorer::walkToNext()
    {
    int nextDirection = searchAround();
    if(nextDirection == -1)
    {
    if(goBack())
    return 0;//可以往后退
    else
    return -1;//已经退回起点了,迷宫无解
    } //无路可走
    if(nextDirection == 0) return 1; //到达终点
    walkTowards(nextDirection);
    return 0;//移动到下一点
    }

    int Explorer::getPosition_x()
    {
    return current_x;
    }

    int Explorer::getPosition_y()
    {
    return current_y;
    }

    int Explorer::goAhead()
    {
    int walkResult;
    for(int i=0;; i++)
    {
    walkResult
    = walkToNext();
    if( walkResult == 1)
    {
    return 1;//到达终点
    }
    if( walkResult == -1)
    {
    return -1;//找不到出口
    }
    system(
    "pause"); //按任意键继续
    system("cls"); //清屏
    explored_Maze->display(); //重画迷宫
    // cout<<current_x<<' '<<current_y<<endl;
    }
    return 1;
    }

    void Explorer::mark(char mk)
    {
    explored_Maze
    ->mark(current_x, current_y, mk);
    }

    bool Explorer::goBack()//可以后退返回true,无法后退,即已经回到起点,则返回false
    {
    // cout<<memory.top();
    if(memory.top() == 3)//若来的时候是从东边来,返回东边的那一格。
    walkTo(current_x + 1, current_y);
    else if(memory.top() == 2)
    walkTo(current_x, current_y
    - 1);
    else if(memory.top() == 1)
    walkTo(current_x
    - 1, current_y);
    else if(memory.top() == 4)
    walkTo(current_x, current_y
    + 1);
    else if(memory.top() == 0)
    {
    return false;
    }
    memory.pop();
    //把自己记录的路线做一下修改。
    return true;
    }

    最后,再次感受一下面向对象的强大魅力。

    简洁明了的main.cpp,都不知道什么还有地方需要解说了。

    ps:yy无罪。

    /*main.cpp*/

    #include"explorer.h"
    void main()
    {
    char filename[30] = "maze.data";
    Maze mz(filename);
    //创建迷宫
    cout<<"据乾陵《述圣纪》碑记载,唐高宗临终遗言,要求将他生前所珍爱的书籍、字画等全部埋入陵中。武则天营建乾陵的目的是为了报答唐高宗的知遇之恩,因此,陪葬入乾陵的稀世珍宝一定不少。这是一个满藏无价瑰宝的地宫。\n古往今来,多少歹人绞尽脑汁,费尽心思找不到的乾陵地宫墓道口,在上个世纪50年代末被几个农民意外发现。"<<endl;
    mz.display();
    //打印迷宫
    Maze weilaosMz = mz;
    Explorer weilao(
    &weilaosMz);//创建探险者
    cout<<"现在weilao,一个特别牛X的考古学家来到了这里,一场惊心动魄的探险开始了……"<<endl;
    int weilaosExplorResult = weilao.goAhead();//探险者走迷宫
    if(weilaosExplorResult == 1) cout<<"weilao找到了大量宝藏!"<<endl;
    if(weilaosExplorResult == -1) cout<<"weilao空手而归。。。"<<endl;
    cin
    >>weilaosExplorResult;
    // weilaosMz.display();
    }

  • 相关阅读:
    2019年面试题1
    面试题
    vsftp多个用户公享同一个文件,但是权限不同
    centos7搭建ftp
    安装v2ra y
    centos7安装lamp
    日升昌面试题
    一些插件
    面试被怼集(字节跳动篇)
    TOMCAT原理详解及请求过程(转载)
  • 原文地址:https://www.cnblogs.com/weilao/p/obj_maze.html
Copyright © 2020-2023  润新知