1. 程式人生 > >A星演算法(遊戲尋路演算法)的C++實現

A星演算法(遊戲尋路演算法)的C++實現

      先吐槽一句:CODE功能太不給力了,怎麼弄怎麼崩潰,難道是CSDN也被掃黃打非了???

---------------------------------------------

    A星演算法的實現原理看這裡:http://www.cnblogs.com/technology/archive/2011/05/26/2058842.html

    實現部分:

    標頭檔案:

/*
	A star 演算法的基礎處理
*/
#ifndef _A_STAR_BASE_H_
#define _A_STAR_BASE_H_
#include "windows.h"

typedef struct _APoint{
	int x; // x 座標
	int y; // y 座標
	int type; // 型別
	int f; // f = g + h
	int g; 
	int h;
} APoint,*PAPoint;

enum APointType{
	APT_UNKNOWN, // 未知狀態
	APT_OPENED, // 開放列表中
	APT_CLOSED, // 關閉列表中
	APT_STARTPOINT, // 起始點
	APT_ENDPOINT // 結束點
};


class CAStarBase{
public:
	CAStarBase();
	~CAStarBase();
private:
	PAPoint m_pAPointArr;
	int m_nAPointArrWidth;
	int m_nAPointArrHeight;

	PAPoint m_pStartPoint,m_pEndPoint,m_pCurPoint;
	char* m_pOldArr;
public:
	BOOL Create(char* pDateArr,int nWidth,int nHeight);
	void SetStartPoint(int x,int y);
	void SetEndPoint(int x,int y);
	void SetOpened(int x,int y);
	void SetClosed(int x,int y);
	void SetCurrent( int x,int y );
	void PrintCharArr();

	PAPoint CalcNextPoint(PAPoint ptCalc); // 應用迭代的辦法進行查詢
};

#endif

實現cpp檔案:
#include "stdafx.h"
#include "AStarBase.h"


CAStarBase::CAStarBase()
{
	m_pAPointArr = NULL;
	m_nAPointArrWidth = 0;
	m_nAPointArrHeight = 0;

	m_pStartPoint = NULL;
	m_pEndPoint = NULL;
	m_pCurPoint = NULL;

}

CAStarBase::~CAStarBase()
{

}

BOOL CAStarBase::Create( char* pDateArr,int nWidth,int nHeight )
{
	if(!pDateArr) return FALSE;
	if(nWidth<1 || nHeight<1) return FALSE;
	m_pAPointArr = new APoint[nWidth*nHeight];
	if(!m_pAPointArr) return FALSE;
	m_pOldArr = pDateArr;
	m_nAPointArrWidth = nWidth;
	m_nAPointArrHeight = nHeight;
	// 初始化陣列內容
	for ( int y = 0;y<m_nAPointArrHeight;y++)
	{
		for ( int x=0;x<m_nAPointArrWidth;x++)
		{
			m_pAPointArr[y*m_nAPointArrWidth+x].x = x;
			m_pAPointArr[y*m_nAPointArrWidth+x].y = y;
			m_pAPointArr[y*m_nAPointArrWidth+x].g = 0;
			m_pAPointArr[y*m_nAPointArrWidth+x].f = 0;
			m_pAPointArr[y*m_nAPointArrWidth+x].h = 0;

			if ( pDateArr[y*m_nAPointArrWidth+x] == '0')
			{
				m_pAPointArr[y*m_nAPointArrWidth+x].type = APT_OPENED;
			}else if ( pDateArr[y*m_nAPointArrWidth+x] == '1')
			{
				m_pAPointArr[y*m_nAPointArrWidth+x].type = APT_CLOSED;
			}else if ( pDateArr[y*m_nAPointArrWidth+x] == 'S')
			{
				m_pAPointArr[y*m_nAPointArrWidth+x].type = APT_STARTPOINT;
				m_pStartPoint = m_pAPointArr + y*m_nAPointArrWidth+x;
				m_pCurPoint = m_pStartPoint;
			}else if ( pDateArr[y*m_nAPointArrWidth+x] == 'E')
			{
				m_pAPointArr[y*m_nAPointArrWidth+x].type = APT_ENDPOINT;
				m_pEndPoint = m_pAPointArr + y*m_nAPointArrWidth+x;
			}else{
				m_pAPointArr[y*m_nAPointArrWidth+x].type = APT_UNKNOWN;
			}

		}
	}
	return TRUE;
}

