/// <summary> /// A星寻路方法 /// </summary> /// <param name="start">起点</param> /// <param name="end">终点</param> /// <param name="allPlaces">所有有效点</param> /// <returns></returns> public static List <PathNode> AStarFindPath(Place start, Place end, List <Place> allPlaces) { if (start == null || end == null) { return(null); } List <PathNode> pathList = new List <PathNode>(); PathNode startNode = new PathNode(start); if (start == end) { pathList.Add(startNode); return(pathList); } //原地,则直接返回 closePathList = new List <PathNode>(); //开启列表 openPathList = new List <PathNode>(); //关闭列表 openPathList.Add(startNode); PathNode endNode = new PathNode(end); while (true) { List <Place> places = Draw.GetAroundPlaceList(allPlaces, startNode.Place); foreach (var p in places) { FindAroundNodeToOpenList(p, startNode, endNode); } //死路判断 if (openPathList.Count == 0) { return(null); } //应该是已经在openlist中的点要计算好相应的FGH值,判断沿着点位走到第二个点中,如果找到周边有前open点,且点数比当前点小 //则更新点位,删掉前一个点 //openPathList.Sort(SortOpenList);//排序,最小F的为0位 //PathNode minNode = openPathList.Find(obj => obj.F == openPathList.Min(o => o.F));//找到最小F值的node openPathList.OrderBy(o => o.F); PathNode minNode = openPathList[0]; closePathList.Add(minNode);//加入close列表中 //openPathList[0].ParentNode = startNode; startNode = minNode; openPathList.Remove(minNode);//open列表中删除 if (startNode.Place == end) { while (startNode.ParentNode != null) { pathList.Add(startNode); startNode = startNode.ParentNode; } pathList.Add(startNode); pathList.Reverse();//起点终点顺序 return(pathList); } } }
/// <summary> /// 设置未使用的place的地形type /// </summary> /// <param name="placeList">所有的place</param> public static void SetUnUsedPlacesType(List <Place> placeList) { int row = Settings1.Default.Draw_Row; int column = Settings1.Default.Draw_Column; List <Place> seaPlaces = new List <Place>(); for (int i = 0; i < row; i++)//横向的 { if (placeList[i * column].TerrainType == -1) { placeList[i * column].TerrainType = 2;//2ocean海洋 seaPlaces.Add(placeList[i * column]); } if (i > 0 && placeList[i * column - 1].TerrainType == -1) { placeList[i * column - 1].TerrainType = 2; seaPlaces.Add(placeList[i * column - 1]); } } for (int i = 0; i < column; i++)//纵向的 { if (placeList[i].TerrainType == -1) { placeList[i].TerrainType = 2; seaPlaces.Add(placeList[i]); } if (i > 0 && placeList[row * column - i].TerrainType == -1) { placeList[row * column - i].TerrainType = 2; seaPlaces.Add(placeList[row * column - i]); } } List <Place> unUsedPlaces = placeList.FindAll(obj => obj.TerrainType == -1); //找到所有未设定的地块 for (int j = 0; j < 2; j++) //多遍历一次 { for (int i = 0; i < unUsedPlaces.Count; i++) //遍历 { List <Place> tempplaces = Draw.GetAroundPlaceList(placeList, unUsedPlaces[i]); if (tempplaces.Exists(obj => obj.TerrainType == 2)) { unUsedPlaces[i].TerrainType = 2; seaPlaces.Add(unUsedPlaces[i]); unUsedPlaces.Remove(unUsedPlaces[i]); i = 0; } } } foreach (Place p in unUsedPlaces) { //剩下的就是湖泊 p.TerrainType = 1; } }
/// <summary> /// A*寻路方法,得到最短路径 /// </summary> /// <param name="start">起点</param> /// <param name="end">终点</param> /// <param name="places">所有地点集合</param> /// <returns></returns> public static List <PathNode> AStarPath(Place start, Place end, List <Place> places) { if (start == null || end == null) { return(null); } if (!places.Contains(end) || !places.Contains(start)) { return(null); } openPathList = new List <PathNode>(); closePathList = new List <PathNode>(); PathNode startNode = new PathNode(start); openPathList.Add(startNode); while (openPathList.Count != 0) { openPathList.OrderBy(o => o.F); PathNode tempStart = openPathList[0];//找到最小F值的node openPathList.RemoveAt(0); closePathList.Add(tempStart); //找出相邻的点 List <Place> aroundplaces = Draw.GetAroundPlaceList(places, tempStart.Place); foreach (var item in aroundplaces) { if (openPathList.Exists(o => o.Place.Index == item.Index)) { //计算G值, 如果比原来的大, 就什么都不做, 否则设置它的父节点为当前点,并更新G和F PathNode node = openPathList.Find(o => o.Place.Index == item.Index); FoundPoint(tempStart, node); } else { //如果它们不在开始列表里, 就加入, 并设置父节点,并计算GHF PathNode node = new PathNode(item); NotFoundPoint(tempStart, end, node); } } if (openPathList.Exists(o => o.Place == end)) { List <PathNode> resultPath = new List <PathNode>(); PathNode parent = openPathList.Find(o => o.Place == end); while (parent != null) { resultPath.Add(parent); parent = parent.ParentNode; } return(resultPath); } } return(null); }
/// <summary> /// 随机方式获得listplace中的点位,用于生成集结地块(生成陆地,海洋等) /// </summary> /// <param name="placeList">可用地块</param> /// <param name="seed">随机种子</param> /// <param name="percent">生成百分比</param> /// <param name="scatterPoint">初始点位数</param> /// <returns></returns> public static List <Place> GetRandomPlaces(List <Place> placeList, int seed, double percent, int scatterPoint) { if (percent > 1) { return(null); } if (placeList == null || placeList.Count == 0) { return(null); } if (scatterPoint == 0 || scatterPoint >= placeList.Count) { return(null); } Random random = new Random(seed); //List<Place> tempPlaces = new List<Place>(); List <Place> usedplaces = new List <Place>(); int s = placeList.Count / scatterPoint;//用于划区 for (int i = 0; i < scatterPoint; i++) { int index = random.Next(0, s) + (s * i); if (usedplaces.Exists(obj => obj.Index == index)) { i--; continue; } //不能重复 usedplaces.Add(placeList.Find(obj => obj.Index == index)); //找到对应index的place并写入list } //下面按比例生成地块 int count = (int)(placeList.Count * percent);//得到需生成的地块数 //usedplaces.AddRange(tempPlaces); for (int i = 0; i < count; i++) { Place tempPlace = usedplaces[random.Next(0, usedplaces.Count)]; //先随机到已使用的某个点位 List <Place> findPlaces = Draw.GetAroundPlaceList(placeList, tempPlace); //找周围可用的点位, foreach (Place p in usedplaces) //注意排除已使用的 { findPlaces.Remove(p); } if (findPlaces.Count == 0) { i--; continue; } //没有地块则重来 usedplaces.Add(findPlaces[random.Next(0, findPlaces.Count)]); //将随机到的点位加入已使用点位list中 } return(usedplaces); }
/// <summary> /// 给地块赋值区域(默认9块),根据地块terrain类型进行赋值 /// </summary> /// <param name="allPlaces">需要赋值的地块</param> /// <param name="seed">随机数种子</param> public static void SetPlaceDistrict(List <Place> allPlaces, int seed) { //int[] districts = new int[9]; Random random = new Random(seed); //List<District> districts=new List<District>(); foreach (Place p in allPlaces) { p.DistrictList = new List <District>(); //加入区划 for (int i = 0; i < 9; i++) //9是默认区划数 { int r = random.Next(0, Globle.DistFeature.Length - 8); //默认陆地 District district = new District(Globle.AllDistrictList.Count + i, p, r); p.DistrictList.Add(district); //p.DistrictList[i].TypeIndex = r; } Globle.AllDistrictList.AddRange(p.DistrictList); //加入到全局数据中 if (p.TerrainType == 0) //陆地 { if (p.DistrictList.Any(obj => obj.TypeIndex == 3) && !p.DistrictList.Any(obj => obj.TypeIndex == 2)) //表示有绿洲且无沙漠,则清除绿洲 { for (int i = 0; i < p.DistrictList.Count; i++) { if (p.DistrictList[i].TypeIndex == 3) { int r = random.Next(0, Globle.DistFeature.Length - 8); //排除湖泊和海洋区划类型 p.DistrictList[i].TypeIndex = r; if (r == 2) //有沙漠则不再循环 { break; } else { i = 0; continue; } } } } } else if (p.TerrainType == 1) //湖泊 { bool isLand = Draw.GetAroundPlaceList(allPlaces, p).Exists(obj => obj.TerrainType == 0); //判断是否靠岸 for (int i = 0; i < p.DistrictList.Count; i++) { int r = random.Next(11, Globle.DistFeature.Length - 4); //11开始,排除非湖泊类区划 if (isLand == false && r == 12 || r == 13) //没有陆地,不能形成河流和湿地,12为河流13湿地 { i--; continue; } p.DistrictList[i].TypeIndex = r; if (p.DistrictList[i].TypeIndex != 14) { if (random.Next(0, 4) == 0)//设置来偏移湖泊内容,目前1/4的几率非湖泊 { p.DistrictList[i].TypeIndex = r; } else { p.DistrictList[i].TypeIndex = 14;//设为湖泊 } } } } else if (p.TerrainType == 2) //海洋 { bool isLand = Draw.GetAroundPlaceList(allPlaces, p).Exists(obj => obj.TerrainType == 0); //判断是否靠岸 for (int i = 0; i < p.DistrictList.Count; i++) { int r = random.Next(15, Globle.DistFeature.Length); if (isLand == false && r == 17)//没有陆地,不能形成半岛,17为半岛 { i--; continue; } p.DistrictList[i].TypeIndex = r; if (p.DistrictList[i].TypeIndex != 18) { if (random.Next(0, 4) == 0)//设置来偏移海洋内容,目前1/4的几率非海洋 { p.DistrictList[i].TypeIndex = r; } else { p.DistrictList[i].TypeIndex = 18;//设为海洋 } } } } } }