日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java做a_Java编程实现A*算法完整代码

發布時間:2024/9/27 java 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java做a_Java编程实现A*算法完整代码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

A*搜尋算法俗稱A星算法。這是一種在圖形平面上,有多個節點的路徑,求出最低通過成本的算法。常用于游戲中

通過二維數組構建的一個迷宮,“%”表示墻壁,A為起點,B為終點,“#”代表障礙物,“*”代表算法計算后的路徑

本文實例代碼結構:

% % % % % % %

% o o o o o %

% o o # o o %

% A o # o B %

% o o # o o %

% o o o o o %

% % % % % % %

=============================

經過A*算法計算后

=============================

% % % % % % %

% o o * o o %

% o * # * o %

% A o # o B %

% o o # o o %

% o o o o o %

% % % % % % % <

算法理論

算法的核心公式為:F=G+H

把地圖上的節點看成一個網格。

G=從起點A,沿著產生的路徑,移動到網格上指定節點的移動消耗,在這個例子里,我們令水平或者垂直移動的耗費為10,對角線方向耗費為14。我們取這些值是因為沿對角線

的距離是沿水平或垂直移動耗費的的根號2,或者約1.414倍。為了簡化,我們用10和14近似。

既然我們在計算沿特定路徑通往某個方格的G值,求值的方法就是取它父節點的G值,然后依照它相對父節點是對角線方向或者直角方向(非對角線),分別增加14和10。例子中這

個方法的需求會變得更多,因為我們從起點方格以外獲取了不止一個方格。

H=從當前格移動到終點B的預估移動消耗。為什么叫”預估“呢,因為我們沒有辦法事先知道路徑的長度,這里我們使用曼哈頓方法,它計算從當前格到目的格之間水平和垂直

的方格的數量總和,忽略對角線方向。然后把結果乘以10。

F的值是G和H的和,這是我們用來判斷優先路徑的標準,F值最小的格,我們認為是優先的路徑節點。

實現步驟

算法使用java寫的,先看一看節點類的內容

package a_star_search;

/**

* 節點類

* @author zx

*

*/

public class Node {

private int x; //x坐標

private int y; //y坐標

private String value; //表示節點的值

private double FValue = 0; //F值

private double GValue = 0; //G值

private double HValue = 0; //H值

private boolean Reachable; //是否可到達(是否為障礙物)

private Node PNode; //父節點

public Node(int x, int y, String value, boolean reachable) {

super();

this.x = x;

this.y = y;

this.value = value;

Reachable = reachable;

}

public Node() {

super();

}

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 String getValue() {

return value;

}

public void setValue(String value) {

this.value = value;

}

public double getFValue() {

return FValue;

}

public void setFValue(double fValue) {

FValue = fValue;

}

public double getGValue() {

return GValue;

}

public void setGValue(double gValue) {

GValue = gValue;

}

public double getHValue() {

return HValue;

}

public void setHValue(double hValue) {

HValue = hValue;

}

public boolean isReachable() {

return Reachable;

}

public void setReachable(boolean reachable) {

Reachable = reachable;

}

public Node getPNode() {

return PNode;

}

public void setPNode(Node pNode) {

PNode = pNode;

}

}

還需要一個地圖類,在map的構造方法中,我通過創建節點的二維數組來實現一個迷宮地圖,其中包括起點和終點

package a_star_search;

public class Map {

private Node[][] map;

//節點數組

private Node startNode;

//起點

private Node endNode;

//終點

public Map() {

map = new Node[7][7];

for (int i = 0;i<7;i++){

for (int j = 0;j<7;j++){

map[i][j] = new Node(i,j,"o",true);

}

}

for (int d = 0;d<7;d++){

map[0][d].setValue("%");

map[0][d].setReachable(false);

map[d][0].setValue("%");

map[d][0].setReachable(false);

map[6][d].setValue("%");

map[6][d].setReachable(false);

map[d][6].setValue("%");

map[d][6].setReachable(false);

}

map[3][1].setValue("A");

startNode = map[3][1];

map[3][5].setValue("B");

endNode = map[3][5];

for (int k = 1;k<=3;k++){

map[k+1][3].setValue("#");

map[k+1][3].setReachable(false);

}

}

//展示地圖

public void ShowMap(){

for (int i = 0;i<7;i++){

for (int j = 0;j<7;j++){

System.out.print(map[i][j].getValue()+" ");

}

System.out.println("");

}

}

public Node[][] getMap() {

return map;

}

public void setMap(Node[][] map) {

this.map = map;

}

public Node getStartNode() {

return startNode;

}

public void setStartNode(Node startNode) {

this.startNode = startNode;

}

public Node getEndNode() {

return endNode;

}

public void setEndNode(Node endNode) {

this.endNode = endNode;

}

}