void CAStarBase::SetStartPoint( int x,int y )
{
	if ( m_pStartPoint && m_pAPointArr[y*m_nAPointArrWidth+x].type!=APT_CLOSED )
	{
		m_pStartPoint->type = APT_OPENED;
		// 設定新的值
		m_pStartPoint = m_pAPointArr + y*m_nAPointArrWidth+x;
		m_pStartPoint->type = APT_STARTPOINT;
		m_pCurPoint = m_pStartPoint;
	}
}

void CAStarBase::SetEndPoint( int x,int y )
{
	if ( m_pStartPoint && m_pAPointArr[y*m_nAPointArrWidth+x].type!=APT_CLOSED )
	{
		m_pStartPoint->type = APT_OPENED;
		// 設定新的值
		m_pStartPoint = m_pAPointArr + y*m_nAPointArrWidth+x;
		m_pStartPoint->type = APT_ENDPOINT;
	}
}

void CAStarBase::SetCurrent( int x,int y )
{
//	if ( m_pAPointArr[y*m_nAPointArrWidth+x].type==APT_OPENED )
	{
		m_pCurPoint = m_pAPointArr+y*m_nAPointArrWidth+x;
	}
}

void CAStarBase::SetOpened( int x,int y )
{
	if ( m_pAPointArr[y*m_nAPointArrWidth+x].type!=APT_OPENED )
	{
		m_pAPointArr[y*m_nAPointArrWidth+x].type = APT_OPENED;
	}
}

void CAStarBase::SetClosed( int x,int y )
{
	if ( m_pAPointArr[y*m_nAPointArrWidth+x].type!=APT_CLOSED )
	{
		m_pAPointArr[y*m_nAPointArrWidth+x].type = APT_CLOSED;
	}
}

void CAStarBase::PrintCharArr()
{
	if ( m_pOldArr )
	{
		for ( int y=0; y<m_nAPointArrHeight;y++)
		{
			for ( int x=0;x<m_nAPointArrWidth;x++)
			{
				printf("%c ",m_pOldArr[x+m_nAPointArrWidth*y]);
			}
			printf("\r\n");
		}
		printf("\r\n");
	}
}

