A*算法的初探

5 篇文章 0 订阅
1 篇文章 0 订阅

马上找工作了,因为自己算是从事三维建模方面的,虽说不抱太大希望能找到相关领域的工作,但为了防止找工作时候丢了导师和学校的脸面,还是最近把和图论相关的东西看了一下。

自己算是半路出家,没沐浴过什么高大上的经典算法,自己也秉承着先看懂,然后自己按照意思把算法写出来的一贯原则,去学习了A*算法,一天时间,也算把这两个算法的初步意思理解了,本着留给媳妇看的想法把演示demo写完之后,发现基本没写注释。。。,好吧,正好在此记录下来,留着以后学习用。


这里是mfc上写的一个最短路径算法的演示demo,额,好久没碰mfc了,不过表示这玩意还算方便,查下百度就知道用哪些函数了,倒是容易上手。

下载地址 http://download.csdn.net/detail/vcchendefu/7770049

A*算法有一种模拟人脑思维过程的感觉,有时候又感觉有点Dijkstra算法的影子,就是在已知到起始点的实际距离的情况下,根据到最终点的趋近性(这点又有些像贪心算法),在搜素过程中对这些存在的可能路径上的点进行比对,进而找出到终点的最短路径(有比较中胜出的一组连续点组成)。

好吧,感觉没表达好。。。就是给格子上一系列权值F、G、H:

1、G是该点到起始点的实际距离,就是算法是怎么从起始点遍历到该点的轨迹距离;

2、H是该点到目标点的直线距离,(A*算法的自由度很高,其实是不是直线距离有你来定,你要是想规定他做战斗机的战术规避动作,随你)

3、F是有G和H组成的,好,这里我认为是组成,不是相加,当然一般情况下是相加,因为A*算法是一个寻路算法,不是死板的最短路径算法,有时候快最重要,有时候牺牲一下精确度,保证算法的性能很重要。

这里再把搜索路径中点归一下类(这里解释可能不太清楚,没事后面会提到,可以看后面时候结合看看)

0、未搜索到的点

1、起始点(搜索的起点,属于4)

2、终点

3、障碍点

4、已经遍历过得点

5、边界点(一定属于4)

6、活跃点(曾经属于5)(动态的,从上一轮活跃点的周围临界点(这些点必须属于0)找到权值最小的点作为新的活跃点,如果找到的新的活跃点的权值还大于之前的某个边界点,那么就把这个边界点作为活跃点)(这个事整个算法很重要的一部分,我认为这里阐述的比较清楚)(注意活跃点在每一轮搜索过程中都是动态的,是推进搜索进程的关键!!!)

7、路径点(曾经属于6)(最后由2回溯可得到路径)

好,回到主线上来,那怎样得到和运用这些节点上的权值呢,“找路”整个过程是这样的,我尝试用我贫瘠的语言表达能力,来叙述一下:

从起始点开始,把它作为这一轮搜索的活跃点,查找,周围八个点(这个是可以自己定义的,也可以只是上下左右四个,这根实际需要和G值,F值的取法有关)中状态属于未遍历的点,把他们看做新的边界点(类型5),把这些点的父亲节点记为生成他的活跃点(他们是有这个点搜索生成而来的),然后遍历这些边界点,找到F值最小的点看做新的活跃点(类型6)(这里有个为题就是G值的获取,G值其实是个层层累加的过程,就是获取当前点到父亲的距离,当然这个距离计算方法可以使欧式距离,曼哈顿距离,等等。。。,累加父亲节点的G值而成的,这点很像Dijkstra算法,这是一个累积生成的过程,具体怎么实现看代码吧);好,从起始点开始到现在,产生了新的一批活跃点(类型6),并记录下了生成中形成的边界点,下面所做的就是重复上面的过程,去找到新的活跃点周围的未遍历的点,进而生成新的活跃点。好!!!!,问题来了!!就这样继续下去么,如果遇到一个迷宫一样的地图绕进去了怎么办,这时候可能出现一个问题,就是当活跃点在迷宫的小巷子里面蜿蜒深入的的时候,这些点的H值可能正在变小,但是G值可能变得非常大(因为可能绕了很多路么!!!),这时候新生活跃点的F值可能会出现超越之前边界点的情况(类型5),为了避免这种情况的发生,就需要在上述过程中加上这样一个环节——————把新生成的活跃点与之前生成的边界点比较,如果发现还没有之前的边界点小,那么就把这些边界点从边界点集合中剔除,把它作为新的边活跃点,继续之后的搜索过程,循环往复,知道找到终点为止!!!


