A*寻路 SLG 战棋寻路 类

using System;
using System.Collections.Generic;

namespace GAME
{
    public struct mapPoint
    {
        public int x;
        public int y;
    }
    class FindWay
    {
        class Point
        {
            public Point() { }
            public int G;
            public int H;
            public int x;
            public int y;
            public Point father;
        }

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

        public List<mapPoint> Astar(mapPoint _startingPoint, mapPoint _destination, int movePower, ref byte[,] consumption)
        {
            //定义出发位置
            Point startingPoint = new Point();
            startingPoint.x = _startingPoint.x;
            startingPoint.y = _startingPoint.y;

            //定义目的地
            Point destination = new Point();
            destination.x = _destination.x;
            destination.y = _destination.y;

            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 });
            }

            return way;
        }
       
        //从开启列表查找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 IsInCloseList(int x, int y)
        {
            foreach (Point p in close_List) if (p.x == x && p.y == y) return true;
            return false;
        }
        //判断开启列表是否包含一个坐标的点
        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;
        }
        //检查当前节点附近的节点
        private 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 G_new = nowPoint.G + consumption[pt.x, pt.y];
                        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;
                        pt.G = pt.father.G + consumption[pt.x, pt.y];
                        pt.H = Math.Abs(pt.x - destination.x) + Math.Abs(pt.y - destination.y);
                        open_List.Add(pt);
                    }
                }
            }
        }
    }
}

  

posted on 2013-01-30 16:09  snet  阅读(749)  评论(0编辑  收藏  举报