PAPoint CAStarBase::CalcNextPoint( PAPoint ptCalc )
{
	if ( ptCalc == NULL )
	{
		ptCalc = m_pStartPoint;
	}
	int x = ptCalc->x;
	int y = ptCalc->y;
	int dx = m_pEndPoint->x;
	int dy = m_pEndPoint->y;
	int xmin = x,ymin = y,vmin = 0; // 最優步驟的座標和值
	// 判斷是否已經到了最終的位置
	if ( (x==dx && abs(y-dy)==1) || (y==dy && abs(x-dx)==1) )
	{
		return m_pEndPoint;
	}
	// 上
	if ( m_pAPointArr[(x+0)+m_nAPointArrWidth*(y-1)].type == APT_OPENED && y>0)
	{
		m_pAPointArr[(x+0)+m_nAPointArrWidth*(y-1)].g = 10;
		m_pAPointArr[(x+0)+m_nAPointArrWidth*(y-1)].h = 
			10*(abs(x - dx) + abs(y-1 - dy));
		m_pAPointArr[(x+0)+m_nAPointArrWidth*(y-1)].f = 
			m_pAPointArr[(x+0)+m_nAPointArrWidth*(y-1)].g + m_pAPointArr[(x+0)+m_nAPointArrWidth*(y-1)].h;
		if ( vmin==0 )
		{
			xmin = x;
			ymin = y-1;
			vmin = m_pAPointArr[(x+0)+m_nAPointArrWidth*(y-1)].f;
		}else{
			if ( vmin > m_pAPointArr[(x+0)+m_nAPointArrWidth*(y-1)].f )
			{
				xmin = x;
				ymin = y-1;
				vmin = m_pAPointArr[(x+0)+m_nAPointArrWidth*(y-1)].f;
			}
		}
	}
	// 下
	if ( m_pAPointArr[(x+0)+m_nAPointArrWidth*(y+1)].type == APT_OPENED && y<m_nAPointArrHeight)
	{
		m_pAPointArr[(x+0)+m_nAPointArrWidth*(y+1)].g = 10;
		m_pAPointArr[(x+0)+m_nAPointArrWidth*(y+1)].h = 
			10*(abs(x - dx) + abs(y+1 - dy));
		m_pAPointArr[(x+0)+m_nAPointArrWidth*(y+1)].f = 
			m_pAPointArr[(x+0)+m_nAPointArrWidth*(y+1)].g + m_pAPointArr[(x+0)+m_nAPointArrWidth*(y+1)].h;
		if ( vmin==0 )
		{
			xmin = x;
			ymin = y+1;
			vmin = m_pAPointArr[(x+0)+m_nAPointArrWidth*(y+1)].f;
		}else{
			if ( vmin > m_pAPointArr[(x+0)+m_nAPointArrWidth*(y+1)].f )
			{
				xmin = x;
				ymin = y+1;
				vmin = m_pAPointArr[(x+0)+m_nAPointArrWidth*(y+1)].f;
			}
		}
	}
	// 左
	if ( m_pAPointArr[(x-1)+m_nAPointArrWidth*y].type == APT_OPENED && x>0)
	{
		m_pAPointArr[(x-1)+m_nAPointArrWidth*y].g = 10;
		m_pAPointArr[(x-1)+m_nAPointArrWidth*y].h = 
			10*(abs(x-1 - dx) + abs(y - dy));
		m_pAPointArr[(x-1)+m_nAPointArrWidth*y].f = 
			m_pAPointArr[(x-1)+m_nAPointArrWidth*y].g + m_pAPointArr[(x-1)+m_nAPointArrWidth*y].h;
		if ( vmin==0 )
		{
			xmin = x-1;
			ymin = y;
			vmin = m_pAPointArr[(x-1)+m_nAPointArrWidth*y].f;
		}else{
			if ( vmin > m_pAPointArr[(x-1)+m_nAPointArrWidth*y].f )
			{
				xmin = x-1;
				ymin = y;
				vmin = m_pAPointArr[(x-1)+m_nAPointArrWidth*y].f;
			}
		}
	}
	// 右
	if ( m_pAPointArr[(x+1)+m_nAPointArrWidth*y].type == APT_OPENED && x<m_nAPointArrWidth)
	{
		m_pAPointArr[(x+1)+m_nAPointArrWidth*y].g = 10;
		m_pAPointArr[(x+1)+m_nAPointArrWidth*y].h = 
			10*(abs(x+1 - dx) + abs(y - dy));
		m_pAPointArr[(x+1)+m_nAPointArrWidth*y].f = 
			m_pAPointArr[(x+1)+m_nAPointArrWidth*y].g + m_pAPointArr[(x+1)+m_nAPointArrWidth*y].h;
		if ( vmin==0 )
		{
			xmin = x+1;
			ymin = y;
			vmin = m_pAPointArr[(x+1)+m_nAPointArrWidth*y].f;
		}else{
			if ( vmin > m_pAPointArr[(x+1)+m_nAPointArrWidth*y].f )
			{
				xmin = x+1;
				ymin = y;
				vmin = m_pAPointArr[(x+1)+m_nAPointArrWidth*y].f;
			}
		}
	}

	// 如果有最優點則迭代,則否就返回NULL
	if ( vmin )
	{
		SetCurrent(xmin,ymin);
		SetClosed(xmin,ymin);
		*(m_pOldArr+xmin+m_nAPointArrWidth*ymin) = '-';
		PrintCharArr();
		PAPoint pApoint = CalcNextPoint(m_pCurPoint);
		if ( pApoint == NULL )
		{
			SetCurrent(x,y);
			SetClosed(xmin,ymin);
			*(m_pOldArr+xmin+m_nAPointArrWidth*ymin) = '0';
			return CalcNextPoint(m_pCurPoint);
		}
		return pApoint;
	}else{
		return NULL;
	}

}

測試檔案:
// AStarMath.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include "AStarBase.h"

CAStarBase Astarbase;

