C# A*寻路算法代码

using System;
using System.Collections.Generic;

public struct _mapPoint
{
    public int x;
    public int y;
}
class FindWay
{
    class Point
    {
        public Point() { }
        public Point(_mapPoint m) { x = m.x; y = m.y; }
        public int G;
        public int H;
        public int x;
        public int y;
        public Point father;
    }

    //开启列表
    static List<Point> open_List = new List<Point>();
    //关闭列表
    static List<Point> close_List = new List<Point>();

    /// <summary>
    /// A*寻路算法
    /// </summary>
    /// <param name="startPoint"></param>
    /// <param name="endPoint"></param>
    /// <param name="movePower"></param>
    /// <param name="consumption"></param>
    /// <returns></returns>
    public static List<_mapPoint> Astar(_mapPoint startPoint, _mapPoint endPoint, int movePower, ref byte[,] consumption)
    {
        //定义出发位置
        Point startingPoint = new Point(startPoint);

        //定义目的地
        Point destination = new Point(endPoint);

        open_List.Add(startingPoint);
        while (!(IsInOpenList(destination.x, destination.y))) //当终点存在开启列表中就意味着寻路结束了
        {
            Point nowPoint = GetMinFFromOpenList();
            open_List.Remove(nowPoint);
            close_List.Add(nowPoint);
            CheckGrid(nowPoint, destination, ref consumption);
        }

        List<_mapPoint> way = new List<_mapPoint>();

        Point p = GetPointFromOpenList(destination.x, destination.y);
        List<Point> temp = new List<Point>();
        while (p.father != null)
        {
            temp.Add(p);
            p = p.father;
        }
        temp.Reverse();
        foreach (Point pt in temp)
        {
            if (pt.G > movePower) break;
            way.Add(new _mapPoint() { x = pt.x, y = pt.y });
        }
        open_List.Clear();
        close_List.Clear();
        return way;
    }

    //从开启列表查找F值最小的节点
    private static 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 static bool IsInCloseList(int x, int y)
    {
        Point p = close_List.Find(item => item.x == x && item.y == y);
        if (p!=null) return true;

        return false;
    }
    //判断开启列表是否包含一个坐标的点
    private static bool IsInOpenList(int x, int y)
    {
        Point p = open_List.Find(item => item.x == x && item.y == y);
        if (p!=null) return true;

        return false;
    }
    //从开启列表返回对应坐标的点
    private static Point GetPointFromOpenList(int x, int y)
    {
        foreach (Point p in open_List) if (p.x == x && p.y == y) return p;
        return null;
    }
    //检查当前节点附近的节点
    private static void CheckGrid(Point nowPoint, Point destination, ref byte[,] consumption)
    {
        for (int xt = nowPoint.x - 1; xt <= nowPoint.x + 1; xt++)
        {
            for (int yt = nowPoint.y - 1; yt <= nowPoint.y + 1; yt++)
            {
                //排除超过边界、不相干和关闭列表中的点
                if (!(xt >= 0 && xt < consumption.GetLength(0) && yt >= 0 && yt < consumption.GetLength(1))) continue;
                if (IsInCloseList(xt, yt)) continue;
                if (!(xt == nowPoint.x && yt - 1 == nowPoint.y) && !(xt - 1 == nowPoint.x && yt == nowPoint.y) && !(xt + 1 == nowPoint.x && yt == nowPoint.y) && !(xt == nowPoint.x && yt + 1 == nowPoint.y))
                    continue;

                if (IsInOpenList(xt, yt))
                {
                    Point pt = GetPointFromOpenList(xt, yt);
                    int cost = CalculateConsumption(ref consumption, pt, nowPoint);
                    int G_new = nowPoint.G + cost;
                    if (G_new < pt.G)
                    {
                        open_List.Remove(pt);
                        pt.father = nowPoint;
                        pt.G = G_new;
                        open_List.Add(pt);
                    }
                }
                else //不在开启列表中
                {
                    Point pt = new Point();
                    pt.x = xt;
                    pt.y = yt;
                    pt.father = nowPoint;
                    int cost = CalculateConsumption(ref consumption, pt, nowPoint);
                    pt.G = pt.father.G + cost;
                    pt.H = Math.Abs(pt.x - destination.x) + Math.Abs(pt.y - destination.y);
                    open_List.Add(pt);
                }
            }
        }
    }

    /// <summary>
    /// 计算移动消耗
    /// </summary>
    /// <param name="consumption"></param>
    /// <param name="pt"></param>
    /// <param name="nowPoint"></param>
    /// <returns></returns>
    private static int CalculateConsumption(ref byte[,] consumption, Point pt,Point nowPoint)
    {
        int xt = nowPoint.x;
        int yt = nowPoint.y;
        int cost = consumption[pt.x, pt.y] - consumption[xt, yt];
        if (cost <= 1) cost = 1;
        else if (cost > 1 || cost < 2) cost *= Road.jumpCost;
        else cost *= Road.climbCost;
        return cost;
    }
}
此为用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>
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值