下面是最重要的AStar類

操作過程

1從起點A開始,并且把它作為待處理點存入一個“開啟列表”,這是一個待檢查方格的列表。

2尋找起點周圍所有可到達或者可通過的方格,跳過無法通過的方格。也把他們加入開啟列表。為所有這些方格保存點A作為“父方格”。當我們想描述路徑的時候,父方格的資

料是十分重要的。后面會解釋它的具體用途。

3從開啟列表中刪除起點A,把它加入到一個“關閉列表”,列表中保存所有不需要再次檢查的方格。

經過以上步驟,“開啟列表”中包含了起點A周圍除了障礙物的所有節點。他們的父節點都是A,通過前面講的F=G+H的公式,計算每個節點的G,H,F值,并按照F的值大小,從小

到大進行排序。并對F值最小的那個節點做以下操作

4,把它從開啟列表中刪除,然后添加到關閉列表中。

5,檢查所有相鄰格子。跳過那些不可通過的(1.在”關閉列表“中,2.障礙物),把他們添加進開啟列表,如果他們還不在里面的話。把選中的方格作為新的方格的父節點。

6,如果某個相鄰格已經在開啟列表里了,檢查現在的這條路徑是否更好。換句話說,檢查如果我們用新的路徑到達它的話,G值是否會更低一些。如果不是,那就什么都不

做。(這里,我的代碼中并沒有判斷)

7,我們重復這個過程,直到目標格(終點“B”)被添加進“開啟列表”,說明終點B已經在上一個添加進“關閉列表”的節點的周圍,只需走一步,即可到達終點B。

8,我們將終點B添加到“關閉列表”

9,最后一步,我們要將從起點A到終點B的路徑表示出來。父節點的作用就顯示出來了,通過“關閉列表”中的終點節點的父節點,改變其value值,順藤摸瓜即可以顯示出路徑。

看看代碼

package a_star_search;

import java.util.ArrayList;

