`
cjx186
  • 浏览: 265274 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

A start (A*) 算法的Java实现

    博客分类:
  • java
阅读更多
一、AStart类,AStart(int[][] map, int width, int height),用find查找两点间的坐标。
/**
 * @author ChenJianxiang 
 * @deprecated
 */
package com.cjx.path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
//估值函数:f(n)=g(n)+h(n)
public class AStart {
	private int[][] map;
	private int width;
	private int height;
	/** 开启列表 */
	private Node[] OpenList;
	/** 开启列表长度 */
	private int olength = 0;
	/** 开启hashMap */
	private HashMap<String, Node> OpenTable = new HashMap<String, Node>();
	/** 记录节点状态 */
	private int[][] mapc;
	/** 是否找到 */
	private boolean findFalg = false;
	public AStart(int[][] map, int width, int height) {
		this.width = width;
		this.height = height;
		this.map = map;
		this.mapc = new int[width][height];
		this.OpenList = new Node[width * height / 2];
	}
	public static void main(String[] args) {
		int[][] map = new int[][] {// 地图数组
		// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
		{ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 0
		{ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 1
		{ 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, // 2
		{ 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, // 3
		{ 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, // 4
		{ 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0 }, // 5
		{ 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 }, // 6
		{ 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1 }, // 7
		{ 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 }, // 8
		{ 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 9
		{ 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; // 10
		// Node sNode = new Node(a.map, 0, 0, null);
		// Node eNode = new Node(a.map, 10, 14, null);
		AStart a = new AStart(map, 11,15);
		System.out.println("====================");
		long t = new java.util.Date().getTime();
		List<Node> list = a.find(0, 0, 9,13);
		if (list.size() > 0) {
			for (int i = 0; i < list.size(); i++) { //
				a.mapc[list.get(i).getX()][list.get(i).getY()] = 7;
			}
			for (int i = 0; i < a.map.length; i++) {
				for (int j = 0; j < a.map[0].length; j++) {
					if (a.mapc[i][j] == 7) {
						System.out.print("※");
					} else {
						if (a.map[i][j] == 0) {
							System.out.print("〓");
						} else {
							System.out.print(" ");
						}
					}
				}
				System.out.println();
			}
		} else {
			System.out.println("没有通路。");
		}
		System.out.println("用时:" + (new java.util.Date().getTime() - t));
		System.out.println("====================");

	}
	/**
	 * 查找路径
	 * 
	 * @param x1
	 * @param y1
	 * @param x2
	 * @param y2
	 * @return
	 */
	public List<Node> find(int x1, int y1, int x2, int y2) {
		Node sN = this.getNearNode(x1, y1, x2, y2, map, width, height);
		Node eN = this.getNearNode(x2, y2, x1, y1, map, width, height);
		List<Node> result = this.find(sN, eN);
		return result;
	}
	/**
	 * @param map
	 * @param startNode
	 * @param endNode
	 * @return
	 */
	private List<Node> find(Node sNode, Node eNode) {
		List<Node> resultList = new ArrayList<Node>();
		olength++;
		OpenList[olength] = sNode;
		mapc[sNode.getX()][sNode.getY()] = Constant.NOTE_OPEN;

		Node cNode = null;
		while (olength > 0) {
			cNode = OpenList[1];
			@SuppressWarnings("unused")
			boolean f0 = false, f1 = false, f2 = false, f3 = false;// 当前节点四方向可通行标志
			for (int i = 0; i < 8; i++) {
				switch (i) {
				case 0:// 东
					f0 = check(cNode.getX(), cNode.getY() + 1, eNode, cNode,
							Constant.COST_STRAIGHT);
					break;
				case 1:// 南
					f1 = check(cNode.getX() + 1, cNode.getY(), eNode, cNode,
							Constant.COST_STRAIGHT);
					break;
				case 2:// 西
					f2 = check(cNode.getX(), cNode.getY() - 1, eNode, cNode,
							Constant.COST_STRAIGHT);
					break;
				case 3:// 北
					f3 = check(cNode.getX() - 1, cNode.getY(), eNode, cNode,
							Constant.COST_STRAIGHT);
					break;
				case 4:// 东南
					// if (f0 && f1)可以直接跳
					check(cNode.getX() + 1, cNode.getY() + 1, eNode, cNode,
							Constant.COST_DIAGONAL);
					break;
				case 5:// 东北
					// if (f0 && f3)可以直接跳
					check(cNode.getX() - 1, cNode.getY() + 1, eNode, cNode,
							Constant.COST_DIAGONAL);
					break;
				case 6:// 西南
					// if (f2 && f1)可以直接跳
					check(cNode.getX() + 1, cNode.getY() - 1, eNode, cNode,
							Constant.COST_DIAGONAL);
					break;
				case 7:// 西北
					// if (f2 && f3)可以直接跳
					check(cNode.getX() - 1, cNode.getY() - 1, eNode, cNode,
							Constant.COST_DIAGONAL);
					break;
				}// end switch
			}// end for
			this.putClosedTabe(cNode, eNode);
			if (this.findFalg) {
				break;
			}
		}
		if (this.findFalg) {// 有
			read(resultList, cNode);
			return resultList;
		} else {// 无
			/** 清空 */
			return resultList;
		}
	}// end find
	/**
	 * 读取所有节点,从起点开始返
	 * 
	 * @param resultList
	 * @param node
	 */
	private void read(List<Node> resultList, Node node) {
		if (node.getParentNode() != null) {
			read(resultList, node.getParentNode());
		}
		resultList.add(node);
	}
	/**
	 * 检查 当前节点周围的节点,是否可以通行,是否在开启列表中,是否在关闭列表中 如果不在关闭与开启列表中则加入开启列表,如果在开启中则更新节点G值信息
	 * 
	 * @param x
	 *            X值
	 * @param y
	 *            Y值
	 * @param eNode
	 *            终点
	 * @param parentNode
	 *            父节点
	 * @param step
	 *            步长
	 * @return
	 */
	private boolean check(int x, int y, Node eNode, Node parentNode, int step) {
		try {
			if (map[x][y] == Constant.NOTE_NOWAY) {// 没门
				return false;
			}
		
		if (mapc[x][y] == Constant.NOTE_CLOSED) {
			return false;
		}
		if (mapc[x][y] == Constant.NOTE_NONE) {
			this.putOpenTable(x, y, eNode, parentNode, step);
			mapc[x][y] = Constant.NOTE_OPEN;
			return true;
		} else if (mapc[x][y] == Constant.NOTE_OPEN) {
			this.updateOpenTable(x, y, eNode, parentNode, step);
			return true;
		}
		} catch (java.lang.ArrayIndexOutOfBoundsException e) {
			return false;// 下标越界
		}
		return false;
	}// end check
	/**
	 * 放入关闭列表
	 * 
	 * @param node
	 * @return
	 */
	private void putClosedTabe(Node node, Node eNode) {
		if (node.getX() == eNode.getX() && node.getY() == eNode.getY()) {
			this.findFalg = true;// 找到了
			return;
		}
		Node tNode;
		OpenList[1] = OpenList[olength];
		tNode = OpenList[1];
		int i = 1;
		while ((i * 2 + 1) <= olength) {
			if (tNode.getF() < OpenList[i * 2].getF()
					&& tNode.getF() < OpenList[i * 2 + 1].getF()) {
				break;
			} else {
				if (OpenList[i * 2].getF() < OpenList[i * 2 + 1].getF()) {// 找一个相对较小的子节点交换
					OpenList[i] = OpenList[i * 2];
					OpenList[i * 2] = tNode;
					i = i * 2;
				} else {
					OpenList[i] = OpenList[i * 2 + 1];
					OpenList[i * 2 + 1] = tNode;
					i = i * 2 + 1;
				}
			}
		}
		OpenList[olength] = null;
		olength--;
		mapc[node.getX()][node.getY()] = Constant.NOTE_CLOSED;
	}
	/**
	 * 放入开启列表
	 * 
	 * @param x
	 * @param y
	 * @param eNode
	 * @param parentNode
	 * @param step
	 * @return
	 */
	private boolean putOpenTable(int x, int y, Node eNode, Node parentNode,
			int step) {
		Node node = new Node(map, x, y, parentNode);
		this.count(node, eNode, step);
		olength++;
		OpenList[olength] = node;
		OpenTable.put(node.getX() + "_" + node.getY(), node);
		int i = olength / 2;
		Node mid = OpenList[i];
		while (mid.getF() > node.getF()) {
			Node temp = mid;
			OpenList[i] = OpenList[olength];
			OpenList[olength] = temp;
			i = i / 2;
			if (i < 1) {
				i = 1;
			}
			mid = OpenList[i];
		}
		return true;
	}
	/**
	 * 已经存在 更新节点F值
	 * 
	 * @param x
	 * @param y
	 * @param eNode
	 * @param parentNode
	 * @param step
	 * @return
	 */
	private boolean updateOpenTable(int x, int y, Node eNode, Node parentNode,
			int step) {
		Node node = OpenTable.get(x + "_" + y);
		int g = parentNode.getG() + step;
		if (g < node.getG()) {
			node.setParentNode(parentNode);
			this.count(node, eNode, step);
			return true;
		}
		return false;
	}
	/**
	 * GHF
	 * 
	 * @param node
	 * @param eNode
	 * @param parentNode
	 * @param step
	 */
	private void count(Node node, Node eNode, int step) {
		this.countG(node, node.getParentNode(), step);
		this.countH(node, eNode);
		this.countF(node);
	}
	/**
	 * 计算G值
	 * 
	 * @param node
	 * @param parentNode
	 * @param step
	 */
	private void countG(Node node, Node parentNode, int step) {
		if (parentNode == null) {
			node.setG(step);
		} else {
			node.setG(parentNode.getG() + step);
		}
	}
	/**
	 * 计算H值
	 * 
	 * @param node
	 * @param eNode
	 */
	private void countH(Node node, Node eNode) {
		node.setH(Math.abs(eNode.getX() - node.getX())
				+ Math.abs(eNode.getY() - node.getY()));
	}
	/**
	 * 计算F值
	 * 
	 * @param node
	 */
	private void countF(Node node) {
		node.setF(node.getG() + node.getH());
	}
	/**
	 * 在地图线路上没有坐标点时取最后的一个点
	 * 
	 * @param x1
	 * @param y1
	 * @param x2
	 * @param y2
	 * @param map
	 * @param width
	 * @param height
	 * @return
	 */
	private Node getNearNode(int x1, int y1, int x2, int y2, int map[][],
			int width, int height) {
		Node node = null;
		List<Node> nodeList = new ArrayList<Node>();
		int length = width > height ? width : height;
		for (int k = 1; k < length; k++) {
			for (int i = -k; i <= k; i++) {
				try {
					if (map[x1 - k][y1 + i] == 1) {
						nodeList.add(new Node(x1 - k, y1 + i));
					}
				} catch (Exception e) {
				}
			}
			for (int i = -k; i <= k; i++) {
				try {
					if (map[x1 + k][y1 + i] == 1) {
						nodeList.add(new Node(x1 + k, y1 + i));
					}
				} catch (Exception e) {
				}
			}
			for (int i = -(k - 1); i <= k - 1; i++) {
				try {
					if (map[x1 + i][y1 - k] == 1) {
						nodeList.add(new Node(x1 + i, y1 - k));
					}
				} catch (Exception e) {
				}
			}
			for (int i = -(k - 1); i <= k - 1; i++) {
				try {
					if (map[x1 + i][y1 + k] == 1) {
						nodeList.add(new Node(x1 + i, y1 + k));
					}
				} catch (Exception e) {
				}
			}
			if (nodeList.size() > 0)
				break;
		}
		if (nodeList.size() < 1) {
			return null;
		} else {
			node = nodeList.get(0);
		}
		for (int i = 1; i < nodeList.size(); i++) {
			Node temp = nodeList.get(i);
			int xc = Math.abs(temp.getX() - x2);
			int yc = Math.abs(temp.getY() - y2);
			if (Math.abs(node.getX() - x2) + Math.abs(node.getY() - y2) > xc
					+ yc) {
				node = temp;
			}
		}
		return node;
	}
}

二、节点类
package com.cjx.path;
public class Node {
	@SuppressWarnings("unused")
	private int value;// 当前节点的值,0不可通过,1可通过.
	private int x;// x坐标
	private int y;// y坐标
	private int g;// g值 起始点到当前点
	private int h;// h值 当前点到目标点
	private int f;// f=g+h;
	private Node parentNode = null;
	/**
	 * @param x
	 * @param y
	 */
	public Node(int x, int y) {
		this.x = x;
		this.y = y;
	}
	/**
	 * @param map
	 *            地图
	 * @param x
	 *            x坐标
	 * @param y
	 *            y坐标
	 * @param parentNode
	 *            父节点
	 */
	public Node(int[][] map, int x, int y, Node parentNode) {
		this.x = x;
		this.y = y;
		this.parentNode = parentNode;
		try {
			this.value = map[x][y];
		} catch (java.lang.ArrayIndexOutOfBoundsException e) {
			this.value = 0;
		}
	}
	public int getX() {
		return x;
	}
	public int getY() {
		return y;
	}
	public int getF() {
		return f;
	}
	public void setF(int f) {
		this.f = f;
	}
	/** g值 起始点到当前点 */
	public int getG() {
		return g;
	}
	/** g值 起始点到当前点 */
	public void setG(int g) {
		this.g = g;
	}
	public int getH() {
		return h;
	}
	public void setH(int h) {
		this.h = h;
	}
	public Node getParentNode() {
		return parentNode;
	}
	public void setParentNode(Node parentNode) {
		this.parentNode = parentNode;
	}
}

三、常量类
package com.cjx.path;
public class Constant {
	/**横或竖向移动一格的路径评分*/
	public static int COST_STRAIGHT = 10;
	/**斜向移动一格的路径评分*/
	public static int COST_DIAGONAL = 14;
	/**不能行走*/
	public static int NOTE_NOWAY = 0;
	/**当前节点没使用过*/
	public static int NOTE_NONE = 0;
	/**在开启列表中 */
	public static int NOTE_OPEN = 1;
	/**在关闭列表中 */
	public static int NOTE_CLOSED = 2;
}
4
1
分享到:
评论

相关推荐

    A*算法源码及实验报告(java实现)

    采用二维的网格表示,其中0表示点可走,1表示点不可以走。点用( x, y )表示,寻找从某一个给定的起始单元格出发, 经由行相邻或列相邻的单元格(可以通过的),最终可以到达目标单元格的、所走过的单元格序列。...

    simhash算法的java实现simhash-java.zip

    simhash 算法的 java 实现。特点计算字符串的 simhash通过构建智能索引来计算所有字符串之间的相似性,因此可以处理大数据使用使用输入文件和输出文件运行 Maininputfile 的格式(参见 src / test_in):一个文件每...

    AStart寻路算法

    AStart寻路算法,代码为java

    java之A start算法演示

    这是我在CP大神的基础上亲自实践的java之A star算法窗口演示

    对Java Applet和Java Web Start进行数字签名

    对Java Applet和Java Web Start进行数字签名

    基于文本内容的协同过滤推荐算法实现(计算文本内容相似度)

    1、解压下载的CollaborativeFilteringBasedText压缩文件 2、操作系统中需装java jdk1.7或者以上版本 3、点击start.bat,在运行过程中,输出文本之间的距离和相似度

    计算机操作系统进程调度算法模拟

    (1) 用C、C++、Java语言编程实现对5个进程采用动态优先权调度算法进行调度的过程。数据如下: 5个进程的到达时刻和服务时间见下表,忽略I/O以及其它开销时间,使用动态优先权算法进行调度,优先权初始值为100,请...

    JAVA3d空间建模算法

    applet.start(); frame.setSize(300, 300); Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); Dimension frameSize = frame.getSize(); frame.setLocation((d.width - frameSize.width) / 2, (d....

    基于云模型的协同过滤推荐算法实现(输入用户id,输出用户相似度、最近邻居、推荐结果)

    操作说明: 1、解压下载的CollaborativeFilteringBasedUserCloud压缩...2、操作系统中需装java jdk1.7或者以上版本 3、点击start.bat,在运行过程中,会输出评分时间,然后输出用户id进行推荐 4、数据集movielens

    用java语言实现数字全排列

    4、从j=start开始到end结束,对排列中的每一个字符和a[start]进行比较,若a[j]==a[start]&&j!=start,跳过,否则,交换当前排列中位于start和j处的字符,再将start=start+1,并跳转到1,再将位于j和start处的字符...

    磁盘调度算法

    #include ...int start; //定义开始时磁头所在位置 void initial() { //初始化函数 int i; for(i = 0; i ; i++) { queue[i].go = -1; queue[i].visited = 0; } start = 50;

    使用动态优先权的进程调度算法的模拟

    (1)用C语言来实现对N个进程采用动态优先算法的进程调度; (2)每个用来标识进程的进程控制块 PCB用结构来描述,包括以下字段: 进程标识符id 进程优先数priority,并规定优先数越大的进程,其优先权越高; 进程已...

    达内 coreJava 习题答案

    a = 10*a +a1; // 这表示a 的下一项 // 每次 a 的下一项都等于前一项*10,再加上刚输入时的 a ;注意,这时的 a 已经变化了。 } System.out.println("sum="+sum); } } 8、求 2/1+3/2+5/3+8/5+13/8.....前20项...

    基于CBS算法多AGV路径规划仿真系统源代码+项目开发说明+演示程序(高分毕业设计)

    算法基本实现,逻辑已基本无bug 输入 : agent:start,end obstacles map:rows,cols 输出: - 不懂运行,下载完可以私聊问,可远程教学 该资源内项目源码是个人的毕设,代码都测试ok,都是运行成功后才上传...

    AStartText.java

    游戏里的人物自动寻路,怪物的寻路

    Java开发技术大全(500个源代码).

    signByIF.java 用if语句实现符号函数示例 triangleStar.java 输出一个由*组成的直角三角形 upperToLowCase.java 大写转换成小写 variableScopeExample.java 变量使用范围示例 第3章 示例描述:本章学习对象和类...

    操作系统Java实现SJF代码

    Process[] processes=start(p); Out(processes); } //输出 public static void Out(Process[] p){ DecimalFormat df = new DecimalFormat("#.00"); float sumWT=0; float sumWWT=0; float AverageWT; ...

    java程序设计填空题题库49道

    《java程序设计》课程的题库资料,由贺州学院整理,可供学生期末课程复习使用,也可以供相关任课教师出卷使用。 内容示例为: 40. __________包包含了Collection的接口的类的API。 答案:Java.util 41. Math.round...

    A_Star:它是 A* 寻路算法的演示

    一个明星它是 A* 寻路算法的演示。 非常感谢 Patrick Lester 的解释 //他的网站这只是一个演示。 所以你不能使用任何方法。 对不起。 只需阅读链接,开始演示,画一些墙,设置开始和结束,按开始并观看。 控制:有两...

Global site tag (gtag.js) - Google Analytics