在这贴的代码是为了有需要的人学习而不是 提供源码给别人用的所以大家见谅。这个算法没有跟传统的2维数组作为存储容器,而用哈希表,这样做的好处在于查询跟修改的速度要比2维数组的快而且方便。
package astart.interfaces
{
public interface IAstartSourceMode
{
/**
*对应数据源的方格的id
* @return
*
*/
function get keyPoint():Point
/**
*对应数据源的方格的id 的字符串形式(如 var keyPoint=new Point(x,y),则key应为 "x,y" )
* @return
*
*/
function get key():String
/**
* 对应数据源的方格的类型 0为非可走区域
* @return
*
*/
function get type():int
}
}
//
package astart.interfaces
{
import flash.geom.Point;
public interface IAstarData
{
function get key():String
function get keyPoint():Point
function get G():int;
function get F():int;
function get parent():IAstarData
function get type():int
function set key(val:String):void
function set keyPoint(val:Point):void
function set G(val:int):void;
function set F(val:int):void;
function set parent(val:IAstarData):void
function set type(val:int):void
}
}
package astart.interfaces
{
import flash.geom.Point;
public interface IAstar
{
/**
* 返回结果路径
* @param source 以IAstartSourceMode接口所实现的vo类的实例为键值的数组对象 查询key必须为 *IAstartSourceMode接口所实现的vo类的key属性对应
* @param startPoint 开始点,如:new Point (1,2)队形数据源
* @param endPoint 结束点 如:new Point(4,5)对应数据源
* @return
*
*/
function getPath(source:Array,startPoint:Point,endPoint:Point):Array
}
}
/ /以上是接口文件
//下边是具体实现//
/**
*实现数据源以对象形式的A星寻路
* by 吾系衰人/wxsr
*@2008
*/
package astart.actualize
{
import flash.geom.Point;
import astart.interfaces.IAstartSourceMode
import astart.interfaces.IAstart
public class Astar implements IAstar
{
private static const COST_STRAIGHT :int=10;
private static const COST_DIAGONAL :int=14;
private static const DIR_TC:String='tc';
private static const DIR_CT:String='ct';
private static const DIR_CR:String='cr';
private static const DIR_BC:String='bc';
private var nonce:AstarData;
private var isFinish:Boolean;
private var G:int;
private var source:Array;
private var startPoint:Point
private var endPoint:Point
private var colsePath:Array;
private var colseArray:Array;
private var openPath:Array;
private var openArray:Array;
private var pathArray:Array
private var canTL:Boolean;
private var canTR:Boolean;
private var canBL:Boolean;
private var canBR:Boolean;
public function Astar()
{
}
/**
*寻路
* @param source 数据源
* @param startPoint 当前开始
* @param endPoint
* @param cell
* @return
*
*/
public function getPath(source:Array,startPoint:Point,endPoint:Point):Array
{
reSet()
this.startPoint=startPoint
this.endPoint=endPoint
this.source=source
this.nonce==null?this.nonce=new AstarData(0,0,this.startPoint):'';
this.nonce.parent=this.nonce;
this.colseArray.push({F:this.nonce.F,data:this.nonce})
this.colsePath[this.nonce.key]=this.colseArray[0]
while(this.isFinish){
getScale9Grid(source,this.nonce,this.endPoint)
}
return cleanArray()
}
//评分
private function getDis(point:Point,endPoint:Point):int
{
var dix:int=Math.abs(endPoint.x-point.x)
var diy:int=Math.abs(endPoint.y-point.y)
return Math.abs(dix+diy)
}
//获取当前评分最优对象垂直线对象
private function stratght(tar:IAstartSourceMode,endPoint:Point,type:String):void
{
if(tar!=null){
if(tar.type>0){
var costH:int=getDis(tar.keyPoint,endPoint)*10;
var costG:int=COST_STRAIGHT+G
var data:AstarData=new AstarData(costG,(costG+costH),tar.keyPoint);
data.parent==null?data.parent=this.nonce:''
if(openPath[tar.key]==null&&this.colsePath[tar.key]==null){
openPath[tar.key]=data
this.openArray.push({F:data.F,data:data})
}else if(openPath[tar.key]!=null)
{
var old:AstarData=openPath[tar.key]
data.F<old.F?openPath[tar.key]=data:''
}
}else {
if(type==DIR_TC)
{
this.canTL=false;
this.canTR=false;
}else if(type==DIR_CT)
{
this.canTL=false;
this.canBL=false;
}else if(type==DIR_CR)
{
this.canTR=false;
this.canBR=false;
}else if(type==DIR_BC)
{
this.canBL=false;
this.canBR=false;
}
}
}
}
//获取当前评分最优对象对角线对象
private function diagonal(tar:IAstartSourceMode,endPoint:Point,can:Boolean):void
{
if(can&&tar!=null)
{
if(tar.type>0)
{
var costH:int=getDis(tar.keyPoint,endPoint)*10;
var costG:int=COST_DIAGONAL+G
var data:AstarData=new AstarData(costG,costG+costH,tar.keyPoint);
data.parent==null?data.parent=this.nonce:''
if(openPath[tar.key]==null&&colsePath[tar.key]==null)
{
openPath[tar.key]=data
this.openArray.push({F:data.F,data:data})
}else if(openPath[tar.key]!=null){
var old:AstarData=openPath[tar.key]
data.F<old.F?openPath[tar.key]=data:''
}
}
}
}
//获取当前评分最佳对象
private function getScale9Grid(source:Array,data:AstarData,endPoint:Point):void
{
this.canBL=true;
this.canBR=true;
this.canTL=true;
this.canTR=true;
var x:int=data.keyPoint.x
var y:int=data.keyPoint.y
var tc:IAstartSourceMode=source[x+','+(y-1)];
var ct:IAstartSourceMode=source[(x-1)+','+y]
var cr:IAstartSourceMode=source[(x+1)+','+y]
var bc:IAstartSourceMode=source[x+','+(y+1)]
var tl:IAstartSourceMode=source[(x-1)+','+(y-1)];
var tr:IAstartSourceMode=source[(x+1)+','+(y-1)];
var bl:IAstartSourceMode=source[(x-1)+','+(y+1)]
var br:IAstartSourceMode=source[(x+1)+','+(y+1)]
stratght(tc,endPoint,DIR_TC)
stratght(ct,endPoint,DIR_CT)
stratght(cr,endPoint,DIR_CR)
stratght(bc,endPoint,DIR_BC)
diagonal(tl,endPoint,canTL)
diagonal(tr,endPoint,canTR)
diagonal(bl,endPoint,canBL)
diagonal(br,endPoint,canBR)
openArray.sortOn('F',Array.NUMERIC);
if(this.openArray[0]==null)
{
this.isFinish=false ;
return
}else {
this.nonce=this.openArray[0].data;
delete this.openPath[this.openArray[0].key];
this.openArray.shift()
if(this.colsePath[this.nonce.key]==null)
{
this.colseArray.unshift({F:this.nonce.F,data:this.nonce})
this.colsePath[this.nonce.key]=this.colseArray[0]
}
this.G=this.nonce.G
}
if(this.nonce.keyPoint.x==endPoint.x&&this.nonce.keyPoint.y==endPoint.y)
{
this.isFinish=false;
}
return
}
//返回最后路径
private function cleanArray():Array
{
this.pathArray=new Array
var key:String=String(this.endPoint.x+','+this.endPoint.y);
if(this.colsePath[key]!=null){
this.pathArray.push(this.colsePath[key].data.parent.keyPoint);
this.pathArray.push(this.colsePath[key].data.keyPoint);
while(true){
key=String(this.colsePath[key].data.parent.key);
if(key==String(this.startPoint.x+','+this.startPoint.y))break;
var item:IAstartSourceMode=this.source[key]
this.pathArray.unshift(this.colsePath[key].data.parent.keyPoint)
}
}
return this.pathArray
}
// 初始化数组
private function reSet() : void
{
this.pathArray=[]
this.source = [];
this.colsePath = [];
this.colseArray=[]
this.openPath = [];
this.openArray=[]
this.G=0
this.nonce=null
this.canTL=true
this.canTR=true
this.canBL=true
this.canBR=true
this.isFinish=true
}
}
}
/**
*A星寻路的数据存储单位
* by 吾系衰人/wxsr
*@2008
*/
package astart.AstarData
{
import astar.interfaces.IAstarData;
public class AstarData implements IAstarData
{
private var _key:String
private var _keyPoint:Point
private var _G:int=0;
private var _F:int=0;
private var _parent:AstarData
private var _type:int
public function AstarData(g:int,f:int,keyPoint:Point)
{
this._G=g;
this.F=f;
this.keyPoint=keyPoint
}
public function get key():String
{
return this._key;
}
public function get keyPoint():Point
{
return this._keyPoint;
}
public function get G():int
{
return this._G;
}
public function get F():int
{
return this._F;
}
public function get parent():IAstarData
{
return this._parent;
}
public function get type():int
{
return this._type;
}
public function set key(val:String):void
{
this._key=val
}
public function set keyPoint(val:Point):void
{
this.keyPoint=val
}
public function set G(val:int):void
{
this._G=val
}
public function set F(val:int):void
{
this._F=val
}
public function set parent(val:IAstarData):void
{
this._parent=val
}
public function set type(val:int):void
{
this._type=val
}
}
}
/
/**
*A星寻路的哈希表数据源的查询key为该类属性的key值,键值为该对象实例
*如:source:Array=[]
*source["1,2"]=new AstartSourceMode (new keyPoint(1,2),1);
*source["-1,-2"]=new AstartSourceMode (new keyPoint(-1,-2),1)
*source["2,-3"]=new AstartSourceMode (new keyPoint(2,-3),0)
*然后以此source为参数 传递给Astart
* by 吾系衰人/wxsr
*@2008
*/
package astar.actualize
{
import flash.geom.Point;
import astar.interfaces.IAstartSourceMode;
public class AstartSourceMode implements IAstartSourceMode
{
private var _keyPoint:Point
private var _key:String
private var _type:int
public function AstartSourceMode(keyPoint:Point,type:int)
{
this._keyPoint=keyPoint
this._key=String(this._keyPoint.x+','+this._keyPoint.y)
this._type=type
}
public function get keyPoint():Point
{
return _keyPoint;
}
public function get key():String
{
return this._key;
}
public function get type():int
{
return this._type;
}
}
}