迷宫寻路的等高线算法

 对于迷宫寻路的一般算法是用递归实现,或者用栈来实现,二者其实基本思路都一样:由起点开始,逐个点遍历上下左右,重复遍历率高,效率一般。还有就是A×算法,不过掌握起来难度较大。现介绍一种效率高,同时又较简单的寻路算法:等高线算法。

所谓等高线算法,主要原理是:由终点开始延伸,每个点的四个方向相临点属于同一个高度,将每个点到终点的最小距离记录到辅助数组的相应位置,如果有权值的话每走一步加的是权值,否则直接加加,这样所有位置到终点的距离都在辅助数组里面,最后只要到辅助数组里面去收集最短路径就可以了。

此算法同样适用于有障碍物的地图寻路,这里只给出了四联通的,此算法同样适合八个方向的情况。算法代码如下:

//  MapContour.cpp : 定义控制台应用程序的入口点。
// 算法原理: 从终点往外开始延伸, 直到起始点,
//         再从起始点选择最小的号码, 逐步按照路径行走, 回到终点,即算完成
#include  < iostream >
#include 
< queue >

using   namespace  std;

#define  D_MapWidth    15
#define  D_MapHeight 13
#define  D_MapSize    (D_MapWidth * D_MapHeight)

// 数组MapData记录地图中的原始数据;
// 1表示有路可走;
// 0表示没有路相通
int  MapData[D_MapHeight  *  D_MapWidth]  =  
{
    
1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,
        
1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,
        
1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,
        
1,1,1,0,0,1,1,1,1,1,0,1,1,1,1,
        
1,1,0,0,0,1,1,1,0,0,0,1,1,1,1,
        
1,1,1,1,1,1,1,0,0,0,1,1,1,1,0,
        
0,1,1,1,1,1,1,0,0,1,1,1,1,0,0,
        
0,1,1,1,1,1,0,0,1,1,1,1,0,0,0,
        
0,0,1,1,1,0,0,1,1,1,0,0,0,0,0,
        
0,0,0,1,0,0,0,1,1,1,0,1,1,1,1,
        
0,0,0,0,0,1,1,1,1,1,0,1,1,1,0,
        
0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,
        
0,0,0,0,1,1,1,1,1,1,1,0,0,0,0
}
;
// 计算用的地图数组
// BackupMap数组记录地图上的各点到达起始点的最小步数;
int  BackupMap[D_MapWidth  *  D_MapHeight];


// 记录路径的数组
// Path数组依次记录:结果路径的顶点;
int  Path[D_MapHeight  *  D_MapWidth];
// 为Path数组的容量;
int  CountOfPath  =   0 ;

bool  SetpMaker( int  Position,  int  StepNo,  int  CheckPosition);
void  QuickMapping( int  Pos_Target,  int  Pos_Start);
void  PathRecorder( int  StartPos,  int  TargetPos);
int  GetStep( int  Position,  int   & StepNo);
void  ShowPath( void );

// 由于STL的queue的函数都是正交的,
// 将Pop函数与front函数组合返回队列是非为空;
template < typename T >
bool  IsNullAfterPop(queue < T >   * que, T &  current)
{
    
if (que->empty())
    
{
        
return false;
    }

    current 
= que->front();
    que
->pop();
    
return true;
}


int  main()
{
    
//起点,终点;
    int Pos_Start = (10 * D_MapWidth) + 12;
    
int Pos_Target = (1 * D_MapWidth) + 1;

    
bool Found = false;
    
int Step = 1;
    
int Mapsize = D_MapSize;

    
//初始化辅助数组;
    memset(BackupMap, 0sizeof(int)* Mapsize);
    
    
//将每个位置到终点的距离写到辅助数组BackupMap里面
    QuickMapping(Pos_Target, Pos_Start);
    
//输出辅助数组内容:
    for (int i = 0; i < D_MapHeight; i++)
    
{
        
for (int j = 0; j < D_MapWidth; j++)
        
{
            printf(
" %02d", BackupMap[i*D_MapWidth + j]);
        }

        cout 
<< endl;
    }

    
//筛选最小路径
    PathRecorder(Pos_Start, Pos_Target);
    
//显式路径;
    ShowPath();
    
return 0;
}


