A*寻路算法就是启发式探索的一个典型实践,在寻路的过程中,给每个节点绑定了一个估计值(即启发式),在对节点的遍历过程中是采取估计值优先原则,估计值更优的节点会被优先遍历。
如下图区域,被简化成6*6的小方格。其中绿色表示起点,红色表示终点,黑色表示路障,不能通行。

先描述A*算法的大致过程:
- 将初始节点放入到open列表中。
- 判断open列表。如果为空,则搜索失败。如果open列表中存在目标节点,则搜索成功。
- 从open列表中取出F值最小的节点作为当前节点,并将其加入到close列表中。
- 计算当前节点的相邻的所有可到达节点,生成一组子节点。对于每一个子节点:
- 如果该节点在close列表中,则丢弃它
- 如果该节点在open列表中,则检查其通过当前节点计算得到的F值是否更小,如果更小则更新其F值,并将其父节点设置为当前节点。
- 如果该节点不在open列表中,则将其加入到open列表,并计算F值,设置其父节点为当前节点。
- 转到2步骤
概括:
1、两个集合+一个公式
* openlist\closelist --- 集合
* F=G+H --- 公式
* openlist:可达到的格子
* closelist:已经到达的格子
* G:从起点到当前格子的成本
* H:不考虑障碍的情况下,当前格子到目标格子的距离
* F:G+H

代码如下:
package com.wemew.wmgame.sort;
import java.util.ArrayList;
import java.util.List;
/**
* A*寻路算法
* <p>
* 寻路算法
* 1、两个集合+一个公式
* openlist\closelist
* F=G+H
* openlist:可达到的格子
* closelist:已经到达的格子
* G:从起点到当前格子的成本
* H:不考虑障碍的情况下,当前格子到目标格子的距离
* F:G+H
*
*/
public class FindRoad {
public static void main(String[] args) {
Grid startgrid = new Grid(2, 1);
Grid endgrid = new Grid(2, 5);
Grid grid = aStarSearch(startgrid, endgrid);
List<Grid> path = new ArrayList();
while (grid != null) {
path.add(new Grid(grid.x, grid.y));
grid = grid.parent;
}
// 循环打印
for (int i = 0; i < MAZE.length; i++) {
for (int i1 = 0; i1 < MAZE[0].length; i1++) {
if (containArrys(path, i, i1)) {
System.out.print("$" + " ,");
} else {
System.out.print(MAZE[i][i1] + " ,");
}
}
System.out.println();
}
/**
* 0 ,0 ,$ ,$ ,$ ,$ ,0 ,
* 0 ,0 ,$ ,1 ,0 ,$ ,0 ,
* 0 ,$ ,$ ,1 ,0 ,$ ,0 ,
* 0 ,0 ,0 ,1 ,0 ,0 ,0 ,
* 0 ,0 ,0 ,0 ,0 ,0 ,0 ,
*/
}
public static final int[][] MAZE = {
{0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0},
};
/**
* 寻路主逻辑
*
* @param start
* @param end
* @return
*/
public static Grid aStarSearch(Grid start, Grid end) {
List<Grid> openList = new ArrayList<>();
List<Grid> closeList = new ArrayList<>();
// 先加入到openlist
openList.add(start);
while (openList.size() > 0) {
// 找到当前最小的F值
Grid cureentGrid = fineMinGrid(openList);
// 移除 openList
openList.remove(cureentGrid);
// 移动到 closeList
closeList.add(cureentGrid);
// 查询出附近的最佳节点
List<Grid> neibers = findNeibers(cureentGrid, openList, closeList);
for (Grid neiber : neibers) {
if (!openList.contains(neiber)) {
neiber.initGrid(cureentGrid, end);
openList.add(neiber);
}
}
for (Grid grid : openList) {
if (end.x == grid.x && end.y == grid.y) {
return grid;
}
}
}
return null;
}
public static Grid fineMinGrid(List<Grid> grids) {
Grid grid = grids.get(0);
for (Grid grid1 : grids) {
if (grid.getF() > grid1.getF()) {
grid = grid1;
}
}
return grid;
}
public static List<Grid> findNeibers(Grid grid, List<Grid> openList, List<Grid> closeList) {
List<Grid> arraylist = new ArrayList<>();
// 上
if (isValidate(grid.x, grid.y - 1, openList, closeList)) {
arraylist.add(new Grid(grid.x, grid.y - 1));
}
// 下
if (isValidate(grid.x, grid.y + 1, openList, closeList)) {
arraylist.add(new Grid(grid.x, grid.y + 1));
}
// 左
if (isValidate(grid.x - 1, grid.y, openList, closeList)) {
arraylist.add(new Grid(grid.x - 1, grid.y));
}
// 右
if (isValidate(grid.x + 1, grid.y, openList, closeList)) {
arraylist.add(new Grid(grid.x + 1, grid.y));
}
return arraylist;
}
public static boolean isValidate(int x, int y, List<Grid> openList, List<Grid> closeList) {
// 是否越过边界
if (x < 0 || x >= MAZE.length || y < 0 || y >= MAZE[0].length) {
return false;
}
// 是否越过障碍
if (MAZE[x][y] == 1) {
return false;
}
// 是否包含openList
if (containArrys(openList, x, y)) {
return false;
}
// 是否包含openList
if (containArrys(closeList, x, y)) {
return false;
}
return true;
}
public static boolean containArrys(List<Grid> openList, int x, int y) {
for (Grid grid : openList) {
if (grid.x == x && grid.y == y) {
return true;
}
}
return false;
}
static class Grid {
int x;
int y;
int f;
int g;
int h;
Grid parent;
// f g h
void initGrid(Grid parent, Grid end) {
this.parent = parent;
if (parent != null) {
this.g = parent.g + 1;
} else {
this.g = 1;
}
// 计算h值
this.h = Math.abs(this.x - end.x) + Math.abs(this.y - end.y);
// 计算f值
this.f = this.g + this.h;
}
public Grid(int x, int y) {
this.x = x;
this.y = y;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getF() {
return f;
}
public void setF(int f) {
this.f = f;
}
public int getG() {
return g;
}
public void setG(int g) {
this.g = g;
}
public int getH() {
return h;
}
public void setH(int h) {
this.h = h;
}
public Grid getParent() {
return parent;
}
public void setParent(Grid parent) {
this.parent = parent;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
}
}
版权声明:本文为javashareauthor原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。