a算法java_A星算法Java实现详解

import java.util.ArrayList;

import java.util.Collections;

import java.util.Comparator;

import java.util.List;

public class AStar {

private int[][] map;// 地图(1可通过 0不可通过)

private List openList;// 开启列表

private List closeList;// 关闭列表

private final int COST_STRAIGHT = 10;// 垂直方向或水平方向移动的路径评分

private final int COST_DIAGONAL = 14;// 斜方向移动的路径评分

private int row;// 行

private int column;// 列

public AStar(int[][] map, int row, int column) {

this.map = map;

this.row = row;

this.column = column;

openList = new ArrayList();

closeList = new ArrayList();

}

// 查找坐标(-1:错误,0:没找到,1:找到了)

public int search(int x1, int y1, int x2, int y2) {

if (x1 < 0 || x1 >= row || x2 < 0 || x2 >= row || y1 < 0

|| y1 >= column || y2 < 0 || y2 >= column) {

return -1;

}

if (map[x1][y1] == 0 || map[x2][y2] == 0) {

return -1;

}

Node sNode = new Node(x1, y1, null);

Node eNode = new Node(x2, y2, null);

openList.add(sNode);

List resultList = search(sNode, eNode);

if (resultList.size() == 0) {

return 0;

}

for (Node node : resultList) {

map[node.getX()][node.getY()] = -1;

}

return 1;

}

// 查找核心算法

private List search(Node sNode, Node eNode) {

List resultList = new ArrayList();

boolean isFind = false;

Node node = null;

while (openList.size() > 0) {

// 取出开启列表中最低F值,即第一个存储的值的F为最低的

node = openList.get(0);

// 判断是否找到目标点

if (node.getX() == eNode.getX() && node.getY() == eNode.getY()) {

isFind = true;

break;

}

// 上

if ((node.getY() - 1) >= 0) {

checkPath(node.getX(), node.getY() - 1, node, eNode,

COST_STRAIGHT);

}

// 下

if ((node.getY() + 1) < column) {

checkPath(node.getX(), node.getY() + 1, node, eNode,

COST_STRAIGHT);

}

// 左

if ((node.getX() - 1) >= 0) {

checkPath(node.getX() - 1, node.getY(), node, eNode,

COST_STRAIGHT);

}

// 右

if ((node.getX() + 1) < row) {

checkPath(node.getX() + 1, node.getY(), node, eNode,

COST_STRAIGHT);

}

// 左上

if ((node.getX() - 1) >= 0 && (node.getY() - 1) >= 0) {

checkPath(node.getX() - 1, node.getY() - 1, node, eNode,

COST_DIAGONAL);

}

// 左下

if ((node.getX() - 1) >= 0 && (node.getY() + 1) < column) {

checkPath(node.getX() - 1, node.getY() + 1, node, eNode,

COST_DIAGONAL);

}

// 右上

if ((node.getX() + 1) < row && (node.getY() - 1) >= 0) {

checkPath(node.getX() + 1, node.getY() - 1, node, eNode,

COST_DIAGONAL);

}

// 右下

if ((node.getX() + 1) < row && (node.getY() + 1) < column) {

checkPath(node.getX() + 1, node.getY() + 1, node, eNode,

COST_DIAGONAL);

}

// 从开启列表中删除

// 添加到关闭列表中

closeList.add(openList.remove(0));

// 开启列表中排序,把F值最低的放到最底端

Collections.sort(openList, new NodeFComparator());

}

if (isFind) {

getPath(resultList, node);

}

return resultList;

}

// 查询此路是否能走通

private boolean checkPath(int x, int y, Node parentNode, Node eNode,

int cost) {

Node node = new Node(x, y, parentNode);

// 查找地图中是否能通过

if (map[x][y] == 0) {

closeList.add(node);

return false;

}

// 查找关闭列表中是否存在

if (isListContains(closeList, x, y) != -1) {

return false;

}

// 查找开启列表中是否存在

int index = -1;

if ((index = isListContains(openList, x, y)) != -1) {

// G值是否更小,即是否更新G,F值

if ((parentNode.getG() + cost) < openList.get(index).getG()) {

node.setParentNode(parentNode);

countG(node, eNode, cost);

countF(node);

openList.set(index, node);

}

} else {

// 添加到开启列表中

node.setParentNode(parentNode);

count(node, eNode, cost);

openList.add(node);

}

return true;

}

// 集合中是否包含某个元素(-1:没有找到,否则返回所在的索引)

private int isListContains(List list, int x, int y) {

for (int i = 0; i < list.size(); i++) {

Node node = list.get(i);

if (node.getX() == x && node.getY() == y) {

return i;

}

}

return -1;

}

// 从终点往返回到起点

private void getPath(List resultList, Node node) {

if (node.getParentNode() != null) {

getPath(resultList, node.getParentNode());

}

resultList.add(node);

}

// 计算G,H,F值

private void count(Node node, Node eNode, int cost) {

countG(node, eNode, cost);

countH(node, eNode);

countF(eNode);

}

// 计算G值

private void countG(Node node, Node eNode, int cost) {

if (node.getParentNode() == null) {

node.setG(cost);

} else {

node.setG(node.getParentNode().getG() + cost);

}

}

// 计算H值

private void countH(Node node, Node eNode){

int x = Math.abs(node.getX() - eNode.getX());

int y = Math.abs(node.getY() - eNode.getY());

if(x

node.setH(x * COST_DIAGONAL + (y-x) * COST_STRAIGHT);

}else{

node.setH(y * COST_DIAGONAL + (x-y) * COST_STRAIGHT);

}

}

// 计算F值

private void countF(Node node) {

node.setF(node.getG() + node.getH());

}

public static void main(String[] args) {

int[][] map=new int[][]{// 地图数组

{1,1,1,1,1,1,1,1,1,1},

{1,1,1,1,0,1,1,1,1,1},

{1,1,1,1,0,1,1,1,1,1},

{1,1,1,1,0,1,1,1,1,1},

{1,1,1,1,0,1,1,1,1,1},

{1,1,1,1,0,1,1,1,1,1}

};

AStar aStar=new AStar(map, 6, 10);

int flag=aStar.search(4, 0, 3, 8);

if(flag==-1){

System.out.println("传输数据有误!");

}else if(flag==0){

System.out.println("没找到!");

}else{

for(int x=0;x<6;x++){

for(int y=0;y<10;y++){

if(map[x][y]==1){

System.out.print(" ");

}else if(map[x][y]==0){

System.out.print("〓");

}else if(map[x][y]==-1){

System.out.print("※");

}

}

System.out.println();

}

}

}

}

// 节点类

class Node {

private int x;// X坐标

private int y;// Y坐标

private Node parentNode;// 父类节点

private int g;// 当前点到起点的移动耗费

private int h;// 当前点到终点的移动耗费,即曼哈顿距离|x1-x2|+|y1-y2|(忽略障碍物)

private int f;// f=g+h

public Node(int x, int y, Node parentNode) {

this.x = x;

this.y = y;

this.parentNode = parentNode;

}

public int getX() {

return x;

}

public void setX(int x) {

this.x = x;

}

public int getY() {

return y;

}

public void setY(int y) {

this.y = y;

}

public Node getParentNode() {

return parentNode;

}

public void setParentNode(Node parentNode) {

this.parentNode = parentNode;

}

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 int getF() {

return f;

}

public void setF(int f) {

this.f = f;

}

}

// 节点比较类

class NodeFComparator implements Comparator {

@Override

public int compare(Node o1, Node o2) {

return o1.getF() - o2.getF();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值