AStar 搜索(A*) 寻路算法

这几天看了A*搜索的寻路算法,发现精华在于f = g + h,我觉得难点在于如何确定估价函数的h。

本段代码是迷宫找路。估价函数:h是用的曼哈顿距离

贴出自己的代码,分享一下。可以讨论

文章会附上:代码.rar和测试

 

 

import java.util.PriorityQueue;
import java.util.Scanner;

public class AStar {
	private int stepx[] = { 0, 1, 1, 1, 0, -1, -1, -1 };// 第一个是上,顺时针
	private int stepy[] = { 1, 1, 0, -1, -1, -1, 0, 1 };// 第一个是上,顺时针
	private int gvalue[] = { 10, 14, 10, 14, 10, 14, 10, 14 };

	private int n;
	private int m;
	private char map[][];
	private Node mapNode[][];

	public AStar(int n, int m, Scanner s) {
		this.n = n;
		this.m = m;
		this.init(s);
	}

	public int run() {
		NodeComparator cmp = new NodeComparator();
		PriorityQueue<Node> open = new PriorityQueue<Node>(n * m, cmp);
		int x, y;
		int nxti, nxtj;
		Node nxt;

		mapNode[0][0].setInbox(true);
		mapNode[0][0].g = 0;
		mapNode[0][0].f = mapNode[0][0].g + mapNode[0][0].h;
		open.add(mapNode[0][0]);
		while (!open.isEmpty()) {
			Node top = open.poll();// 获取并移除此队列的头,如果此队列为空,则返回 null。
			top.setSteped(true);
			// 如果终点在结束列表中,表示表示找到了最优解
			if (mapNode[n - 1][m - 1].isSteped())
				break;
			x = top.i;
			y = top.j;
			for (int i = 0; i < 8; i++) {
				nxti = x + stepx[i];
				nxtj = y + stepy[i];
				if (!inRange(nxti, nxtj))
					continue;
				if(map[nxti][nxtj]=='x')continue;
				nxt = mapNode[nxti][nxtj];
				int gg = top.g + gvalue[i];
				if (gg < nxt.g) {
					nxt.g = gg;
					nxt.f = gg + nxt.h;
					nxt.parent = top;
				}
				if (!nxt.isInbox()){
					nxt.setInbox(true);
					open.add(nxt);
//					System.out.println("--> ("+nxt.i+", "+nxt.j+")");
				}
			}
		}
		return mapNode[n-1][m-1].f;
	}

	public void printRace(){
		Node cur = mapNode[n-1][m-1];
		while(!cur.parent.equals(cur)){
//			System.out.println("[ "+cur.i+", "+cur.j+"]");
			map[cur.i][cur.j] = 'O';
			cur = cur.parent;
		}
		
		for( int i = 0 ; i < n; i++){
			for( int j = 0; j < m; j++){
				System.out.print(map[i][j]);
			}
			System.out.println();
		}
	}
	private boolean inRange(int nxti, int nxtj) {
		if (nxti >= n || nxtj >= m || nxti < 0 || nxtj < 0)
			return false;
		return true;
	}

	private void init(Scanner s) {
		map = new char[n][m];
		mapNode = new Node[n][m];
		for (int i = 0; i < n; i++) {
			String tmp = s.next();
			for (int j = 0; j < m; j++) {
				map[i][j] = tmp.charAt(j);
				mapNode[i][j] = new Node(i, j);
				mapNode[i][j].h = getH(i + 1, j + 1);
			}
		}
	}

	/**
	 * 曼哈顿距离
	 * 
	 * @param i
	 * @param j
	 * @return
	 */
	private int getH(int i, int j) {
		return (n - i + m - j) * 10;
	}

	public int getN() {
		return n;
	}

	public void setN(int n) {
		this.n = n;
	}

	public int getM() {
		return m;
	}

	public void setM(int m) {
		this.m = m;
	}

	public char[][] getMap() {
		return map;
	}

	public void setMap(char[][] map) {
		this.map = map;
	}

}

 

 

 

/**
 * 地图中的每个位置
 * @author coolgo
 */
public class Node {

	public int i,j;
	/**
	 * f = g + h; h为估价函数
	 */
	public int f=1<<30;
	public int g=1<<30;
	public int h=1<<30;
	/**
	 * if steped= true;表示已经在close列表中
	 */
	private boolean steped = false;
	/**
	 * if inbox = true;表示已经在open列表中
	 */
	private boolean inbox = false;
	public Node parent = this;

	public Node(int ii, int jj){
		i = ii;
		j = jj;
	}

	public void setSteped(boolean steped) {
		this.steped = steped;
	}

	public boolean isSteped() {
		return steped;
	}

	public void setInbox(boolean inbox) {
		this.inbox = inbox;
	}

	public boolean isInbox() {
		return inbox;
	}
}

 

 

import java.util.Comparator;

/**
 * 比较器
 * @author coolgo
 */
public class NodeComparator implements Comparator<Node> {
	@Override
	public int compare(Node x, Node y) {
		return x.f - y.f;
	}
}
 

 

 

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Date;
import java.util.Scanner;


public class Mainx{
	public static void main(String [] argv) throws FileNotFoundException {
	
		FileInputStream fs = new FileInputStream("D:\\work\\Astar\\src\\c.txt");
		Scanner s = new Scanner(fs);
		int n,m;
		n = s.nextInt();
		m = s.nextInt();
		AStar ast = new AStar(n,m,s);
		Date t = new Date();
		int res = ast.run();
		Long x = (new Date()).getTime() - t.getTime();
		ast.printRace();
		System.out.println("消耗"+res);
		System.out.println("运行时间"+x+"毫秒");
		
	}
}

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值