int _tmain(int argc, _TCHAR* argv[])
{
	char pBuff[5][7] = {
		'0','0','0','1','0','0','0',
		'0','1','1','0','0','1','1',
		'0','S','1','0','1','E','0',
		'0','1','0','0','0','1','0',
		'0','0','0','1','0','0','0'
	};
	Astarbase.Create(&pBuff[0][0],7,5);
	Astarbase.PrintCharArr();
	PAPoint pPoint = Astarbase.CalcNextPoint(NULL);
	if ( pPoint == NULL )
	{
		printf("no path can arrive!\r\n");
	}else{
		printf("success arrived!\r\n");
	}
	getchar();
	return 0;
}


結果:

相關推薦

A演算法(遊戲演算法)的C++實現

      先吐槽一句:CODE功能太不給力了,怎麼弄怎麼崩潰,難道是CSDN也被掃黃打非了??? ---------------------------------------------     A星演算法的實現原理看這裡:http://www.cnblogs.com

對於DFS,BFS,A*與IDA*等演算法的總結跟感悟

本人大一,今年2017最後一天,準備做點這學期學的演算法一點總結,當做複習吧。 一週前看見了貪吃蛇AI演算法,受到震撼於是就把以前的win32貪吃蛇加了個AI實現,讓我這個渣渣寫了好幾天才完工,終於能吃完全屏了,雖然離自己看的那個貪吃蛇AI的gif還有些距離emmmm,貪吃蛇

A演算法-自動-c++

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

淺談遊戲中的A*演算法

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

如何實現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*是一種啟發式的演算法,所謂的"啟發式",就是對每一個搜尋的位置進行評估,也就是把找的位

RPG遊戲製作-03-人物行走及A*演算法

在遊戲中,可以控制人物的方法一般有:1.鍵盤 2.虛擬搖桿 3.滑鼠 4.手機觸碰。鍵盤一般是在PC端較為常用,如果在遊戲中使用wasd等操作人物的話,那麼在移植到安卓端時,就需要使用虛擬搖桿或虛擬按鈕來模擬鍵盤,以實現處理的統一性。滑鼠類似於手機的單點觸碰,而手機觸碰一般分

A*演算法基於C#實現

 玩過即時戰略,RPG等型別的遊戲的朋友一定會知道,當我們用滑鼠選取某些單位並命令其到達地圖上確定的位置時,這些單位總是可以自動的選擇最短的路徑到達。這個時候我們就會聯想到大名鼎鼎的A*尋路演算法,下文簡略介紹演算法實現原理,並附上C#實現方法。using System; u

A*演算法C++簡單實現

2007/8/13 17:26:59 #include <iostream> #include <ctime> #include <list> #include <algorithm> #include <cassert&

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演算法

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

A演算法的Lua實現

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

A*演算法C++簡單實現

參考文章: A*尋路演算法是遊戲中常用的AI演算法,這裡用C++簡單實現了一下演算法,便於理解。 搜尋區域 如圖所示簡易地圖, 其中綠色方塊的是起點 (用 A 表示), 中間藍色的是障礙物, 紅色的方塊 (用 B 表示) 是目的地. 為了可以用一個二

A演算法最簡單理解

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

理解A*演算法過程

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

C語言-老鼠走迷宮(廣度演算法)

老鼠走迷宮-c語言(基於廣度優先的尋路演算法) 深讀優先尋路演算法原文:https://blog.csdn.net/qq_42476927/article/details/81868068  本文是基於之前的深度優先尋路演算法改進而來,參考了許多廣度遍歷的程式碼結合自己程

C語言-老鼠走迷宮(深度演算法)

老鼠走迷宮-c語言(基於深度優先的尋路演算法) 這個是學校的課設,剛開始有點頭疼,但是感覺越做越有意思了,於是就有如下程式碼,可能相較於大佬還有差距,但是這是我目前所能做的最優的程式了吧!    話不多說,說一下程式碼的核心內容吧!   &nb

C#中的演算法

目錄 介紹 問題 Dijkstra演算法 A *演算法 結果 結論 挑戰 Dijkstra和Astar的比較 Download source - 571.3 KB 在Visual Studio 2017中解壓縮並開啟解決方案 介紹 你有沒