zoukankan      html  css  js  c++  java
  • A* +二叉堆 斜视45度寻路

    前段时间在园子提问关于45度 没有找到好的解决方法 

    下面是自己写的A*,基于as3 3.0实现的 代码如有不妥和bug之处 大家请指正

    贡献源代码这个是在我之前做一个flash的虚拟城市用到的

    mapDataInfo 是地图的数据信息

    没有经过优化    这两天有点浮躁天气热 了

    /*
    =================================================================================================
     E_the code
    2009/02/28 A* Astar Road 斜视45度
    =================================================================================================
    */
    package gamesrc.com{
     import gamesrc.Model.mapDataInfo;
     
     //import flash.utils.ByteArray;
     //import flash.utils.getTimer;
     public class SearchRoad {
      private var endx:uint;
      private var endy:uint;
      private var openA:Array;
      private var closeA:Array;
      private var isfindpath:Boolean=false;
      private var findA:Array;
      //横或竖向移动一格的路径评分
      private const COST_STRAIGHT : int = 10;
      //斜向移动一格的路径评分
      private const COST_DIAGONAL : int = 14;
      private static var _getInstance:SearchRoad;
      private var maxStep:int=1000;
      private var mstep:int=0;
      private var isuseOpenlist:Boolean;
      //起点
      //private var startX:uint;
      //private var startY:uint;
      public function SearchRoad()
      {
      
      }
      public function searchRoads(sx:uint,sy:uint,endx:uint,endy:uint):Array
      {
       isfindpath=false;
       var empArray:Array=null;
       isuseOpenlist=false;
       openA=new Array();
       closeA=new Array();
       mstep=0;
       findA=mapDataInfo.mapArray;
       this.endx=endx;
       this.endy=endy;
       //this.startX=sx;
       //this.startY=sy;
       openA.push([sx,sy,sx,sy,0,0]);//[sx,sy,px,py,g,f]
       seachRoad();
       if(isfindpath){
        return getpath();
       }
       //trace(findA[endy][endx])
       openlistHF();
       iscloseHF();
       return empArray;
      }
      private function iscloseHF():void
      {
       for each(var sA:Array in closeA)
       {
        findA[sA[1]][sA[0]]=0;
       }
      }
      private function getpath():Array
      {
       var py:int=0;
       var px:int=0;
       var len:int=this.closeA.length-1;
       var pathArray:Array=new Array();
       //trace(this.closeA.length)
       for(var pt:int=len;pt>=0;pt--)
       {
        //trace(this.closeA[pt])
        if(pt==len)
        {
         px=this.closeA[pt][2];
         py=this.closeA[pt][3];
         pathArray.push([closeA[pt][0],closeA[pt][1]]);
        }
        else if(closeA[pt][1]==py&&closeA[pt][0]==px)
        {
         px=this.closeA[pt][2];
         py=this.closeA[pt][3];
         pathArray.push([closeA[pt][0],closeA[pt][1]]);
        }
        findA[closeA[pt][1]][closeA[pt][0]]=0;
       }
       openlistHF();
       return pathArray.reverse();
      }
      //恢复开启列表的元素
      private function openlistHF():void
      {
      
       for each(var sA:Array in openA)
       {
        findA[sA[1]][sA[0]]=0;
       }
      }
      public function seachRoad():void
      {
       var tempOA:Array;
       while(openA.length>0&& !isfindpath)
       {
        if(++mstep>=maxStep)break;
        tempOA=openA[0]//.splice(getminFopenlist(),1)[0];
        //trace(tempOA);
        //trace(tempOA.length);
        putInclose(tempOA[0],tempOA[1],tempOA[2],tempOA[3]);
        if(tempOA[0]==endx&&tempOA[1]==endy)
        {
         isfindpath=true;
         break;
        }
        //this.getground(tempOA[0],tempOA[1],tempOA[4]);
        get45ground(tempOA[0],tempOA[1],tempOA[4]);
       }
      }
      //寻找f最小的
      private function getminFopenlist():int
      {
       var min:uint=0;
       for(var isf:int=0;isf<this.openA.length;isf++)
       {
        if(this.getScore(min+1)>this.getScore(isf+1))
         min=isf;
       }
       return min;
      }
      //加入到关闭列表
      private function putInclose(nx:int,ny:int,px:int,py:int):void
      {
       closeA.push([nx,ny,px,py])
       findA[ny][nx]=1;
       //trace("查看openA列表是否被删除:"+openA)
       if(openA.length<2)
       {
        if(isuseOpenlist)openlistHF()
        openA=[];
        return;
       }
       openA[0]=openA.pop();
       shortBackoutNode();
      }
      //加入到开启列表
      private function putInopenlist(nx:int,ny:int,px:int,py:int,g:int,f:int):void
      {
       isuseOpenlist=true;
       openA.push([nx,ny,px,py,g,f]);
       shortopenlist(openA.length);
      }
      //获取四周的节点
      private function getground(sx:uint,sy:uint,g:uint):void
      {
       //var d:int=this.openA.length;
      
       var Canup:Boolean=isNodeCango(sx,sy-1,sx,sy,g+COST_STRAIGHT);
       if(isfindpath)return;
       var Canright:Boolean=isNodeCango(sx+1,sy,sx,sy,g+COST_STRAIGHT);
       if(isfindpath)return;
       var Canlefth:Boolean=isNodeCango(sx-1,sy,sx,sy,g+COST_STRAIGHT);
       if(isfindpath)return;
       var Candown:Boolean=isNodeCango(sx,sy+1,sx,sy,g+COST_STRAIGHT);
       if(isfindpath)return;
       //trace("Canup:"+Canup+",Canright:"+Canright+",Canlefth:"+Canlefth+",Candown:"+Candown)
       //右上
       if(Canup&&Canright&&!isfindpath)isNodeCango(sx+1,sy-1,sx,sy,g+COST_DIAGONAL);
       //右下
       if(Canright&&Candown&&!isfindpath)isNodeCango(sx+1,sy+1,sx,sy,g+COST_DIAGONAL);
       //左上
       if(Canup&&Canlefth&&!isfindpath)isNodeCango(sx-1,sy-1,sx,sy,g+COST_DIAGONAL);
       //左下
       if(Candown&&Canlefth&&!isfindpath)isNodeCango(sx-1,sy+1,sx,sy,g+COST_DIAGONAL);
      
       /*if(d==this.openA.length)
       {
        trace("没有增加一个元素nx:"+sx+"ny:"+sy);
        isNodeCango2(sx,sy-1,sx,sy,g+COST_STRAIGHT);
        isNodeCango2(sx+1,sy,sx,sy,g+COST_STRAIGHT)
        isNodeCango2(sx-1,sy,sx,sy,g+COST_STRAIGHT)
        isNodeCango2(sx,sy+1,sx,sy,g+COST_STRAIGHT)
        isNodeCango2(sx+1,sy-1,sx,sy,g+COST_DIAGONAL);
       //右下
       if(Canright&&Candown&&!isfindpath)
        isNodeCango2(sx+1,sy+1,sx,sy,g+COST_DIAGONAL);
       //左上
       if(Canup&&Canlefth&&!isfindpath)
        isNodeCango2(sx-1,sy-1,sx,sy,g+COST_DIAGONAL)
       //左下
       if(Candown&&Canlefth&&!isfindpath)
        isNodeCango2(sx-1,sy+1,sx,sy,g+COST_DIAGONAL)
       }*/
      }
      private function isNodeCango2(nx:uint,ny:uint,px:uint,py:uint,g:uint):void
     
      {
      
       var tempOpenIndex:uint=0;
       var hvag:uint=0;
       if(nx<0||nx>=mapDataInfo.MAP_X||ny<0||ny>=mapDataInfo.MAP_Y)
       {
        trace("超过数组大小了:nx="+nx+",ny="+ny)
       }
       else
        trace("是否为障碍物:"+findA[ny][nx]);
      
      }
      private function isNodeCango(nx:uint,ny:uint,px:uint,py:uint,g:uint):Boolean
      {
      
       var tempOpenIndex:uint=0;
       var hvag:uint=0;
       if(nx<0||nx>=mapDataInfo.MAP_X||ny<0||ny>=mapDataInfo.MAP_Y)
       {
        //trace("超过数组大小了:nx="+nx+",ny="+ny)
        return false;
       }
       if(findA[ny][nx]==1)return false;
       if(nx==endx&&ny==endy)
       {
        closeA.push([nx,ny,px,py]);
        isfindpath=true;
        return false;
       }
       if(findA[ny][nx]>1)
       {
        if(findA[ny][nx]>g)
        {
         tempOpenIndex=getopenindex(nx,ny);
         hvag=setH(nx,ny);
         findA[ny][nx]=g;
         openA[tempOpenIndex]=[nx,ny,px,py,g,g+hvag];
         shortopenlist(tempOpenIndex);
        }
        return true;
       }
       hvag=setH(nx,ny);
       findA[ny][nx]=g;
       putInopenlist(nx,ny,px,py,g,g+hvag);
       return true;
      }
      //获取最小的f开启列表路径
      private function getopenindex(x:uint,y:uint):uint
      {
       for(var sj:uint=0;sj<openA.length;sj++)
       {
        if(x==openA[sj][0]&&y==openA[sj][1])return sj;
       }
       return undefined;
      }
      //开启列表排序
      private function shortopenlist(indexs:int):void
      {
       var father:int;
       while(indexs>1)
       {
        father=Math.floor(indexs/2);
        //如果该节点的F值小于父节点的F值则和父节点交换
        if(this.getScore(indexs)<this.getScore(father))
         indexs=Swap(father,indexs);
        else
         break
       }
      }
      //开启列表取出后进行排序
      private function shortBackoutNode():void
      {
       var checkIndex:int=1;
       var temp:int;
       while(true)
       {
        temp=checkIndex
        if(checkIndex*2<=openA.length)
        {
         if(getScore(checkIndex)>getScore(2*temp))
          checkIndex=2*temp;
         if(temp*2+1<=openA.length)
         {
          if(getScore(checkIndex)>this.getScore(temp*2+1))
          {
           checkIndex=2*temp+1;
          }
         }
        }
        if(temp==checkIndex)
         break;
        else
        {
         Swap(checkIndex,temp);
        }
       }
      }
      //获取openlist f值
      private function getScore(p_index:int):int
      {
       //trace(this.openA[0]);
       return openA[p_index-1][5];
      }
      //交换节点
      private function Swap(a:uint,b:uint):uint
      {
       var last:Array=openA[a-1];
       openA[a-1]=openA[b-1];
       openA[b-1]=last;
       return a;
      }
      //路径估算评分
      private function setH(nx:uint,ny:uint):uint
      {
       return this.set45H(nx,ny);
       //return 10 * (Math.abs(endx - nx) + Math.abs(endy - ny))
      }
      public static function getInstance():SearchRoad
      {
       if(!_getInstance)
       {
        _getInstance=new SearchRoad();
       }
       return _getInstance;
      }
      //45度的ground
      private function get45ground(sx:uint,sy:uint,g:uint):void
      {
       var temT:Boolean=Boolean(sy&1);
       var Canup:Boolean=temT?isNodeCango(sx+1,sy-1,sx,sy,g+COST_STRAIGHT):isNodeCango(sx,sy-1,sx,sy,g+COST_STRAIGHT);
       if(isfindpath)return;
       var Canright:Boolean=temT?isNodeCango(sx+1,sy+1,sx,sy,g+COST_STRAIGHT):isNodeCango(sx,sy+1,sx,sy,g+COST_STRAIGHT);
       if(isfindpath)return;
       var Canlefth:Boolean=temT?isNodeCango(sx,sy-1,sx,sy,g+COST_STRAIGHT):isNodeCango(sx-1,sy-1,sx,sy,g+COST_STRAIGHT);
       if(isfindpath)return;
       var Candown:Boolean=temT?isNodeCango(sx,sy+1,sx,sy,g+COST_STRAIGHT):isNodeCango(sx-1,sy+1,sx,sy,g+COST_STRAIGHT);
       if(isfindpath)return;
       //trace("Canup:"+Canup+",Canright:"+Canright+",Canlefth:"+Canlefth+",Candown:"+Candown)
       //右上
       if(Canup&&Canright&&!isfindpath)isNodeCango(sx+1,sy,sx,sy,g+COST_DIAGONAL);
       //右下
       if(Canright&&Candown&&!isfindpath)isNodeCango(sx,sy+2,sx,sy,g+COST_DIAGONAL);
       //左上
       if(Canup&&Canlefth&&!isfindpath)isNodeCango(sx,sy-2,sx,sy,g+COST_DIAGONAL);
       //左下
       if(Candown&&Canlefth&&!isfindpath)isNodeCango(sx-1,sy,sx,sy,g+COST_DIAGONAL);
      }
      //45度估算评分
      private function set45H(nx:uint,ny:uint):uint
      {
       //return (Math.abs(mapDataInfo.MapArrayElement[endy][endx][0]-mapDataInfo.MapArrayElement[ny][nx][0])+Math.abs(mapDataInfo.MapArrayElement[endy][endx][1]-mapDataInfo.MapArrayElement[ny][nx][1]))*10
       //var Bol:Boolean=Boolean(ny&1);
       //var w:uint=2;
       //w=2;
       //True y=int(y/2)+w-x;x=int(y/2)+x;
       //false y=w-1+int(y/2)-x;x=int(y/2)+x;
       //var Bigy:int=Bol?int(ny/2)+w-nx:w-1+int(ny/2)-nx;
       //var Bigx:int=int(ny/2)+nx
       /* var _loc_4:uint;
                var _loc_5:uint;
                var _loc_6:uint;
                var _loc_7:uint;
                var _loc_8:uint;
                _loc_4 = Math.abs(endx - nx) + Math.abs(endy - ny);
                _loc_5 = Math.abs(startX - nx);
                _loc_6 = Math.abs(startY - ny);
                _loc_7 = Math.min(_loc_5, _loc_6);
                _loc_8 = Math.abs(_loc_5 - _loc_6) * 10 + _loc_7 * 14;
                return _loc_4 * 10 + _loc_8;*/
       return (Math.abs(setbigX(endx,endy)-setbigX(nx,ny))+Math.abs(setbigY(endx,endy)-setbigY(nx,ny)))*10
      }
      //45度y
      private function setbigY(nx:uint,ny:uint):uint
      {
       return mapDataInfo.EleArray[ny][nx][1];
       //var Bol:Boolean=Boolean(ny&1);
       //return (Bol?Math.floor(ny/2)+mapDataInfo.MAP_X-nx:mapDataInfo.MAP_X-1+int(ny/2)-nx);
      }
      private function setbigX(nx:uint,ny:uint):uint
      {
       return mapDataInfo.EleArray[ny][nx][0];
       //return Math.floor(ny/2)+nx;
      }
     }
    }

  • 相关阅读:
    Web防止button按钮点击多次
    缓存
    A标签跳转链接并修改样式
    省、市、区 三级联动
    ASP.NET的OnClientClick与OnClick事件
    ASP:CheckBox获取前台的checked的属性
    c#字符串大小写转换
    C# Base64编码
    自定义滚动条样式 -webkit-scrollbar
    代码 三角
  • 原文地址:https://www.cnblogs.com/mklp98999/p/1451278.html
Copyright © 2011-2022 走看看