用a*算法实现推箱子_A*寻路算法 java实现 简单版

本文介绍了如何使用A*寻路算法在Java中实现推箱子问题。通过理解A*算法的核心思想,结合示例代码,详细解释了最短路径计算和避开障碍物的策略。读者可以通过代码运行和调试加深理解。
摘要由CSDN通过智能技术生成

参考:https://www.bilibili.com/video/av23095766?from=search&seid=17012483131579025134

A*(也叫A star, A星)寻路算法Java版

A* 寻路算法 - christanxw的专栏 - C++博客

A*寻路算法(下面简称A星算法),就是在一个矩阵里,一个点到另一个点的最短路径的求解。这里面可能含有很多障碍物。所以,可以用于迷宫找到出口的路径,地图上的导航,游戏中的点到点的路径确定之类的场合当中。

要理解这个算法,感觉如果基础不太好的话,建议先看第一个视频,用1.5倍速观看,关键是对中间部分的那个图的演示过程有深入的理解。然后就能理解它是怎么样寻路的。 接着可以看第三个连接,这是一个相当于对视频的讲解,博主也很费心的画出了过程图。 最后是看第二个链接的代码,然后一步一步去理解就ok了。

我这里先针对算法里面的重点部分进行形象讲解,然后再对代码进行详细的展示。代码参考第二个链接。如下图:

ba648d02a6168f64e1f10edbfa42b832.png

A星寻路算法解决的问题就是:我们如何走最短的路径从左边的绿点,不经过中间的红点,到达右边的绿点。

我们从视觉上很容易得出结果,但是我们需要使用算法来解决问题。所以,我们需要先用二维数组来描述上面这个输入信息,旁边的数字是二维数组的坐标。描述可走路径的值为0,不可走路径(即红色部分为1)

我们需要先冷静下来思考,我们关键是要解决什么东西?

1.最短路径

2.避开障碍物

然后互我们先来解决第一个问题:

如何得到最短路径:

公式 :F=G+H

含义:G:起点到当前点的距离 H :当前点到终点的距离。

F:等于前面两者之和,用于判定下一节点该往哪里走。如下图,此时,我们先不考虑障碍物先。

cad8c2f32e47dc4ff1e072d26f981a9f.png

一个方格内:左下角为G值,右下角为H值,左上角为F值。以横竖方向的距离为10,斜方向的为14,相当于根号2,即1.414x10。让人的视觉好处理。所以大家应该能看懂上面的三个格子吧?这里只考虑了G值得斜方向,没有考虑H值得斜方向。这里只是举个例子,让大家深入了解这个公式的意义。

然后,我们让下一步走在F值最小的格子上,如果是上图,那么就是F值为40的格子,然后依次类推,就可以找到去终点的最短路径。(这里只是进行了最简单的解释,也就是大概个原理,后面看代码才是最重要的)

然后我们来看第二个问题:怎么避开障碍物

这里是在前面的基础上,在寻找周围节点的时候,看看它的值是不是0,如果不是,就不把它放在下一步的考虑范围内就行了。

看完上面的感觉还不理解?没事,上面本来就是先打一层铺垫,后面看代码才是最完整的。

先上代码: 全部参考上面的第二个链接,但是感觉讲得不详细,所以我做的就是详尽的解释和理解。

import java.util.ArrayList;
import java.util.List;

//第一遍看懂了怎么找到最短路径,但是没看出它是怎么避过障碍物的,可是它却实现了避过障碍物
public class AStar {
	public static final int[][] NODES = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, };

	public static final int STEP = 10;

	private ArrayList<Node> openList = new ArrayList<Node>();
	private ArrayList<Node> closeList = new ArrayList<Node>();

	public Node findMinFNodeInOpenList() {
		Node tempNode = openList.get(0); // 先以第一个元素的F为最小值,然后遍历openlist的所有值,找出最小值
		for (Node node : openList) {
			if (node.F < tempNode.F) {
				tempNode = node;
			}
		}
		return tempNode;
	}

	// 考虑周围节点的时候,就不把节点值为1的节点考虑在内,所以自然就直接避开了障碍物
	public ArrayList<Node> findNeighborNodes(Node currentNode) {
		ArrayList<Node> arrayList = new ArrayList<Node>();
		// 只考虑上下左右,不考虑斜对角
		int topX = currentNode.x;
		int topY = currentNode.y - 1;
		// canReach方法确保下标没有越界 exists方法确保此相邻节点不存在于closeList中,也就是之前没有遍历过
		if (canReach(topX, topY) && !exists(closeList, topX, topY)) {
			arrayList.add(new Node(topX, topY));
		}
		int bottomX = currentNode.x;
		int bottomY = currentNode.y + 1;
		if (canReach(bottomX, bottomY) && !exists(closeList, bottomX, bottomY)) {
			arrayList.add(new Node(bottomX, bottomY));
		}
		int leftX = currentNode.x - 1;
		int leftY = currentNode.y;
		if (canReach(leftX, leftY) && !exists(closeList, leftX, leftY)) {
			arrayList.add(new Node(leftX, leftY));
		}
		int rightX = currentNode.x 
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值