好的,大概就是整个过程了,这里说一些自己的对A*算法想法,首先我认为A*算法是一个自由度非常高的算法,可能看上面也能看出来,有好些部分都是编程者自己控制的,这点比较像希尔排序,和联合排序——选择一个适合情况的参数方法才能实现算法本身的高效性,A*算法从G、H、F值的获取,周围点选取,路径规则(甚至我认为,连替代活跃点判定————当然这可能会牺牲路径的准确性,但会在一定程度上快速得到一个较为满意的结果)都是可以自己定义的。

写到这里,我有种感觉:A*算法算是一个人工智能的最简单例子吧,多想一个正在权衡思考的脑袋啊。。。

附上代码:

// A_PathDlg.h : 头文件
//

#pragma once

#include <vector>
#include <math.h>
using namespace std;

#define CUBE_NUMBER 25//格子数量

#define WIDTH 600//对话框尺寸
#define HEIGHT 500

#define FIND_PATH 0

#define DONE 1//格子三种状态 1,已经遍历过得,2,障碍物,3,空白
#define BARRIER 2
#define CLEAR 3


#define BOUNDARY_COLOR 0//演示给格子上颜色
#define ATCIVE_COLOR 1
#define  DONE_COLOR 2
#define PATH_COLOR 3
#define WHITE_COLOR 4
#define START_COLOR 5
#define TARGET_COLER 6
#define BARRIER_COLOR 7

//这里信息是一个25*25的格子,那么存储整张格子信息用的就是一个25*25的二维数组
//由于索引都是整形的,所以这时候我把一个格子的索引信息用CPoint类型来存储
//例如m_stData[m_cStartPoint.y][m_cStartPoint.x](m_cStartPoint 是CPoint类型的)

struct MyStruct//存储格子信息的结构体
{
	float m_fValue;//当前格子在搜寻路径图中,相对于起始点和目标点的综合权值
	float m_fValueG;//存储到起始点的权值
	int m_nStatus;//当前格子状态,可以为done(已经遍历) barrier(障碍物) clear(未遍历几种)
	CPoint m_nFather;//副节点索引
	MyStruct()
	{
		m_fValue = 0;

		m_nStatus = CLEAR;
		m_nFather.x = -1;
		m_nFather.y = -1;
	
	}
};


// CA_PathDlg 对话框
class CA_PathDlg : public CDialogEx
{
// 构造
public:
	CA_PathDlg(CWnd* pParent = NULL);	// 标准构造函数

// 对话框数据
	enum { IDD = IDD_A_PATH_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedOk();//开始查找按钮
	afx_msg void OnBnClickedCancel();//退出按钮
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);//点击对话框事件

private:
	
	vector<CPoint> GetAroundIndex(CPoint pt);//获取周围所有可以未遍历点的索引信息

	float GetValueF(CPoint pt);//获取当前格子的总权值
	float GetValueG(CPoint pt);//获取当前格子到起始点的权值
	float GetValueH(CPoint pt);//获取当前格子到终点的权值

	float GetValue(CPoint pt);//求总权
	float GetValue2(CPoint pt);//求已知路径权

	CPoint GetFather(CPoint pt);//获取当前格子的父亲节点索引
	MyStruct GetData(CPoint pt);//获取当前格子的整个结构体信息
	int GetDataStatus(CPoint pt);//获取当前格子的状态值信息
	bool Erase(vector<CPoint> &vPoint,CPoint pt);//擦除容器中的一个值
	float GetFatherDistance(CPoint pt);//获取当前格子相对于父亲节点的距离

	//打印
	void Print(CPoint pt,int nColorIndex);//绘制格子颜色


private:
	MyStruct m_stData[CUBE_NUMBER][CUBE_NUMBER];//存储地图信息
	vector<CPoint> m_vBoundary;//存储边界信息
	vector<CPoint> m_vActive;//存储活跃边界/


	int m_nCubeClass;//设置地图信息时候的操作类型

	CPoint m_cStartPoint;//起始点索引
	CPoint m_cTargetPoint;//目标点索引

	

public:
	afx_msg void OnBnClickedRadio1();
	afx_msg void OnBnClickedRadio2();
	afx_msg void OnBnClickedRadio3();
	afx_msg void OnTimer(UINT_PTR nIDEvent);
};<pre name="code" class="cpp">// A_PathDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "A_Path.h"
#include "A_PathDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif



// CA_PathDlg 对话框



CA_PathDlg::CA_PathDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CA_PathDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CA_PathDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CA_PathDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDOK, &CA_PathDlg::OnBnClickedOk)
	ON_BN_CLICKED(IDCANCEL, &CA_PathDlg::OnBnClickedCancel)
	ON_WM_LBUTTONDOWN()
	ON_BN_CLICKED(IDC_RADIO1, &CA_PathDlg::OnBnClickedRadio1)
	ON_BN_CLICKED(IDC_RADIO2, &CA_PathDlg::OnBnClickedRadio2)
	ON_BN_CLICKED(IDC_RADIO3, &CA_PathDlg::OnBnClickedRadio3)
	ON_WM_TIMER()
END_MESSAGE_MAP()


// CA_PathDlg 消息处理程序

BOOL CA_PathDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码

	CRect   rcTemp;
	rcTemp.BottomRight()   =   CPoint(600,   500);
	rcTemp.TopLeft()   =   CPoint(0,   0);
	MoveWindow(&rcTemp);



	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CA_PathDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);

	

	}
	else
	{



		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CA_PathDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}






void CA_PathDlg::OnBnClickedCancel()
{
	// TODO: 在此添加控件通知处理程序代码
	CDialogEx::OnCancel();
}


void CA_PathDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	
	int nX = point.x;
	int nY = point.y;

	CPoint pt(nX/20,nY/20);

	if(pt.x >= 0 && pt.x < 25 && pt.y >= 0 && pt.y < 25)
	{
		switch (m_nCubeClass)
		{
		case 0://起点
			{
				Print(m_cStartPoint,WHITE_COLOR);
				Print(pt,START_COLOR);
				m_cStartPoint = pt;
			}
			break;
		case 1://终点
			{
				Print(m_cTargetPoint,WHITE_COLOR);
				Print(pt,TARGET_COLER);
				m_cTargetPoint = pt;
			}
			break;
		case 2://障碍物
			{
				if(m_stData[pt.y][pt.x].m_nStatus != BARRIER)
				{
					Print(pt,BARRIER_COLOR);
					m_stData[pt.y][pt.x].m_nStatus = BARRIER;
				}
				else
				{
					Print(pt,WHITE_COLOR);
					m_stData[pt.y][pt.x].m_nStatus = CLEAR;
				}
	
			}
			break;
		default:
			break;
		}
	}

	CDialogEx::OnLButtonDown(nFlags, point);
}




void CA_PathDlg::OnBnClickedRadio1()
{
	// TODO: 在此添加控件通知处理程序代码
	m_nCubeClass = 0;
}


void CA_PathDlg::OnBnClickedRadio2()
{
	// TODO: 在此添加控件通知处理程序代码
	m_nCubeClass = 1;
}


void CA_PathDlg::OnBnClickedRadio3()
{
	// TODO: 在此添加控件通知处理程序代码
	m_nCubeClass = 2;
}

void CA_PathDlg::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码

	//启动演示计时器//对算法进行初始化//计时器相当于算法循环中的一个步骤

	for(int i = 0;i < CUBE_NUMBER;i++)
	{
		for(int j = 0;j < CUBE_NUMBER;j++)
		{
			CPoint cTemp(i,j);
			if(GetDataStatus(cTemp) != BARRIER)
			{
				Print(cTemp,WHITE_COLOR); 
			}
		}
	}


	m_vActive.push_back(m_cStartPoint);
	m_stData[m_cStartPoint.y][m_cStartPoint.x].m_nStatus = DONE;
	m_stData[m_cStartPoint.y][m_cStartPoint.x].m_fValue = GetValueF(m_cStartPoint);
	m_stData[m_cStartPoint.y][m_cStartPoint.x].m_fValueG = 0;
	SetTimer(FIND_PATH,100,NULL);

}

void CA_PathDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	for(int i = 0;i < m_vBoundary.size();i++)
	{
		Print(m_vBoundary[i],BOUNDARY_COLOR);
	}
	for(int i = 0;i < m_vActive.size();i++)
	{
		Print(m_vActive[i],ATCIVE_COLOR);
	}


	if(nIDEvent == FIND_PATH)
	{

		
		float fMin = -1;
		vector<CPoint> cMin;
		for(int i = 0;i < m_vActive.size();i++)
		{
			vector<CPoint> cTemp =  GetAroundIndex(m_vActive[i]);
			for(int j = 0;j < cTemp.size();j++)
			{
				if(cTemp[j] == m_cTargetPoint)
				{
					//打印
					CPoint pTemp =  m_vActive[i];;
					
					while(pTemp != m_cStartPoint)
					{
						Print(pTemp,PATH_COLOR);
						pTemp = GetFather(pTemp);
					}
					Print(m_cTargetPoint,TARGET_COLER);
					Print(m_cStartPoint,START_COLOR);
					KillTimer(FIND_PATH);

					//清零
				

					return;
				}
		
				
				m_stData[cTemp[j].y][cTemp[j].x].m_nFather = m_vActive[i];
				float fTest = GetValueF(cTemp[j]);
				m_stData[cTemp[j].y][cTemp[j].x].m_fValue = GetValueF(cTemp[j]);
				m_stData[cTemp[j].y][cTemp[j].x].m_fValueG = GetValueG(cTemp[j]);

				m_stData[cTemp[j].y][cTemp[j].x].m_nStatus = DONE;
				Print(cTemp[j],DONE_COLOR);
				m_vBoundary.push_back(cTemp[j]);

				if(fMin == -1)//第一次进入
				{
					fMin = m_stData[cTemp[j].y][cTemp[j].x].m_fValue;
					cMin.push_back(cTemp[j]);
				}
				else if(m_stData[cTemp[j].y][cTemp[j].x].m_fValue < fMin)
				{
					fMin = m_stData[cTemp[j].y][cTemp[j].x].m_fValue;
					cMin.clear();
					cMin.push_back(cTemp[j]);
				}
				else if(m_stData[cTemp[j].y][cTemp[j].x].m_fValue == fMin)
				{
					cMin.push_back(cTemp[j]);
				}
			}
		}

		bool bChange = false; 
		if(cMin.size() != 0)
		{
			for(int i = 0;i < m_vBoundary.size();i++)
			{
				if(GetValue(m_vBoundary[i]) < GetValue(cMin[0]))
				{
					bChange = true;
					break;
				}
			}
		}
	

		if(cMin.size() == 0 || bChange == true)
		{
			fMin = GetValueF(m_vBoundary[0]);
			cMin.push_back(m_vBoundary[0]);
			for(int i = 1;i < m_vBoundary.size();i++)
			{
				float fTemp = GetValueF(m_vBoundary[i]);
				if(fTemp < fMin)
				{
					fMin = fTemp;
					cMin.clear();
					cMin.push_back(m_vBoundary[i]);
				}
				else if(fTemp == fMin)
				{
					cMin.push_back(m_vBoundary[i]);
				}
			}
			m_vActive = cMin;
		}
		else 
		{
			m_vActive = cMin;
		}
		for(int i = m_vBoundary.size() - 1;i >= 0;i--)
		{
			for(int j = 0;j < m_vActive.size();j++)
			{
				if(m_vBoundary[i] == m_vActive[j])
				{
					m_vBoundary.erase(m_vBoundary.begin() + i);
					break;
				}
			}
		}

	
		

		
	
	}

	CDialogEx::OnTimer(nIDEvent);
}

vector<CPoint> CA_PathDlg::GetAroundIndex( CPoint pt )
{
	vector<CPoint> vResult;

	bool bRet1 = (pt.x + 1 < CUBE_NUMBER);
	bool bRet2 = (pt.x - 1 >= 0);
	bool bRet3 = (pt.y + 1 < CUBE_NUMBER);
	bool bRet4 = (pt.y - 1 >= 0);

	if(bRet1 == true)
	{
		CPoint cTemp(pt.x + 1,pt.y);
		if(GetDataStatus(cTemp) == CLEAR)
		{
			vResult.push_back(cTemp);
		}
	}

	if(bRet1 == true && bRet3 == true)
	{
		CPoint cTemp(pt.x + 1,pt.y + 1);
		if(GetDataStatus(cTemp) == CLEAR)
		{
			vResult.push_back(cTemp);
		}
	}

	if(bRet3 == true)
	{
		CPoint cTemp(pt.x,pt.y + 1);
		if(GetDataStatus(cTemp) == CLEAR)
		{
			vResult.push_back(cTemp);
		}
	}

	if(bRet3 == true && bRet2 == true)
	{
		CPoint cTemp(pt.x - 1,pt.y + 1);
		if(GetDataStatus(cTemp) == CLEAR)
		{
			vResult.push_back(cTemp);
		}
	}
	
	if(bRet2 == true)
	{
		CPoint cTemp(pt.x - 1,pt.y);
		if(GetDataStatus(cTemp) == CLEAR)
		{
			vResult.push_back(cTemp);
		}
	}

	if(bRet2 == true && bRet4 == true)
	{
		CPoint cTemp(pt.x - 1,pt.y - 1);
		if(GetDataStatus(cTemp) == CLEAR)
		{
			vResult.push_back(cTemp);
		}
	}

	if(bRet4 == true)
	{
		CPoint cTemp(pt.x,pt.y - 1);
		if(GetDataStatus(cTemp) == CLEAR)
		{
			vResult.push_back(cTemp);
		}
	}

	if(bRet1 == true && bRet4 == true)
	{
		CPoint cTemp(pt.x + 1,pt.y - 1);
		if(GetDataStatus(cTemp) == CLEAR)
		{
			vResult.push_back(cTemp);
		}
	}

	return vResult;

}

float CA_PathDlg::GetValueF(CPoint pt)
{
	float fTest1 = GetValueG(pt);
	float fTest2 = GetValueH(pt);
	return GetValueG(pt) + GetValueH(pt);
}

float CA_PathDlg::GetValueG(CPoint pt)
{
	//CPoint cFather = GetFather(pt);
	//return GetFatherDistance(pt) + GetValue(cFather);

	//return abs(pt.x - m_cStartPoint.x) + abs(pt.y - m_cStartPoint.y);

	if(pt == m_cStartPoint)
	{
		return 0;
	}
	CPoint cFather = GetFather(pt);
	return GetFatherDistance(pt) + GetValue2(cFather);
}

float CA_PathDlg::GetValueH(CPoint pt)
{

	return abs(pt.x - m_cTargetPoint.x) + abs(pt.y - m_cTargetPoint.y);
}

MyStruct CA_PathDlg::GetData( CPoint pt )
{
	return m_stData[pt.y][pt.x];
}

int CA_PathDlg::GetDataStatus( CPoint pt )
{
	return m_stData[pt.y][pt.x].m_nStatus;
}

bool CA_PathDlg::Erase(vector<CPoint> &vPoint,CPoint pt )
{
	bool bEnter = false;
	for(int i = vPoint.size() - 1;i >= 0;i--)
	{
		if(vPoint[i] == pt)
		{
			vPoint.erase(vPoint.begin() + i);
			bEnter = true;
		}
	}
	return bEnter;
}

void CA_PathDlg::Print( CPoint pt,int nColorIndex )
{
	switch (nColorIndex)
	{
	case BOUNDARY_COLOR:
		{
			CBrush br(RGB(0,0,128));
			CClientDC dc(this);
			CBrush *pOldBr = dc.SelectObject(&br);
			CPoint pt1(pt.x * 20,pt.y * 20);
			CPoint pt2(pt.x * 20 + 20,pt.y * 20 + 20);
			dc.Rectangle(CRect(pt1,pt2));
			dc.SelectObject(pOldBr);
		}
		break;
	case ATCIVE_COLOR:
		{
			CBrush br(RGB(153,204,0));
			CClientDC dc(this);
			CBrush *pOldBr = dc.SelectObject(&br);
			CPoint pt1(pt.x * 20,pt.y * 20);
			CPoint pt2(pt.x * 20 + 20,pt.y * 20 + 20);
			dc.Rectangle(CRect(pt1,pt2));
			dc.SelectObject(pOldBr);
		}
		break;
	case DONE_COLOR:
		{
			CBrush br(RGB(204,255,204));
			CClientDC dc(this);
			CBrush *pOldBr = dc.SelectObject(&br);
			CPoint pt1(pt.x * 20,pt.y * 20);
			CPoint pt2(pt.x * 20 + 20,pt.y * 20 + 20);
			dc.Rectangle(CRect(pt1,pt2));
			dc.SelectObject(pOldBr);
		}
		break;
	case PATH_COLOR:
		{
			CBrush br(RGB(255,0,255));
			CClientDC dc(this);
			CBrush *pOldBr = dc.SelectObject(&br);
			CPoint pt1(pt.x * 20,pt.y * 20);
			CPoint pt2(pt.x * 20 + 20,pt.y * 20 + 20);
			dc.Rectangle(CRect(pt1,pt2));
			dc.SelectObject(pOldBr);
		}
		break;

	case WHITE_COLOR:
		{
			CBrush br(RGB(255,255,255));
			CClientDC dc(this);
			CBrush *pOldBr = dc.SelectObject(&br);
			CPoint pt1(pt.x * 20,pt.y * 20);
			CPoint pt2(pt.x * 20 + 20,pt.y * 20 + 20);
			dc.Rectangle(CRect(pt1,pt2));
			dc.SelectObject(pOldBr);
		}
		break;
	case START_COLOR:
		{
			CBrush br(RGB(255,0,0));
			CClientDC dc(this);
			CBrush *pOldBr = dc.SelectObject(&br);
			CPoint pt1(pt.x * 20,pt.y * 20);
			CPoint pt2(pt.x * 20 + 20,pt.y * 20 + 20);
			dc.Rectangle(CRect(pt1,pt2));
			dc.SelectObject(pOldBr);
		}
		break;
	case TARGET_COLER:
		{
			CBrush br(RGB(0,255,0));
			CClientDC dc(this);
			CBrush *pOldBr = dc.SelectObject(&br);
			CPoint pt1(pt.x * 20,pt.y * 20);
			CPoint pt2(pt.x * 20 + 20,pt.y * 20 + 20);
			dc.Rectangle(CRect(pt1,pt2));
			dc.SelectObject(pOldBr);
		}
		break;

	case BARRIER_COLOR:
		{
			CBrush br(RGB(0,0,0));
			CClientDC dc(this);
			CBrush *pOldBr = dc.SelectObject(&br);
			CPoint pt1(pt.x * 20,pt.y * 20);
			CPoint pt2(pt.x * 20 + 20,pt.y * 20 + 20);
			dc.Rectangle(CRect(pt1,pt2));
			dc.SelectObject(pOldBr);
		}
		break;
	default:
		break;
	}
}

CPoint CA_PathDlg::GetFather( CPoint pt )
{
	return m_stData[pt.y][pt.x].m_nFather;
}

float CA_PathDlg::GetValue( CPoint pt )
{

	return m_stData[pt.y][pt.x].m_fValue;
}

float CA_PathDlg::GetFatherDistance( CPoint pt )
{
	CPoint cFather = GetFather(pt);
	if(pt.x != cFather.x && pt.y != cFather.y)
	{
		return 1.4;
	}
	else
	{
		return 1;
	}
}

float CA_PathDlg::GetValue2( CPoint pt )
{
	return m_stData[pt.y][pt.x].m_fValueG;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值