A* 寻路算法


构造point 类

应包括

X 坐标

Y坐标

G值

H值

F值

parent 父节点


AStar类

应包括

起点

终点

开放列表

关闭列表

障碍列表

地图数组


流程:

1 将起点放入开放列表

2 从开放列表中查找F值最低的点

3 检测此点周围的可到地点,并放入开放列表中

4 将此点放入闭合列表,并在开放列表中将其删除

5 如果在开放列表中检测到终点,则找到路径,结束查找,反之从2开始重复


最短路径是从终点开始遍历父节点,直到起点形成的路径。

package AzureL;

import java.util.ArrayList;

import AzureL.Point;
import android.util.Log;

public class Astar {
	private  Point start; //起点
	private  Point terminal; //终点
	private  ArrayList<Point> openlist; 
	private  ArrayList<Point> closelist;
	private  int[] pass = {1,2};
	private  int[][] map; //地图
	/**
	 * 构造函数
	 * @param s 起点
	 * @param t 终点
	 * @param m 地图
	 */
	public Astar(Point s,Point t,int[][] m){
		start = s;
		terminal = t;
		map = m;
		openlist  = new ArrayList<Point>();
		closelist =  new ArrayList<Point>();
	}
	/**
	 * 获得起点
	 * @return  返回起点
	 */
	public Point getStartPoint(){
		return start;
	}
	/**
	 * 获得终点
	 * @return 返回终点
	 */
	public Point getTerminalPoint(){
		return terminal;
	}
	/**
	 * 返回开放列表
	 * @return 返回开放列表
	 */
	public ArrayList<Point> getopenlist(){
		return openlist;
	}
	/**
	 * 返回闭合列表
	 * @return 返回闭合列表
	 */
	public ArrayList<Point> getcloselist(){
		return closelist;
	}
	/**
	 * 从openlist查找最低F值的点
	 * 
	 * @return 最低F值点的序号
	 */
	private  Point getPfromopenlist(){
		Point p;
		int f = 0;
		int t = 0;
		if(openlist.size()>1){
			
			for(int i = 0;i<openlist.size();i++){
				p = (Point)openlist.get(i);
				if(f == 0 || f > p.getF()){
					f = p.getF();
					t = i;
					Log.i(" getP ","t = "+t);
				}
			}
			return openlist.get(t);
		}
		else{
			return openlist.get(0);
		}
	}
	/**
	 * 找到路径 
	 * @return 返回闭合列表
	 */
	public  ArrayList<Point> findPath(){
		openlist = new ArrayList<Point>();
		closelist = new ArrayList<Point>();
		openlist.add(start);
		
		while(openlist.size() > 0){
			Point p = getPfromopenlist();
			checkArroundPoint(p);
			openlist.remove(p);
			closelist.add(p);
			if(containPoint(openlist, new Point(terminal.getX(),terminal.getY()))){
				break;
			}
		}
		
		return closelist;
	}
	/**
	 * 查找此点周边可用点
	 * @param p 当前点 
	 */
	private  void checkArroundPoint(Point p){
		
		for(int ix = -1;ix<2;ix++){
			for(int iy = -1;iy<2;iy++){
				if( !(ix == 0 && iy == 0)){
					Point newPoint = new Point(p.getX()+ix,p.getY()+iy);
					if(newPoint.getX()>=0 && newPoint.getX()<map[0].length && newPoint.getY()+iy>=0 && newPoint.getY()+iy<map.length && isAccess(map, pass, newPoint) && !containPoint(closelist, newPoint) ){
						
						if(!containPoint(openlist, newPoint)){
							newPoint.setParent(p);
							if(newPoint.getG() == 0){
								getF(newPoint);
							}
							openlist.add(newPoint);
							
						}
						else{
							Point open = searchPoint(openlist, new Point(p.getX()+ix,p.getY()+iy));
							int tmp = 0;
							if(Math.abs(open.getX()-p.getX())+Math.abs(open.getY()-p.getY()) == 1){
								tmp = 10;
							}
							else if(Math.abs(open.getX()-p.getX())+Math.abs(open.getY()-p.getY()) == 2){
								tmp =14;
							}
							if(p.getG()+tmp < open.getG()){
								open.setParent(p);
								getG(open);
								open.setF(open.getG()+open.getH());
							}
						}						
					}
				}
			}				
		}
	}
	
	/**
	 * 检测是否相同点
	 * @param p1 点1
	 * @param p2 点2
	 * @return 返回是否相同
	 */
	private  Boolean samePoint(Point p1,Point p2){
		if(Math.abs(p1.getX() - p2.getX()) + Math.abs(p1.getY() - p2.getY()) == 0){
			return true;
		}
		else{
			return  false;
		}
	}
	/**
	 * 返回是否包含点
	 * @param list 列表
	 * @param p 点
	 * @return 是否包含点
	 */
	private  Boolean containPoint(ArrayList<Point> list,Point p){
		for(int i = 0;i<list.size();i++){
			if(samePoint((Point)list.get(i),p))
			return true;
		}
		return false;
	}
	/**
	 * 查找点在列表中的位置
	 * @param list 列表
	 * @param p 点
	 * @return 返回在列表中的位置
	 */
	private  Point searchPoint(ArrayList<Point> list,Point p){
		for(int i = 0;i<list.size();i++){
			if(samePoint((Point)list.get(i),p))
			return list.get(i);
		}
		return null;
	}
	/**
	 * 计算H值
	 * @param current 当前点
	 * @param terminal 终点
	 */
	private  void getH(Point current,Point terminal){
		current.setH( (Math.abs(current.getX()-terminal.getX())+Math.abs(current.getY()-terminal.getY()))*10);
		
	}
	/**
	 * 计算G值
	 * @param current 当前点
	 */
	private  void getG(Point current){
		int temp = 0;
		if(Math.abs(current.getParent().getX()-current.getX())+Math.abs(current.getParent().getY()-current.getY()) == 1)
			temp = 10;
		else if(Math.abs(current.getParent().getX()-current.getX())+Math.abs(current.getParent().getY()-current.getY()) == 2){
			temp = 14;
		}
		current.setG(current.getParent().getG()+temp);
	}
	/**
	 * 计算F值
	 * @param p 当前点
	 */
	private  void getF(Point p){
		getH(p,terminal);
		getG(p);
		p.setF( p.getG() + p.getH());
	}
	/**
	 * 检测是否格子可以通过
	 * @param map 地图
	 * @param pass 不可通过数组
	 * @param p 节点
	 * @return 返回是否可以通过
	 */
	private boolean isAccess(int[][] map,int[] pass,Point p){
		boolean result = true;
		for(int i = 0;i < pass.length;i++){
			if(map[p.getY()][p.getX()] == pass[i]){
				result = false;
				break;
			}
			
		}
		return result;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值