不再依赖A*,利用C++编写全新寻路算法
分类:C/C++
2013-07-02 19:24
1841人阅读
评论(8)
收藏
举报
C++
算法
寻路
目录(?)[+]
一,说在前面的话
大概在半年前,看见一到信息竞赛题:在任意方格阵中设置障碍物,确定起始点后,求这两点之间路径。当时觉得蛮有意思的,但是没有时间去做,今天花了两个小时来实现它。据说有一个更高级的寻路算法叫做a*,那我就把我的算法叫做W*。 这个算法主要用于解迷宫和实现战棋游戏(SLG)的寻路。
首先讲一讲我的算法的思路:
我们先确定起始点,然后从起点出发,按一定顺序判断这个位置上下左右是否有可走的位置,如果发现有可走的位置,则递归进入该位置的判断。在递归的同时记录所走的路线。当发现某个位置无路可走,则删除路线的最后一个位置并返回上级位置进行判断。如此反复尝试最终找到路线。
说了这么多,就来讲解一下代码吧。
二,讲解部分
包含头文件(全部都是stl中的):
[cpp]
view plain
copy
- #include<map>
- #include<vector>
- #include<iostream>
为几个冗长的类型重命名,用来使后来的代码更明了。
copy
typedefunsignedintuint;
- typedefstd::vector<int>CRow;
- //相当于把CLabyrinth定义成一个整型的二维数组
- typedefstd::vector<CRow>CLabyrinth;
定义一个类类型表示二维数组中的位置:
copy
classCPoint
- {
-
- public:
- intcol;//列
- introw;//行
-
- public:
- //构造函数,接受行和列的初始化
- CPoint(intc=0,intr=0)
- :col(c)
- ,row(r)
- {
- return;
- }
- //赋值操作
- CPoint&operator=(constCPoint&pt)
- col=pt.col;
- row=pt.row;
- return*this;
- //比较操作
- booloperator==(returncol==pt.col&&row==pt.row;
- //判断该位置是否合法
- boolallRight()
- returncol>=0&&row>=0;
- };
- typedefstd::vector<CPoint>CRoute;
然后到了核心类类型CLabyrinthAI
copy
{
- protected:
- //装有迷宫数据的二维数组
- CLabyrinthm_xLabyrinth;
- //起点位置
- CPointm_ptBeginning;
- //终点位置
- CPointm_ptEnding;
- //记录路线的数组
- CRoutem_vRoute;
- //枚举表示起点、终点的值
- enum{Beginning=-1,Ending=-2};
- //枚举表示障碍物与可走区的值
- enum{CanntGo=0,CanGo=1};
- //枚举是否找到终点
- enum{FoundEnding=0,NotFoundEnding=1};
- //判断某个位置是否已在路线数组中,用于别走重复的路
- boolisRepeat(boolbRes=false;
- CRoute::iteratorit=m_vRoute.begin();
- for(;it!=m_vRoute.end();it++){
- CPointpt0=*it;
- if(pt0==pt){
- bRes=true;
- break;
- }
- returnbRes;
- //将某一位置加入路线数组
- voidadvance(constCPoint&ptTo)
- m_vRoute.push_back(ptTo);
- //将路线数组最后一个位置弹出
- voidback()
- m_vRoute.pop_back();
- //判断某一位置是否是起点
- boolisBeginning(constCPoint&pt)
- returnm_ptBeginning==pt;
- //判断某一位置是否是终点
- boolisEnding(returnm_ptEnding==pt;
- /*-----------------核心算法------------------------*/
- //判断某一位置是否可以向上移动
- CPointcanUp(constCPoint&ptCurrent)//接受当前位置
- CPointptRes=CPoint(-1,-1);
- intcol=ptCurrent.col;
- introw=ptCurrent.row;
- if(row>0){
- CPointptNext=CPoint(col,row-1);//上移后位置
- //检查上移后位置是否已经走过,以免寻路过程中绕圈子进入死循环
- if(!isRepeat(ptNext)){
- //获得迷宫二维数组中上移后位置的属性(起点、终点、可走、障碍)
- intnAttr=m_xLabyrinth[ptNext.row][ptNext.col];
- //如果上移后位置为可走或到达终点,则设定返回值为上移后的位置
- if(nAttr==CanGo||nAttr==Ending){
- ptRes=ptNext;
- returnptRes;//如果上移后位置不可走则返回非法的位置
- //以下判断某一位置可否移动的原理大致与上相同,就不多说了
- //判断某一位置是否可以向下移动
- CPointcanDown(constCPoint&ptCurrent)
- CPointptRes=CPoint(-1,-1);
- intcol=ptCurrent.col;
- introw=ptCurrent.row;
- if(row<m_xLabyrinth.size()-1){
- CPointptNext=CPoint(col,row+1);
- intnAttr=m_xLabyrinth[ptNext.row][ptNext.col];
- returnptRes;
- //判断某一位置是否可以向左移动
- CPointcanLeft(if(col>0){
- CPointptNext=CPoint(col-1,row);
- //判断某一位置是否可以向右移动
- CPointcanRight(if(col<m_xLabyrinth[0].size()-1){
- CPointptNext=CPoint(col+1,0); background-color:inherit">/*
- *判断某一位置是否可以向四周移动,如果判断到某一位置可以移动,则递归进入该位置判断。
- *如果该位置没有任何位置可移动,则返会上级位置并且调用back函数。如果走到终点,
- *则立刻返回枚举值FoundEnding,上级位置检查到返回值为FoundEnding,也直接返回。
- */
- intfindRoute(intnRes=NotFoundEnding;//默认返回值为没有找到终点
- CPointptNext=CPoint(-1,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> advance(ptCurrent);//将当前位置加入路线数组
- //判断当前位置是否是终点,如果是终点则不进行下面的判断,将返回值设置为找到终点
- if(isEnding(ptCurrent)){
- nRes=FoundEnding;
- }else{//按上左下右的顺序判断有无可走路径
- //尝试向上
- ptNext=canUp(ptCurrent);//获取向上走后的位置
- //判断向上走后的位置是否是合法位置,若不合法,则表明上走到了迷宫的边缘,或者上面没有可走路径
- if(ptNext.allRight()){
- //上述判断成功,则将向上移动后的位置传入给自己,进行递归。当该函数退出,查看返回值是否为找到终点。若找到终点则立刻返回FoundEnding
- if(findRoute(ptNext)==FoundEnding){
- returnnRes;
- //下列尝试四周位置是否可走的代码与上述大体相同,就不多说了
- //尝试向左
- ptNext=canLeft(ptCurrent);
- if(findRoute(ptNext)==FoundEnding){
- nRes=FoundEnding;
- returnnRes;
- //尝试向下
- ptNext=canDown(ptCurrent);
- //尝试向右
- ptNext=canRight(ptCurrent);
- //检测是否到达终点,若没有到达终点,则立刻从路线表中删除该位置
- if(nRes!=FoundEnding){
- back();
- //构造函数
- CLabyrinthAI()
- return;
- //带有初始化迷宫数组构造函数
- CLabyrinthAI(constCLabyrinth&vLabyrinth)
- m_xLabyrinth=vLabyrinth;
- getBeginning();
- getEnding();
- //初始化迷宫数组
- voidsetLabyrinth(//查找起点
- voidgetBeginning()
- uintnRow=0;
- for(;nRow<m_xLabyrinth.size();nRow++){
- CRowxRow=m_xLabyrinth[nRow];
- uintnCol=0;
- for(;nCol<xRow.size();nCol++){
- intn=xRow[nCol];
- if(n==Beginning){
- m_ptBeginning=CPoint(nCol,nRow);
- break;
- //查找终点
- voidgetEnding()
- uintnRow=0;
- for(;nRow<m_xLabyrinth.size();nRow++){
- CRowxRow=m_xLabyrinth[nRow];
- uintnCol=0;
- for(;nCol<xRow.size();nCol++){
- intn=xRow[nCol];
- if(n==Ending){
- m_ptEnding=CPoint(nCol,nRow);
- //调用核心算法函数,输出获得的路线
- voidAI()
- findRoute(m_ptBeginning);
- if(!m_vRoute.empty()){
- CPointpt=*it;
- std::cout<<"("<<pt.row<<","<<pt.col<<")";
- if(it!=m_vRoute.end()-1){
- std::cout<<"->";
- else{
- std::cout<<std::endl;
- //如果没有找到路线到达终点
- std::cout<<"Sorrycannotfileanywaystogetending."<<std::endl;
- };
代码都加上了注释,大家可以慢慢看。
如果上述过程把你搅晕了,那就用图来为你解答吧。
(编辑:安卓应用网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|