`
cjx186
  • 浏览: 269692 次
  • 性别: 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实现

    在这个Java实现中,我们将探讨A*算法的基本原理、关键代码实现以及如何在Java环境中应用。 A*算法的核心在于它利用了一个评估函数f(n) = g(n) + h(n),其中g(n)是从起点到当前节点的实际代价,h(n)是从当前节点到...

    A*算法实验报告广工(附源码java)

    根据给定的实验报告标题“**A*算法实验报告广工(附源码java)**”及其描述“**对下图所示的迷宫问题,用A*算法为机器人搜索一条路径:其中(1, 1) 为起始点,(4, 4) 为目标点,启发函数采用曼哈顿距离**”,我们可以...

    A*算法实例,模拟运输

    - **CourierDelivery.java**:可能是整个系统的主控制器,负责设置问题、调用A*算法并处理结果。 - **Task.java** 和 **Job.java**:可能代表任务和工作,比如取包裹和送包裹的任务,它们可能包含位置信息、包裹数量...

    java之A start算法演示

    在"Astar算法.rar"和"astart"这两个文件中,包含了具体的代码实现和可能的测试数据。通过阅读和理解这些代码,你可以更深入地了解A*算法在Java环境中的实际应用。同时,实践运行程序并观察结果将有助于巩固理论知识...

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

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

    A* 寻路算法以及Java代码

    本文将详细介绍 A* 寻路算法的原理、实现步骤和Java代码实例。 一、A* 寻路算法原理 A* 寻路算法是基于图搜索算法的一种变形,使用启发式函数来估算从当前节点到目标节点的距离。该算法的核心思想是从起点出发,...

    图搜索 A* JAVA

    **A* 搜索算法简介** A*(发音“A-star”)是一种在图形中寻找路径的高效搜索算法,广泛应用于游戏开发、地图导航、机器人路径规划等领域。它结合了最佳优先搜索(Best-First Search)和Dijkstra算法的优点,通过...

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

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

    Java实现的等距网格A-Star最短路径规划

    本项目以Java语言实现了基于A*算法的等距网格最短路径规划,集成于SpringBoot框架,为外部提供了一个高效的接口服务。 首先,让我们深入了解A*算法。A*算法的核心在于它使用了启发式函数(通常为曼哈顿距离或...

    AStart寻路算法

    AStart寻路算法,代码为java

    各种排序算法java实现

    根据给定的信息,我们可以深入探讨几种常见的排序算法及其Java实现方式。这些算法包括插入排序(Insert Sort)、冒泡排序(Bubble Sort)、选择排序(Selection Sort)以及希尔排序(Shell Sort)。接下来,我们将...

    java实现的Dijstral算法

    在这个Java实现中,算法的目标是找到从一个给定的起始节点到图中所有其他节点的最短路径。以下是对代码的详细解释: 1. **数据结构与变量**: - `A` 是一个二维浮点数数组,代表图的邻接矩阵,其中 `A[i][j]` 存储...

    死锁算法 Java实现 操作系统

    本教程将通过Java实现死锁的模拟,帮助学习者理解这一复杂的概念,并提供一个简单的、易于理解的解决方案。 首先,我们需要了解死锁的四个必要条件: 1. **互斥条件**:资源必须被单个进程独占,即在同一时刻,...

    Prim算法Java实现

    ### Prim算法Java实现 #### 背景与概念 Prim算法是一种用于寻找加权无向图中的最小生成树(Minimum Spanning Tree, MST)的经典算法。一个无向加权图由一组顶点和一组边组成,每条边都有一个权重值。在本任务中,...

    java算法 经典算法

    ### Java经典算法知识点详解 #### 一、斐波那契数列问题 ...以上仅为部分Java经典算法问题的解析与实现,每个问题都围绕着具体的算法思想和编程技巧展开,有助于加深对Java语言的理解和应用能力。

    java常用算法 代码

    以上介绍了五种常用的排序算法及其Java实现。每种算法都有其特点和适用场景,实际应用时应根据具体情况选择合适的排序算法。例如,对于小规模的数据集,插入排序可能是更好的选择;而对于大规模数据集,快速排序则...

    Java运行环境Java运行环境

    9. **Java平台独立性**:Java运行环境通过Java Application Launcher(JAR文件)和Java Web Start技术,保证了程序可以在任何安装了相应JRE的操作系统上运行,如Windows、Mac OS、Linux等。 10. **Java安全模型**:...

    各种排序算法 JAVA代码实现

    根据提供的文件信息,我们可以归纳总结出以下几个主要的排序算法及其JAVA代码实现: ### 1. 插入排序(Insert Sort) 插入排序是一种简单的排序方法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序...

Global site tag (gtag.js) - Google Analytics