博主真的有段时间没写博客了,主要这段时间在练内功(算法和数据结构),因此就没有写博客了。这次用两个小时写出了寻路算法,算是对之前博主学习进程的一个交待吧。
我们回归正题,BFS和DFS是我们遍历链表树图等等数据结构时候的一种方法,而寻路换句话说就是从起点遍历到终点的过程。(我就不介绍寻路方面的最基础的问题,大家如果需要从头了解的话可以看其他人的博客)
我先默认大家已经了解并掌握了BFS和DFS的基本概念;广度遍历和深度遍历。即使用队列和栈遍历的两种方法。
1,保存路径
寻路算法相比于我们平常使用BFS,DFS时特殊的点在于,判断走得到后,然后保存走过的路径。
以BFS为例如果队列中只储存当前的坐标,即只储存一个一维数组,很显然我们遍历到终点时我们根本不知道终点的前一个节点是什么。
因此我们要让各个有关系的节点关联起来,很显然我们这个时候想到了链表这个结构,即这个时候,以BFS为例,我们的队列储存节点,在这个节点下储存当前的坐标,以及他的父节点。通过这样的方式,当我们到达终点时,我们取出终点这个节点时候就可以遍历得到整个路径。
2 ,A*寻路
BFS是盲目的一种遍历方式,换句话说,你得到的路径很有可能不是最短路径,BFS还好些,DFS那是真的没法用(如果你的深度是无限的话,那你可能永远也别想得到这条路径了)。
因此我们引入优先级,让机器人以一定的想法挑选路径,即,在这我们使用优先队列进行BFS,而优先级的判断,我们采用走过的路程数以及离终点的x + y(曼哈顿距离)的和来判断。这样当我们可能绕远路时我们就可以先暂时跳过他,先遍历另一条有可能更近的路。
为什么这样可以实现?就需要大家自己先用笔在脑海或者书上演示一遍了。
我的代码如下(大家看看有什么地方可以优化下吗?说实话有些地方的代码,写了之后我自己看得挺难受的)
package 寻路算法;
/*
* @param a 所有障碍物的坐标 二维数组
* @param x 起始区域左上角坐标点
* @param length 正方形一排的块数
* @param width 一块正方形的大小(长宽)
* @param start 起始点坐标 一维数组
* @param end 终点坐标 一维数组
*/
import java.awt.*;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
public class JScene extends JFrame {
private static Graphics g;
private int x, length, width;
private int[][] a = new int[100][2]; // 障碍物的坐标
private int[] start = new int[2];
private int[] end = new int[2];
public void paint(Graphics g) {
}
public JScene(int x, int length, int width) {
this.x = x;
this.length = length;
this.width = width;
Random rand = new Random();
this.start[0] = rand.nextInt(length + 1);
this.start[1] = rand.nextInt(length + 1);
this.end[0] = rand.nextInt(length + 1);
this.end[1] = rand.nextInt(length + 1);
}
public JScene() {
}
public void initUI() {
this.setTitle("A星寻路算法");
this.setSize(800,800);
this.setDefaultCloseOperation(3);
this.setLocationRelativeTo(null);
this.setVisible(true);
g = this.getGraphics();
g.setColor(Color.green);
g.fillRect(x + start[0] * width, x + start[1] * width, width, width);
g.setColor(Color.red);
g.fillRect(x + end[0] * width, x + end[1] * width, width, width);
g.setColor(Color.black);
this.paintsolid(a);
ArrayList<int[]> list = AStarSearch.AStarSearching(a, x, length, width, start, end);
for(int i = 0; i < list.size() - 1; i ++){
g.drawLine(x + list.get(i)[0] * width + width / 2, x + width *