构造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;
}
}