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