C# 4格A*自动寻径

    class Program
    {
        //public const char[] _specialStrings = { '☆', '★', '○', '●', '◎', '◇', '◆', '□', '■', '△', '▲', '※' };

        public class Row
        {
            public int Id { get; set; }
            public List<Cell> Cells { get; set; }
        }


        public enum Terrian
        {
            Sea,
            Land,
            River,
            Mountain
        }

        public class Cell
        {
            public int X { get; set; }
            public int Y { get; set; }

            #region
            public int G { get; set; }
            public int H { get; set; }
            public Cell Father { get; set; }

            public bool IsMove
            {
                get
                {
                    if (this._terr == Terrian.Mountain || this._terr == Terrian.Sea)
                        return false;
                    return true;
                }
            }

            #endregion


            public event Action TerrianChanged;
            public void OnTerrianChanged()
            {
                TerrianChanged?.Invoke();
            }


            private Terrian _terr = Terrian.Sea;


            public Terrian GetTerr()
            {
                return this._terr;
            }
            public void SetTerr(Terrian terr)
            {
                this._terr = terr;
            }

            public char GetRender()
            {
                switch (this._terr)
                {
                    case Terrian.Sea:
                        return '';
                    case Terrian.Land:
                        return '';
                    case Terrian.River:
                        return '';
                    case Terrian.Mountain:
                        return '';
                    default:
                        return ' ';
                }
            }


            public bool IsEqual(Cell cell)
            {
                if (this.X == cell.X && this.Y == cell.Y)
                    return true;
                else
                    return false;
            }


        }
        public class Map
        {

            private int _rowCount = 100;
            private int _cellCount = 100;
            private Random _random = new Random();
            private delegate void SetTerrianFunc(Cell Source);

            public List<Row> Rows { get; set; }

            private void InitRows()
            {
                this.Rows = new List<Row>();
                for (int y = 0; y < this._rowCount; y++)
                {
                    var cells = new List<Cell>();
                    for (int x = 0; x < this._cellCount; x++)
                    {
                        var cell = new Cell { X = x, Y = y };
                        cells.Add(cell);
                    }
                    var row = new Row { Id = y, Cells = cells };
                    this.Rows.Add(row);
                }
            }


            public Map(int rowCount, int colCount)
            {
                this._rowCount = rowCount;
                this._cellCount = colCount;

                InitRows();

                ExecuteMap();
            }

            private void ExecuteMap()
            {
                var landSource = GetCell(0, 0);
                DrawLand(landSource);

                var center = GetCenterCell();
                DrawRangeRandom(center, 0, 5, 30, SetMountain);

                int tmpRange = 5;
                var start = GetCell(center.X - tmpRange, center.Y - tmpRange);
                var end = GetCell(center.X + tmpRange, center.Y + tmpRange);
                SetLand(start);
                SetLand(end);
                DrawRiver(start, end);

                //测试代码写于此处


            }



            private void DrawLand(Cell source)
            {
                int land = Convert.ToInt32(_cellCount * 0.7);
                int Islands = Convert.ToInt32(_cellCount * 0.9);

                DrawRangeRandom(source, 0, land, 100, SetLand);
                DrawRangeRandom(source, land, Islands, 20, SetLand);
            }

            private void DrawRangeRandom(Cell source, int startRange, int endRange, int percentage, SetTerrianFunc func)
            {
                var list = GetCells(source, startRange, endRange).Where(x => _random.Next(0, 100) < percentage).ToList();
                SetTerrian(list, func);
            }

            private void DrawRiver(Cell start, Cell end)
            {
                var list = GetPatch(start, end);
                SetTerrian(list, SetRiver);
            }


            #region A*


            private List<Cell> _openList = new List<Cell>();
            private List<Cell> _closeList = new List<Cell>();

            private bool IsInOpenList(Cell cell)
            {
                foreach (var open in _openList)
                    if (open.IsEqual(cell))
                        return true;

                return false;
            }

            private bool IsInCloseList(Cell cell)
            {
                foreach (var open in _closeList)
                    if (open.IsEqual(cell))
                        return true;

                return false;
            }

            private Cell GetMinFFromOpenList()
            {
                Cell Pmin = null;
                foreach (Cell p in _openList)
                    if (Pmin == null || Pmin.G + Pmin.H > p.G + p.H)
                        Pmin = p;
                return Pmin;
            }


            public List<Cell> GetPatch(Cell Start, Cell End)
            {
                var path = new List<Cell>();

                _openList.Add(Start);
                while (!(IsInOpenList(End) || _openList.Count == 0))
                {
                    Cell minF = GetMinFFromOpenList();
                    if (minF == null) return null;
                    _openList.Remove(minF);
                    _closeList.Add(minF);

                    CheckP4(minF, Start, ref End);
                }

                while (End.Father != null)
                {
                    path.Add(End);
                    End = End.Father;
                }

                return path;
            }


            private int GetG(Cell p, Cell pb)
            {
                return Math.Abs(p.X - pb.X) + Math.Abs(p.Y - pb.Y);
            }

            //计算某个点的H值  
            private int GetH(Cell p, Cell pb)
            {
                return Math.Abs(p.X - pb.X) + Math.Abs(p.Y - pb.Y);
            }
            //检查当前节点附近的节点  
            private void CheckP4(Cell minF, Cell pa, ref Cell pb)
            {

                foreach (var nb in GetNeighbors(minF))
                {
                    if (nb.IsMove && !IsInCloseList(nb))
                    {
                        if (IsInOpenList(nb))
                        {
                            _openList.Remove(nb);
                            nb.Father = minF;
                            _openList.Add(nb);
                        }
                        else
                        {
                            //不在开启列表中  
                            nb.Father = minF;
                            nb.H = GetH(nb, pb);
                            nb.G = GetG(nb, pa);
                            _openList.Add(nb);
                        }
                    }
                }

            }

            #endregion


            #region Cell

            public void SetSea(Cell Source)
            {
                Source.SetTerr(Terrian.Sea);
            }

            public void SetLand(Cell Source)
            {
                Source.SetTerr(Terrian.Land);
            }

            public void SetMountain(Cell Source)
            {
                Source.SetTerr(Terrian.Mountain);
            }

            public void SetRiver(Cell Source)
            {
                Source.SetTerr(Terrian.River);
            }

            private void SetTerrian(List<Cell> list, SetTerrianFunc func)
            {
                foreach (var cell in list)
                {
                    func(cell);
                }
            }

            public Cell GetCell(int X, int Y)
            {
                if (X < this._cellCount && Y < this._rowCount && X >= 0 && Y >= 0)
                    return this.Rows[Y].Cells[X];
                else
                    return null;
            }

            private Cell GetCenterCell()
            {
                return GetCell(_cellCount / 2, _rowCount / 2);
            }

            public List<Cell> GetCells(Cell source, int startRange, int endRange)
            {
                var list = new List<Cell>();

                for (int y = source.Y - endRange; y <= source.Y + endRange; y++)
                {
                    for (int x = source.X - endRange; x <= source.X + endRange; x++)
                    {
                        if (x <= source.X - startRange || x >= source.X + startRange || y <= source.Y - startRange || y >= source.Y + startRange)
                        {
                            list.Add(GetCell(x, y));
                        }
                    }
                }

                return list.Where(x => x != null).Distinct().ToList();
            }


            private Cell GetLeft(Cell source)
            {
                return GetCell(source.X - 1, source.Y);
            }

            private Cell GetRight(Cell source)
            {
                return GetCell(source.X + 1, source.Y);
            }

            private Cell GetUp(Cell source)
            {
                return GetCell(source.X, source.Y - 1);
            }

            private Cell GetDown(Cell source)
            {
                return GetCell(source.X, source.Y + 1);
            }

            private List<Cell> GetNeighbors(Cell source)
            {
                var nbs = new List<Cell>();

                nbs.Add(GetLeft(source));
                nbs.Add(GetRight(source));
                nbs.Add(GetUp(source));
                nbs.Add(GetDown(source));

                return nbs.Where(x => x != null).ToList();
            }

            #endregion



        }


        static void Main(string[] args)
        {
            var map = new Map(40, 50);

            foreach (var row in map.Rows)
            {
                string str = "";
                foreach (var cell in row.Cells)
                {
                    str += cell.GetRender();
                }
                Console.WriteLine(str);
            }

            Console.ReadKey();
        }


    }

 

posted @ 2018-01-09 17:33  码农丁  阅读(155)  评论(0编辑  收藏  举报