void  QuickMapping( int  Pos_Target,  int  Pos_Start)
{
    queue
<int>QueA, QueB, *SrcPointer, *DesPointer;
    
int StepNo = 1,
        Position,
        MapSize 
= D_MapWidth*D_MapHeight,
        CurrentPos;

    SrcPointer 
= &QueA;
    DesPointer 
= &QueB;
    SrcPointer
->push(Pos_Target);

    
for (;;)
    
{
        
if ( !IsNullAfterPop(SrcPointer, CurrentPos) )
        
{
            
if (SrcPointer == &QueA)    
            
{
                SrcPointer 
= &QueB;
                DesPointer 
= &QueA;
                StepNo 
++;
            }

            
else
            
{
                SrcPointer 
= &QueA;
                DesPointer 
= &QueB;
                StepNo
++;
            }

            
//两者都空退出;
            if ( !IsNullAfterPop(SrcPointer, CurrentPos) )    
                
return;
        }


        BackupMap[CurrentPos] 
= StepNo;
        
//找到起点;结束;
        if (CurrentPos == Pos_Start)
            
return;
        
        
//To UP
        Position = CurrentPos - D_MapWidth;
        
if (Position >= 0)
        
{
            
if (MapData[Position] != 0)
            
{
                
if (BackupMap[Position] == 0 ||
                    BackupMap[Position] 
> StepNo)
                
{
                    DesPointer
->push(Position);
                }

            }

        }

        
//To DOWN
        Position = CurrentPos + D_MapWidth;
        
if (Position < MapSize)
        
{
            
if (MapData[Position] != 0)
            
{
                
if (BackupMap[Position] == 0 ||
                    BackupMap[Position] 
> StepNo)
                
{
                    DesPointer
->push(Position);
                }

            }

        }

        
//To LEFT
        Position = CurrentPos - 1;
        
if ( (CurrentPos%D_MapWidth) > 0 )
        
{
            
if (MapData[Position] != 0)
            
{
                
if (BackupMap[Position] == 0 ||
                    BackupMap[Position] 
> StepNo)
                
{
                    DesPointer
->push(Position);
                }

            }

        }

        
//To RIGHT
        Position = CurrentPos + 1;
        
if ( (Position%D_MapWidth) < D_MapWidth )
        
{
            
if (MapData[Position] != 0)
            
{
                
if (BackupMap[Position] == 0 ||
                    BackupMap[Position] 
> StepNo)
                
{
                    DesPointer
->push(Position);
                }

            }

        }


    }
//for(;;)
}
// QuickMapping()

