1. 程式人生 > >A*自動尋路演算法—java版(八方向版)

A*自動尋路演算法—java版(八方向版)

上一篇部落格分享了Java版的自動尋路,但是隻是上下左右四個方向的,今天把八方向的也分享出來。

既然四方向的已經成功了,那麼改進成八方向的,只要注意兩個地方就可以了,一個是獲取四周方塊的時候,一個是移動的時候。

一、獲取四周方塊

在autofindway.java中新增靜態變數,用來標識上下左右四個方向是否可通過。

//在獲取上下左右四個方塊的時候,判斷各個方塊是否滿足條件(比如:只有右邊和下邊的方塊都可通過的時候,才能去判斷右下方的方塊是否滿足條件,否則就是穿牆了)
	private static boolean top = false;
	private static boolean down = false;
	private static boolean left = false;
	private static boolean right = false;

在獲取四周方塊的方法aroundFk中,考慮左上、右上、右下、左下四個方塊的判斷。

其中,上下左右四個方塊的判斷中,如果可以通過,則將對應的方向(top/down/left/right)標識為true。只有在左邊和上邊方塊都是true的時候,才能去判斷左上方方塊是否滿足條件,否則就存在穿牆現象。

比如下圖的四種情況,紅點想要移動到左上方的綠點,只有左邊和上邊(①)都可穿過的時候才能正常移動過去。像圖②③④這三種情況如果直接移動,都存在穿牆的現象。


程式碼如下:只要替換掉四方向版本中的aroundFk就可以了。

/**
	 * 獲取周圍方塊
	 * ①判斷是否超越邊界
	 * ②判斷是否是障礙物/已計算過的方塊
	 * @param fk	中心方塊 
	 * @return	周圍方塊結集合
	 */
	public List<FangKuaiPosition> aroundFk(FangKuaiPosition fk){
		//重置
		top = false;
		down = false;
		left = false;
		right = false;
		List<FangKuaiPosition> list = new ArrayList<FangKuaiPosition>();
		//判斷上面的方塊是否符合條件
		//判斷是否超過越邊界
		if(fk.getY() - 1 >= 0){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX(), fk.getY() - 1, fk);
			//判斷是否是障礙物/已計算過的方塊
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
				top = true;//上方方塊符合條件
			}
		}
		
		//判斷下面的方塊是否符合條件
		if(fk.getY() + 1 < BasePanel.heightLength){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX(), fk.getY() + 1, fk);
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
				down = true;//下方方塊符合條件
			}
		}
		
		//判斷左面的方塊是否符合條件
		if(fk.getX() - 1 >= 0){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() - 1, fk.getY(), fk);
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
				left = true;//左方方塊符合條件
			}
		}
		//判斷右面的方塊是否符合條件
		if(fk.getX() + 1 < BasePanel.widthLength){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() + 1, fk.getY(), fk);
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
				right = true;//右方方塊符合條件
			}
		}
		
		//左上方方塊校驗(左移一格不超過邊界&&上移一格不超過邊界&&左邊方塊符合條件&&上邊方塊符合條件,下面的類似原理)
		if(fk.getX() - 1 >= 0 && fk.getY() - 1 >= 0 && left && top){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() - 1, fk.getY() - 1, fk);
			//判斷是否是障礙物/已計算過的方塊
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
			}
		}
		
		//右上方方塊校驗
		if(fk.getX() + 1 < BasePanel.widthLength && fk.getY() - 1 >= 0 && right && top){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() + 1, fk.getY() - 1, fk);
			//判斷是否是障礙物/已計算過的方塊
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
			}
		}
		
		//右下方方塊校驗
		if(fk.getX() + 1 < BasePanel.widthLength && fk.getY() + 1 < BasePanel.heightLength && right && down){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() + 1, fk.getY() + 1, fk);
			//判斷是否是障礙物/已計算過的方塊
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
			}
		}
		
		//左下方方塊校驗
		if(fk.getX() - 1 >= 0 && fk.getY() + 1 < BasePanel.heightLength && left && down){
			FangKuaiPosition tmpFk = new FangKuaiPosition(fk.getX() + 1, fk.getY() + 1, fk);
			//判斷是否是障礙物/已計算過的方塊
			if(!BasePanel.zhangaiList.contains(tmpFk) 
					&& !BasePanel.closedList.contains(tmpFk)){
				list.add(tmpFk);
			}
		}
		//將中心方塊新增到已處理過的集合中
		BasePanel.closedList.add(fk);
		getFGH(list,fk);
		return list;
	}

二、移動