public class AStar {

/**

* 使用ArrayList數組作為“開啟列表”和“關閉列表”

*/

ArrayList open = new ArrayList();

ArrayList close = new ArrayList();

/**

* 獲取H值

* @param currentNode:當前節點

* @param endNode:終點

* @return

*/

public double getHValue(Node currentNode,Node endNode){

return (Math.abs(currentNode.getX() - endNode.getX()) + Math.abs(currentNode.getY() - endNode.getY()))*10;

}

/**

* 獲取G值

* @param currentNode:當前節點

* @return

*/

public double getGValue(Node currentNode){

if(currentNode.getPNode()!=null){

if(currentNode.getX()==currentNode.getPNode().getX()||currentNode.getY()==currentNode.getPNode().getY()){

//判斷當前節點與其父節點之間的位置關系(水平?對角線)

return currentNode.getGValue()+10;

}

return currentNode.getGValue()+14;

}

return currentNode.getGValue();

}

/**

* 獲取F值 : G + H

* @param currentNode

* @return

*/

public double getFValue(Node currentNode){

return currentNode.getGValue()+currentNode.getHValue();

}

/**

* 將選中節點周圍的節點添加進“開啟列表”

* @param node

* @param map

*/

public void inOpen(Node node,Map map){

int x = node.getX();

int y = node.getY();

for (int i = 0;i<3;i++){

for (int j = 0;j<3;j++){

//判斷條件為:節點為可到達的(即不是障礙物,不在關閉列表中),開啟列表中不包含,不是選中節點

if(map.getMap()[x-1+i][y-1+j].isReachable()&&!open.contains(map.getMap()[x-1+i][y-1+j])&&!(x==(x-1+i)&&y==(y-1+j))){

map.getMap()[x-1+i][y-1+j].setPNode(map.getMap()[x][y]);

//將選中節點作為父節點

map.getMap()[x-1+i][y-1+j].setGValue(getGValue(map.getMap()[x-1+i][y-1+j]));

map.getMap()[x-1+i][y-1+j].setHValue(getHValue(map.getMap()[x-1+i][y-1+j],map.getEndNode()));

map.getMap()[x-1+i][y-1+j].setFValue(getFValue(map.getMap()[x-1+i][y-1+j]));

open.add(map.getMap()[x-1+i][y-1+j]);

}

}

}

}

/**

* 使用冒泡排序將開啟列表中的節點按F值從小到大排序

* @param arr

*/

public void sort(ArrayList arr){

for (int i = 0;i

for (int j = i+1;j

if(arr.get(i).getFValue() > arr.get(j).getFValue()){

Node tmp = new Node();

tmp = arr.get(i);

arr.set(i, arr.get(j));

arr.set(j, tmp);

}

}

}

}

/**

* 將節點添加進”關閉列表“

* @param node

* @param open

*/

public void inClose(Node node,ArrayList open){

if(open.contains(node)){

node.setReachable(false);

//設置為不可達

open.remove(node);

close.add(node);

}

}

public void search(Map map){

//對起點即起點周圍的節點進行操作

inOpen(map.getMap()[map.getStartNode().getX()][map.getStartNode().getY()],map);

close.add(map.getMap()[map.getStartNode().getX()][map.getStartNode().getY()]);

map.getMap()[map.getStartNode().getX()][map.getStartNode().getY()].setReachable(false);

map.getMap()[map.getStartNode().getX()][map.getStartNode().getY()].setPNode(map.getMap()[map.getStartNode().getX()][map.getStartNode().getY()]);

sort(open);

//重復步驟

do{

inOpen(open.get(0), map);

inClose(open.get(0), open);

sort(open);

}

while(!open.contains(map.getMap()[map.getEndNode().getX()][map.getEndNode().getY()]));

//知道開啟列表中包含終點時,循環退出

inClose(map.getMap()[map.getEndNode().getX()][map.getEndNode().getY()], open);

showPath(close,map);

}

/**

* 將路徑標記出來

* @param arr

* @param map

*/

public void showPath(ArrayList arr,Map map) {

if(arr.size()>0){

Node node = new Node();

// node = map.getMap()[map.getEndNode().getX()][map.getEndNode().getY()];

// while(!(node.getX() ==map.getStartNode().getX()&&node.getY() ==map.getStartNode().getY())){

// node.getPNode().setValue("*");

// node = node.getPNode();

// }

}

// map.getMap()[map.getStartNode().getX()][map.getStartNode().getY()].setValue("A");

}

}

最后寫一個Main方法

package a_star_search;

public class MainTest {

public static void main(String[] args) {

Map map = new Map();

AStar aStar = new AStar();

map.ShowMap();

aStar.search(map);

System.out.println("=============================");

System.out.println("經過A*算法計算后");

System.out.println("=============================");

map.ShowMap();

}

}

修改地圖再測試一下,看看效果

% % % % % % %

% o o o o o %

% o o # o o %

% A o # o B %

% o o # o o %

% o o o o o %

% % % % % % %

=============================

經過A*算法計算后

=============================

% % % % % % %

% o o o o o %

% o o # o o %

% A o # o B %

% o o # o o %

% o o o o o %

% % % % % % %

總結

保證找到最短路徑(最優解的)條件,關鍵在于估價函數h(n)的選取:估價值h(n)<=n到目標節點的距離實際值,這種情況下,搜索的點數多,搜索范圍大,效率低。但能得到

最優解。如果估價值>實際值,搜索的點數少,搜索范圍小,效率高,但不能保證得到最優解。

最大的感觸就是:做事最忌三天打漁,兩天曬網。量可以不大,但必須有連續性,貴在堅持。

希望每一個程序員,都能開心的敲著代碼,做自己喜歡做的事。

以上就是本文關于Java編程實現A*算法完整代碼的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。

總結

以上是生活随笔為你收集整理的java做a_Java编程实现A*算法完整代码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。