// 将理想的点放进Path数组中;
void  PathRecorder( int  StartPos,  int  TargetPos)
{
    
int Step = BackupMap[StartPos];
    
int index = 0;
    
int Pos = StartPos;

    Path[index
++= Pos;

    
do 
    
{
        Pos 
= GetStep(Pos, Step);
        
if (Pos != -1)
        
{
            Path[index
++= Pos;
            
if (Pos == TargetPos)
            
{
                CountOfPath 
= index;
                
return ;
            }

        }

        
else
            
return;

    }
 while(true);
}


// 检查所在位置的四个方向; 找出最小的位置,
// 也就是最短路径的检测方法;
int  GetStep( int  Position,  int   & StepNo)
{
    
int nUp = Position - D_MapWidth;
    
int nDown = Position + D_MapWidth;
    
int nLeft = Position - 1;
    
int nRight = Position + 1;
    
bool Found = false;

    
if (nUp >= 0)
    
{
        
if (BackupMap[nUp] != 0 && BackupMap[nUp] < StepNo)
        
{
            StepNo 
= BackupMap[nUp];
            
return nUp;
        }

    }

    
if (nDown < D_MapSize)
    
{
        
if (BackupMap[nDown] != 0 && BackupMap[nDown] < StepNo)
        
{
            StepNo 
= BackupMap[nDown];
            
return nDown;
        }

    }

    
if ( (Position%D_MapWidth) > 0)
    
{
        
if (BackupMap[nLeft] != 0 && BackupMap[nLeft] < StepNo)
        
{
            StepNo 
= BackupMap[nLeft];
            
return nLeft;
        }

    }

    
if ( (nRight%D_MapWidth) != 0)
    
{
        
if (BackupMap[nRight] != 0 && BackupMap[nRight] < StepNo)
        
{
            StepNo 
= BackupMap[nRight];
            
return nRight;
        }

    }


    
return -1;
}



// 先把BackuoMap数组清空;
// 再根据Path数组将路径的数据写入到BackupMap数组中,
// 最后显示BackupMap[]数组内容;
void  ShowPath( void )
{
    
int Pos;

    memset(BackupMap, 
0sizeof(int* D_MapSize);

    
for (int loop = 0; loop < CountOfPath; loop++)
    
{
        Pos 
= Path[loop];
        BackupMap[Pos] 
= 1;
    }


    cout 
<< " 显示路径 ";
    
for (int loopy = 0; loopy < D_MapHeight; loopy++)
    
{
        
for (int loopx = 0; loopx < D_MapWidth; loopx++)
        
{
            printf(
" %02d", BackupMap[loopy*D_MapWidth + loopx]);
        }

        cout 
<< endl;
    }

}

核心函数QuickMapping()的实现简介:使用两个队列来遍历,为了交换两个队列内容的需要,定义了两个队列指针。原理的话:当前遍历A点,找到其四个方向的点Aup,Adown, Aleft,  Aright,此时A点是源点,而Aup,Adown, Aleft,  Aright都是目标点。但是在下一次Src队列中的源点全部找完后,即Src为空,交换Src与Dest队列的内容,他们就分别都成为源点了,这样继续记录下去。

当来两个队列都为空,或者起点找到,就退出函数。

  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
等高线追踪 基于TIN绘制等高线直接利用原始观测数据,避免了DTM内插的精度损失,因而等高线精度 较高;对高程注记点附近的较短封闭等高线也能绘制;绘制的等高线分布在采样区域内而 并不要求采样区域有规则四边形边界。而同一高程的等高线只穿过一个三角形最多一次, 因而程序设计也较简单。但是,由于TIN的存贮结构不同,等高线的具体跟踪算法跟踪也有 所不同。 基于三角形搜索的等高线绘制算法如下: 对于记录了三角形表的TIN,按记录的三角形顺序搜索。其基本过程如下: 1)对给定的等高线高程h,与所有网点高程zi(i=1,2,?,n),进行比较,若zi=h ,则将zi加上(或减)一个微小正数ε> 0(如ε=10-4),以使程序设计简单而又不影响 等高线的精度。 2)设立三角形标志数组,其初始值为零,每一元素与一个三角形对应,凡处理过的三角形 将标志置为1,以后不再处理,直至等高线高程改变。 3)按顺序判断每一个三角形的三边中的两条边是否有等高线穿过。若三角形一边的两端点 为P1(x1,y1,z1),P2(x2,y2,z2)则 (z1-h)(z2-h)0表明该边无等高线点。 直至搜索到等高线与网边的第一个交点,称该点为搜索起点,也是当前三角形的等高线进 入边、线性内插该点的平面坐标(x,y): 4)搜索该等高线在该三角形的离去边,也就是相邻三角形的进人边,并内插其平面坐标。 搜索与内插方法与上面的搜索起点相同,不同的只是仅对该三角形的另两边作处理。 5)进入相邻三角形,重复第(4)步,直至离去边没有相邻三角形(此时等高线为开曲线 )或相邻三角形即搜索起点所在的三角形(此时等高线为闭曲线)时为止。 6)对于开曲线,将已搜索到的等高线点顺序倒过来,并回到搜索起点向另一方向搜索,直 至到达边界(即离去边没有相邻三角形)。 7)当一条等高线全部跟踪完后,将其光滑输出,方法与前面所述矩形格网等高线的绘制相
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值