在basepanel.java中的movePanel方法裡面,四方向的版本只做了上下左右四個方向的移動判斷,所以這裡需要將左上、右上、右下、左下的移動判斷新增進來。同樣,也是替換掉四方向版本中的這個movePanel方法就可以了。

/**
	 * 方塊移動
	 * @param wayList	移動路線
	 * @throws InterruptedException
	 */
	public void movePanel(List<FangKuaiPosition> wayList) throws InterruptedException{
		
		if(wayList == null || wayList.size() == 0){
			System.out.println("無法 到達終點 !");
			return;
		}
		
		for(int i = wayList.size() - 2; i >= 0; i--){
			FangKuaiPosition fk = wayList.get(i);
			
			//向左上移動
			while(cat.getY() > fk.getY() * MyPanel.size && cat.getX() > fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX() - 2, cat.getY() - 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向右上移動
			while(cat.getY() > fk.getY() * MyPanel.size && cat.getX() < fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX() + 2, cat.getY() - 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向右下移動
			while(cat.getY() < fk.getY() * MyPanel.size && cat.getX() < fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX() + 2, cat.getY() + 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向左下移動
			while(cat.getY() < fk.getY() * MyPanel.size && cat.getX() > fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX() - 2, cat.getY() + 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向上
			while(cat.getY() > fk.getY() * MyPanel.size && cat.getX() == fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX(), cat.getY() - 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向下
			while(cat.getY() < fk.getY() * MyPanel.size && cat.getX() == fk.getX() * MyPanel.size){
				cat.setBounds(cat.getX(), cat.getY() + 2, MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向左
			while(cat.getX() > fk.getX() * MyPanel.size && cat.getY() == fk.getY() * MyPanel.size){
				cat.setBounds(cat.getX() - 2, cat.getY(), MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
			//向右
			while(cat.getX() < fk.getX() * MyPanel.size && cat.getY() == fk.getY() * MyPanel.size){
				cat.setBounds(cat.getX() + 2, cat.getY(), MyPanel.size, MyPanel.size);
				Thread.sleep(sleepTime);
			}
			
		}
		System.out.println("尋路結束!");
	}

好了,給大家展示一下結果:


相關推薦

A*自動演算法java方向

上一篇部落格分享了Java版的自動尋路,但是隻是上下左右四個方向的,今天把八方向的也分享出來。既然四方向的已經成功了,那麼改進成八方向的,只要注意兩個地方就可以了,一個是獲取四周方塊的時候,一個是移動的時候。一、獲取四周方塊在autofindway.java中新增靜態變數,用

人工智慧: 自動演算法實現(三、A*演算法)

本篇文章是機器人自動尋路演算法實現的第三章。我們要討論的是一個在一個M×N的格子的房間中,有若干格子裡有灰塵,有若干格子裡有障礙物,而我們的掃地機器人則是要在不經過障礙物格子的前提下清理掉房間內的灰塵。具體的問題情景請檢視人工智慧: 自動尋路演算法實現(一、廣度優先搜尋)

如何實現A演算法 Cocos2d-x 3 0 beta2

bool pathFound = false;_spOpenSteps.clear();_spClosedSteps.clear();// 首先,新增貓的方塊座標到open列表this->insertInOpenSteps(ShortestPathStep::createWithPosition(fro

人工智慧: 自動演算法實現(一、廣度優先搜尋)

前言 隨著人工智慧技術的日益發達,我們的生活中也出現了越來越多的智慧產品。我們今天要關注的是智慧家居中的一員:掃地機器人。智慧掃地機器人可以在主人不在家的情況下自動檢測到地面上的灰塵,並且進行清掃。有些更為對路線進行規劃,找到可以清理灰塵的最短路徑,達到省電的

c++實現的A* 靜態演算法 程式碼

在此僅提供程式碼,不對原理進行解釋。 如果想知道原理請自行百度,已經有很多前輩寫過了。 這裡用到了簡單的圖形庫 easyX #include<iostream> #include<math.h> #include<graphics.h> using n

A* (A-star A星)演算法

A*在遊戲尋路演算法裡使用很廣,可是感覺很多介紹它的文章故意讓人看不懂。 仔細看了看gamedev.net的一片文章(A* Pathfinding for Beginners ),對A*更瞭解了一點,寫點東西記錄一下。 A*是一種啟發式的演算法,所謂的"啟發式",就是對每一個搜尋的位置進行評估,也就是把找的位

A演算法流程詳解

using System.Collections; using System.Collections.Generic; using UnityEngine; public class AStar : MonoBehaviour { private const int mapWith = 15;

天神降臨,大家過來膜拜吧! FLASH AS 3.0 A星(A*, A star) 演算法--史上最快,極限優化挑戰!

天神降臨,大家過來膜拜吧!  oh yeah! 轉載請宣告出處,例子程式碼可以免費隨意使用,但請保留或註明作者資訊.  這裡的演算法說是終極優化, 我挑戰了一下, 最終結果比較他快三倍, 我站在高高處,藐視了 一下作者. 優化思路:       

A*智慧演算法(php版本)

          A*被譽為大眾級尋路演算法,常用於獲取兩個座標的最短路徑,屬於AI(人工智慧)範疇,最近自己開發了一套php版本的A*尋路演算法類,想要直接使用的朋友可以借鑑下。可以在我的空間裡面看具體的呼叫部分,類庫我會盡快上傳。           先說下A*的演算

記錄一個下午擼的A演算法

大致思路主要圍繞open表和close表 可能的路徑點先放到open列表裡面(如果該點已經存在於close則跳過,如果改點已經存在與open中,則判斷和值是否更小,如果是則更新) open列表裡面和值最小的轉移到close裡面去,直到最終到達終點,再遍歷前寄得到

A演算法的Lua實現

A*搜尋演算法俗稱A星演算法。這是一種在圖形平面上,有多個節點的路徑,求出最低通過成本的演算法。 對A星演算法的理解還是要從公式 F = G + H開始:在節點化的地圖上,每一步的操作,使得已走距離 + 距離終點距離最小。具體的實現上是維護一個open表和

A演算法最簡單理解

對於a星尋路演算法最直白的理解: 從a點走到b點,首先把地圖畫成網格,讓障礙物在網格內       如圖,從s點要走到e點,把障礙物設成黑色,還要建立2個佇列,一個是尋找新的節點佇列(開啟佇列),一個是儲存已走過的節點佇列(關閉佇列)。在尋找新的節點時,要判斷該節點距

A演算法-自動-c++

一共分三個檔案,一個頭檔案兩個CPP檔案   A星原理可以去網上搜。   那我就直接上程式碼啦!   A星的標頭檔案   [cpp] view plaincopy /******************************************************

Unity A*演算法人物移動AI

最近閒來無事,從網上看了一些大神的心得,再融合自己的體會,寫了一個簡單點的尋路演算法,廢話不多說,直接上程式碼 <Grid> usingUnityEngine; usingSystem.Collections; usingS

淺談遊戲自動A*演算法

 尋路是遊戲中非常重要的一個元素,如何找到一條最短的路徑是程式需要設計的演算法,現在最為流行的尋路演算法是A*演算法。A*演算法與狀態空間搜尋結合的相當緊密。     狀態空間搜尋,就是將問題求解的過程表現為從初始狀態到目標狀態尋找這個路徑的過程,通俗的說就是在解一個問題的

A*算法之在U3d下實現簡單的自動

engine ati mat param erp ane 自動尋路 lose var 前言: 算法簡介:   A*搜尋算法俗稱A星算法。A*算法是比較流行的啟發式搜索算法之一,被廣泛應用於路徑優化領域[。它的獨特之處是檢查最短路徑中每個可能的節點時引入了全局信息,對當前節點

理解A*演算法過程

   這兩天研究了下 A* 尋路演算法, 主要學習了這篇文章, 但這篇翻譯得不是很好, 我花了很久才看明白文章中的各種指代. 特寫此篇部落格用來總結, 並寫了尋路演算法的程式碼, 覺得有用的同學可以看看. 另外因為圖片製作起來比較麻煩, 所以我用的是原文裡的圖片. &n

淺談遊戲中的A*演算法

本文為銳亞教育原創文章,轉載請註明轉載自銳亞教育 A*尋路 A*演算法基本原理 A*(唸作A星)演算法對初學者來說的確有些難度。本文並不試圖對這個話題作權威性的陳述,取而代之的是描述演算法的原理,使你可以在進一步的閱讀中理解其他相關的資

A*演算法補充知識

A*演算法 輔助知識 unity視覺化輔助工具Gizmos Gizmos.color =Color.red;//設定畫筆的顏色 Gizmos.DrawWireCube(位置,Vector3(長寬高));//畫出一個範圍框: Gizmos.DrawCube(位置,三維屬性長寬高); /

A*演算法之解決目標點不可達問題

在遊戲世界的尋路中,通常會有這樣一種情況:在小地圖上點選目標點時,點選到了障礙物或者建築上,然後遊戲會提示我們目標地點無法到達。玩家必須非常小心的在小地圖上點選目標區域的空白部分,才能移動到目標地點。那麼,有沒有辦法來改進一下這種不友好的體驗呢? 下面給出兩種方法: 最近