您的位置:首页 > 编程语言 > C语言/C++

A星算法(游戏寻路算法)的C++实现

2014-04-26 11:46 609 查看
先吐槽一句: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;
}


结果:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: