A*寻路算法基于C#实现

    玩过即时战略,RPG等类型的游戏的朋友一定会知道,当我们用鼠标选取某些单位并命令其到达地图上确定的位置时,这些单位总是可以自动的选择最短的路径到达。这个时候我们就会联想到大名鼎鼎的A*寻路算法,下文简略介绍算法实现原理,并附上C#实现方法。

    算法原理请见:http://data.gameres.com/message.asp?TopicID=25439

 

ContractedBlock.gif ExpandedBlockStart.gif 代码

   
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace ConsoleApplication2
{
class Program
{





static void Main( string [] args)
{



test mytest
= new test();

// 定义出发位置
Point pa = new Point();
pa.x
= 1 ;
pa.y
= 1 ;

// 定义目的地
Point pb = new Point();
pb.x
= 8 ;
pb.y
= 8 ;

mytest.FindWay(pa, pb);

mytest.PrintMap();
Console.ReadLine();
}
}
class test
{

// 数组用1表示可通过,0表示障碍物
byte [,] R = new byte [ 10 , 10 ] {
{
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 },
{
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 },
{
1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 },
{
1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 },
{
1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 },
{
1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 },
{
1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 },
{
1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 },
{
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 },
{
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 }

};



// 开启列表
List < Point > Open_List = new List < Point > ();

// 关闭列表
List < Point > Close_List = new List < Point > ();

// 从开启列表查找F值最小的节点
private Point GetMinFFromOpenList()
{
Point Pmin
= null ;
foreach (Point p in Open_List) if (Pmin == null || Pmin.G + Pmin.H > p.G + p.H) Pmin = p;
return Pmin;
}

// 判断一个点是否为障碍物
private bool IsBar(Point p, byte [,] map)
{
if (map[p.y, p.x] == 0 ) return true ;
return false ;
}

// 判断关闭列表是否包含一个坐标的点
private bool IsInCloseList( int x, int y)
{
foreach (Point p in Close_List) if (p.x == x && p.y == y) return true ;
return false ;
}
// 从关闭列表返回对应坐标的点
private Point GetPointFromCloseList( int x, int y)
{
foreach (Point p in Close_List) if (p.x == x && p.y == y) return p;
return null ;
}

// 判断开启列表是否包含一个坐标的点
private bool IsInOpenList( int x, int y)
{
foreach (Point p in Open_List) if (p.x == x && p.y == y) return true ;
return false ;
}
// 从开启列表返回对应坐标的点
private Point GetPointFromOpenList( int x, int y)
{
foreach (Point p in Open_List) if (p.x == x && p.y == y) return p;
return null ;
}


// 计算某个点的G值
private int GetG(Point p)
{
if (p.father == null ) return 0 ;
if (p.x == p.father.x || p.y == p.father.y) return p.father.G + 10 ;
else return p.father.G + 14 ;
}

// 计算某个点的H值
private int GetH(Point p, Point pb)
{
return Math.Abs(p.x - pb.x) + Math.Abs(p.y - pb.y);
}

// 检查当前节点附近的节点
private void CheckP8(Point p0, byte [,] map, Point pa, ref Point pb)
{
for ( int xt = p0.x - 1 ; xt <= p0.x + 1 ; xt ++ )
{
for ( int yt = p0.y - 1 ; yt <= p0.y + 1 ; yt ++ )
{
// 排除超过边界和等于自身的点
if ((xt >= 0 && xt < 10 && yt >= 0 && yt < 10 ) && ! (xt == p0.x && yt == p0.y))
{
// 排除障碍点和关闭列表中的点
if (map[yt, xt] != 0 && ! IsInCloseList(xt, yt))
{
if (IsInOpenList(xt, yt))
{
Point pt
= GetPointFromOpenList(xt, yt);
int G_new = 0 ;
if (p0.x == pt.x || p0.y == pt.y) G_new = p0.G + 10 ;
else G_new = p0.G + 14 ;
if (G_new < pt.G)
{
Open_List.Remove(pt);
pt.father
= p0;
pt.G
= G_new;
Open_List.Add(pt);
}
}
else
{
// 不在开启列表中
Point pt = new Point();
pt.x
= xt;
pt.y
= yt;
pt.father
= p0;
pt.G
= GetG(pt);
pt.H
= GetH(pt, pb);
Open_List.Add(pt);
}
}
}
}
}
}



public void FindWay(Point pa, Point pb)
{

Open_List.Add(pa);
while ( ! (IsInOpenList(pb.x, pb.y) || Open_List.Count == 0 ))
{
Point p0
= GetMinFFromOpenList();
if (p0 == null ) return ;
Open_List.Remove(p0);
Close_List.Add(p0);
CheckP8(p0, R, pa,
ref pb);
}


Point p
= GetPointFromOpenList(pb.x, pb.y);
while (p.father != null )
{
p
= p.father;
R[p.y, p.x]
= 3 ;
}

}

public void SaveWay( Point pb)
{

Point p
= pb;
while (p.father != null )
{
p
= p.father;
R[p.y, p.x]
= 3 ;
}
}

public void PrintMap()
{




for ( int a = 0 ; a < 10 ; a ++ )
{
for ( int b = 0 ; b < 10 ; b ++ )
{
if (R[a, b] == 1 ) Console.Write( " " );
else if (R[a, b] == 3 ) Console.Write( " " );
else if (R[a, b] == 4 ) Console.Write( " " );

else Console.Write( " " );
}
Console.Write(
" \n " );
}

}


}

class Point
{
public int y;
public int x;
public int G;
public int H;

public Point()
{
}
public Point( int x0, int y0, int G0, int H0, Point F)
{
x
= x0;
y
= y0;
G
= G0;
H
= H0;
father
= F;
}


public Point father;
}


}

 

 

 

转载于:https://www.cnblogs.com/lipan/archive/2010/07/01/1769420.html

此为用C#写的A*算法源代码 using System; using System.Collections.Generic; using System.Text; using System.Drawing; namespace EtSoft.AStarLib { public class AStar { private StarNodeCollection openList = new StarNodeCollection(); private StarNodeCollection closeList = new StarNodeCollection(); public StarNode currentNode = null; #region 构造函数 /// <summary> /// 使用指定的地图对象、起点和终点初始化A星算法 /// </summary> /// <param name="map">地图对象</param> public AStar(Map map) { this.map = map; } /// <summary> /// /// </summary> /// <param name="map">地图对象</param> /// <param name="start">起点坐标</param> /// <param name="end">终点坐标</param> public AStar(Map map, Point start, Point end) : this(map) { this.start = new StarNode(start); this.end = new StarNode(end); openList.Add(new StarNode(start)); //AddStartNodeToOpenList(this.start); } /// <summary> /// /// </summary> /// <param name="map">地图对象</param> /// <param name="startX">起点X坐标</param> /// <param name="startY">起点Y坐标</param> /// <param name="endX">终点X坐标</param> /// <param name="endY">终点Y坐标</param> public AStar(Map map, int startX, int startY, int endX, int endY) : this(map, new Point(startX, startY), new Point(endX, endY)) { } #endregion #region 属性 protected Map map; /// <summary> /// 地图数据 /// </summary> public Map Map { get { return map; } set { map = value; } } private StarNode start = null; /// <summary> /// 起点坐标,如果没有设置起点,返回null /// </summary> public StarNode Start { get { return start; } set { start = value; openList.Clear(); openList.Add(start); //AddNodeToOpenList(start); } } private StarNode end = null; /// <summary> /// 终点坐标,如果没有设置终点,返回null /// </summary> public StarNode End { get { return end; } set { end = value; } } private StarNodeCollection path; /// <summary> /// 返回路径节点集合,没有路径则返回null /// </summary> public StarNodeCollection Path { get { return path; } } private bool allDirection = false; /// <summary> /// true,允许八方向寻路 /// </summary> public bool AllDirection { get { return allDirection; } set { allDirection = value; } } #endregion /// <summary> /// 开始寻路 /// </summary> public void StartSearchPath() { if (start == null) throw new InvalidNodeException(InvalidNodeTypes.NoStart); if (end == null) throw new InvalidNodeException(InvalidNodeTypes.NoEnd); path = null; openList.Clear(); closeList.Clear(); currentNode = start; SearchPath(currentNode); } //寻路递归,受保护的虚方法,允许在子类重写寻路算法 protected virtual void SearchPath(StarNode starNode) { //currentNode = starNode; openList.Remove(starNode); closeList.Add(starNode); AddNodeToOpenList(); if (closeList.Contains(end)) { //如果终点在关闭列表中,找到路径 StarNode node=starNode.Parent; path = new StarNodeCollection(); do { path.Add(node); node = node.Parent; } while (node != null && !node.Equals(start)); path.Reverse(); return; } else if (openList.Count == 0) { //终点不在关闭列表,开放列表已空,没有可通行的路径 return; } currentNode = GetNextNode(); //迭代过程 SearchPath(currentNode); } /// <summary> /// 获得当前节点的下一个最佳节点 /// </summary> /// <returns></returns> public StarNode GetNextNode() { openList.SortByF(); return openList[0]; } /// <summary> /// 把当前点周围可通过的点加入到开放列表中 /// </summary>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值