游戏之寻路算法

      玩游戏的人,都知道游戏中有自动寻路功能,鼠标点击想要到达的终点,主角则会自动走最短的一条路当然同时躲避障碍物,好了,不用多说,直接看效果吧(直观)。

      游戏之寻路算法_第1张图片

     绿色表示起点,红色表示终点,蓝色表示障碍物,而会动的表示从起点运动到终点的轨迹。

     上面用的是寻路算法之曼哈顿算法,具体的表述可以参看http://hi.baidu.com/myfcag/blog/item/48bd91fd012a0bf6fd037fc5.html。别人翻译的很好,完全可以根据他的表述实现自己的寻路算法。下面再贴一张游戏的截面(特别申明:中的素材全部来源于网络 )

     游戏之寻路算法_第2张图片

     截图的效果不太好,不过可以看到主角在后面的移动中可以穿过草丛,因为这里还没加上障碍物的定位和寻路代码,这一部分主要是看看效果,在以后的时间里会贴出完整的代码。(是不是发现游戏的人物是仙剑二中的主角,仙剑经典啊!)

    贴上完整的寻路代码(下面的代码加入了一些在实际应用中的限制程序,理解主要的思想就OK了):

代码
        ///   <summary>
        
///  寻路
        
///   </summary>
         public  List < Point >  PathFinding(Point startPos, Point endPos)
        {
            List
< Point >  ps  =   new  List < Point > ();
            
int  width  =  Matrix.GetLength( 0 );
            
int  height  =  Matrix.GetLength( 1 );
            
// 起点
            startEB  =   new  Entity(startPos);
            startEB.Par 
=   null ;
            
// 终点
            endEB  =   new  Entity(endPos);
            
// 起点加入到开始列表中
            startList.Add(startEB.Pos, startEB);

            Entity s 
=  startList[startEB.Pos];  // 起点

            
if  (s.Pos  ==  endEB.Pos)  return  ps;

            
// 起点的八方向(为代码方便阅读,将8个方向单独处理)
            Entity temp  =   new  Entity();
            Point point 
=   new  Point();
            
bool  upBarrier  =   false ;
            
bool  downBarrier  =   false ;
            
bool  leftBarrier  =   false ;
            
bool  rightBarrier  =   false ;
            
while  (s  !=   null )
            {
                
#region  初始化
                upBarrier 
=   false ;
                downBarrier 
=   false ;
                leftBarrier 
=   false ;
                rightBarrier 
=   false ;
                
#endregion

                
// ****右
                point  =   new  Point(s.Pos.X  +   1 , s.Pos.Y);
                
if  ( ! barrier.ContainsKey(point)  &&   ! closeList.ContainsKey(point)  &&  (point.X  <  width  &&  point.Y  <  height))  // 排除障碍物
                {
                    
if  ( ! startList.ContainsKey(point))
                    {
                        temp 
=   new  Entity(point);  // (*待判断是否越界)
                        temp.Par  =  s;
                        temp.G 
=   1 ;
                        temp.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                        temp.F 
=  temp.G  +  temp.H;
                        startList.Add(point, temp);
                    }
                    
else   // 格子已经包括在开始列表中
                    {
                        Entity exist 
=  startList[point];
                        
if  (s.G  +   1   <  exist.G)
                        {
                            exist.Par 
=  s;
                            exist.G 
=   1 ;
                            exist.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                            exist.F 
=  exist.G  +  exist.H;
                        }
                    }
                }
                
else
                {
                    
if  (barrier.ContainsKey(point))  // 右边有障碍物
                    {
                        rightBarrier 
=   true ;
                    }
                }

                
// ****上
                point  =   new  Point(s.Pos.X, s.Pos.Y  -   1 );
                
if  ( ! barrier.ContainsKey(point)  &&   ! closeList.ContainsKey(point)  &&  (point.X  <  width  &&  point.Y  <  height))  // 排除障碍物
                {
                    
if  ( ! startList.ContainsKey(point))
                    {
                        temp 
=   new  Entity(point);
                        temp.Par 
=  s;
                        temp.G 
=   1 ;
                        temp.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                        temp.F 
=  temp.G  +  temp.H;
                        startList.Add(point, temp);
                    }
                    
else
                    {
                        Entity exist 
=  startList[point];
                        
if  (s.G  +   1   <  exist.G)
                        {
                            exist.Par 
=  s;
                            exist.G 
=   1 ;
                            exist.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                            exist.F 
=  exist.G  +  exist.H;
                        }
                    }
                }
                
else
                {
                    
if  (barrier.ContainsKey(point))  // 上边有障碍物
                    {
                        upBarrier 
=   true ;
                    }
                }

                
// ****左
                point  =   new  Point(s.Pos.X  -   1 , s.Pos.Y);
                
if  ( ! barrier.ContainsKey(point)  &&   ! closeList.ContainsKey(point)  &&  (point.X  <  width  &&  point.Y  <  height))  // 排除障碍物
                {
                    
if  ( ! startList.ContainsKey(point))
                    {
                        temp 
=   new  Entity(point);
                        temp.Par 
=  s;
                        temp.G 
=   1 ;
                        temp.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                        temp.F 
=  temp.G  +  temp.H;
                        startList.Add(point, temp);
                    }
                    
else
                    {
                        Entity exist 
=  startList[point];
                        
if  (s.G  +   1   <  exist.G)
                        {
                            exist.Par 
=  s;
                            exist.G 
=   1 ;
                            exist.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                            exist.F 
=  exist.G  +  exist.H;
                        }
                    }
                }
                
else
                {
                    
if  (barrier.ContainsKey(point))   // 左边有障碍物
                    {
                        leftBarrier 
=   true ;
                    }
                }

                
// ****下
                point  =   new  Point(s.Pos.X, s.Pos.Y  +   1 );
                
if  ( ! barrier.ContainsKey(point)  &&   ! closeList.ContainsKey(point)  &&  (point.X  <  width  &&  point.Y  <  height))  // 排除障碍物
                {
                    
if  ( ! startList.ContainsKey(point))
                    {
                        temp 
=   new  Entity(point);
                        temp.Par 
=  s;
                        temp.G 
=   1 ;
                        temp.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                        temp.F 
=  temp.G  +  temp.H;
                        startList.Add(point, temp);
                    }
                    
else
                    {
                        Entity exist 
=  startList[point];
                        
if  (s.G  +   1   <  exist.G)
                        {
                            exist.Par 
=  s;
                            exist.G 
=   1 ;
                            exist.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                            exist.F 
=  exist.G  +  exist.H;
                        }
                    }
                }
                
else
                {
                    
if  (barrier.ContainsKey(point))
                    {
                        downBarrier 
=   true ;
                    }
                }

                
// ****右上
                point  =   new  Point(s.Pos.X  +   1 , s.Pos.Y  -   1 );
                
if  ( ! barrier.ContainsKey(point)  &&   ! closeList.ContainsKey(point)  &&  (point.X  <  width  &&  point.Y  <  height))  // 排除障碍物
                {
                    
if  ( ! rightBarrier  &&   ! upBarrier)
                    {
                        
if  ( ! startList.ContainsKey(point))
                        {
                            temp 
=   new  Entity( new  Point(s.Pos.X  +   1 , s.Pos.Y  -   1 ));
                            temp.Par 
=  s;
                            temp.G 
=   1.4 ;
                            temp.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                            temp.F 
=  temp.G  +  temp.H;
                            startList.Add(point, temp);
                        }
                        
else
                        {
                            Entity exist 
=  startList[point];
                            
if  (s.G  +   1.4   <  exist.G)
                            {
                                exist.Par 
=  s;
                                exist.G 
=   1.4 ;
                                exist.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                                exist.F 
=  exist.G  +  exist.H;
                            }
                        }
                    }
                }

                
// ****右下
                point  =   new  Point(s.Pos.X  +   1 , s.Pos.Y  +   1 );
                
if  ( ! barrier.ContainsKey(point)  &&   ! closeList.ContainsKey(point)  &&  (point.X  <  width  &&  point.Y  <  height))  // 排除障碍物
                {
                    
if  ( ! rightBarrier  &&   ! downBarrier)
                    {
                        
if  ( ! startList.ContainsKey(point))
                        {
                            temp 
=   new  Entity(point);
                            temp.Par 
=  s;
                            temp.G 
=   1.4 ;
                            temp.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                            temp.F 
=  temp.G  +  temp.H;
                            startList.Add(point, temp);
                        }
                        
else
                        {
                            Entity exist 
=  startList[point];
                            
if  (s.G  +   1.4   <  exist.G)
                            {
                                exist.Par 
=  s;
                                exist.G 
=   1.4 ;
                                exist.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                                exist.F 
=  exist.G  +  exist.H;
                            }
                        }
                    }
                }

                
// ****左上
                point  =   new  Point(s.Pos.X  -   1 , s.Pos.Y  -   1 );
                
if  ( ! barrier.ContainsKey(point)  &&   ! closeList.ContainsKey(point)  &&  (point.X  <  width  &&  point.Y  <  height))  // 排除障碍物
                {
                    
if  ( ! leftBarrier  &&   ! upBarrier)
                    {
                        
if  ( ! startList.ContainsKey(point))
                        {
                            temp 
=   new  Entity(point);
                            temp.Par 
=  s;
                            temp.G 
=   1.4 ;
                            temp.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                            temp.F 
=  temp.G  +  temp.H;
                            startList.Add(point, temp);
                        }
                        
else
                        {
                            Entity exist 
=  startList[point];
                            
if  (s.G  +   1.4   <  exist.G)
                            {
                                exist.Par 
=  s;
                                exist.G 
=   1.4 ;
                                exist.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                                exist.F 
=  exist.G  +  exist.H;
                            }
                        }
                    }
                }

                
// ****左下
                point  =   new  Point(s.Pos.X  -   1 , s.Pos.Y  +   1 );
                
if  ( ! barrier.ContainsKey(point)  &&   ! closeList.ContainsKey(point)  &&  (point.X  <  width  &&  point.Y  <  height))  // 排除障碍物
                {
                    
if  ( ! leftBarrier  &&   ! downBarrier)
                    {
                        
if  ( ! startList.ContainsKey(point))
                        {
                            temp 
=   new  Entity(point);
                            temp.Par 
=  s;
                            temp.G 
=   1.4 ;
                            temp.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                            temp.F 
=  temp.G  +  temp.H;
                            startList.Add(point, temp);
                        }
                        
else
                        {
                            Entity exist 
=  startList[point];
                            
if  (s.G  +   1.4   <  exist.G)
                            {
                                exist.Par 
=  s;
                                exist.G 
=   1.4 ;
                                exist.H 
=  Math.Abs(point.X  -  endEB.Pos.X)  +  Math.Abs(point.Y  -  endEB.Pos.Y);
                                exist.F 
=  exist.G  +  exist.H;
                            }
                        }
                    }
                }

                
// 从开始列表中删除起点,并将其加到关闭列表中
                 if  (startList.ContainsKey(s.Pos))
                {
                    startList.Remove(s.Pos);
                }
                
if  ( ! closeList.ContainsKey(s.Pos))
                {
                    closeList.Add(s.Pos, s);
                }

                
// 寻找F值最低的
                 double  fMin  =  Double.MaxValue ;
                
foreach  (KeyValuePair < Point, Entity >  key  in  startList)
                {
                    
if  (key.Value.F  <=  fMin)
                    {
                        fMin 
=  key.Value.F;
                        temp 
=  key.Value;
                    }
                }

                
// 将最低的从开始列表中删除,加载到关闭列表中 
                 if  (startList.ContainsKey(temp.Pos))
                {
                    startList.Remove(temp.Pos);
                }
                
if  ( ! closeList.ContainsKey(temp.Pos))
                {
                    closeList.Add(temp.Pos, temp);
                }

                
// 判断是否需要继续查找
                 if  (closeList.ContainsKey(endEB.Pos)  ||  startList.Count  <=   0 )
                {
                    
// 如果F值最低的点就是目标点,停止查找
                    s  =   null ;
                }
                
else
                {
                    s 
=  temp;
                }
            }

            
// 返回值
              return  ps;
        }

 

       由于实际需要,在代码中加了少许的修改,理解主要实现的思路即可!!!

你可能感兴趣的:(算法)