zoukankan      html  css  js  c++  java
  • 威老的迷宫探险

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

    在设计这个迷宫的初期,一共想到了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();
    }

  • 相关阅读:
    利用DTrace实时检测MySQl
    改进MySQL Order By Rand()的低效率
    RDS for MySQL查询缓存 (Query Cache) 的设置和使用
    RDS For MySQL 字符集相关说明
    RDS for MySQL 通过 mysqlbinlog 查看 binlog 乱码
    RDS for MySQL Mysqldump 常见问题和处理
    RDS for MySQL Online DDL 使用
    RDS MySQL 表上 Metadata lock 的产生和处理
    RDS for MySQL 如何使用 Percona Toolkit
    北京已成为投融资诈骗重灾区:存好骗子公司黑名单,谨防上当!
  • 原文地址:https://www.cnblogs.com/weilao/p/obj_maze.html
Copyright © 2011-2022 走看看