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