//获得成本最小的节点 AstarListNode AstarGetMinCostList(AstarList astar) { AstarListNode min = astar.openHead.next; AstarListNode current = min.next; while (current != null) { if (current.h < min.h) { min = current; } current = current.next; } return(min); }
public bool AStarSearch(List <List <int> > map, int startX, int startY, int endX, int endY) { astarPathCount = 0; astarPathList.Clear(); _map = map; _startX = startX; _startY = startY; _endX = endX; _endY = endY; if (AstarIsBlock(endX, endY)) { return(false); } int[] offsetX = new int[] { 0, 0, -1, 1 }; int[] offsetY = new int[] { 1, -1, 0, 0 }; // int[] offsetX = new int[]{0, 0, -1, 1, -1, -1, 1, 1}; // int[] offsetY = new int[]{1, -1, 0, 0, 1, -1, 1, -1}; AstarList astar = new AstarList(); astar.openHead = new AstarListNode(); astar.closedHead = new AstarListNode(); AstarListNode currentNode = null; AstarListNode startNode = new AstarListNode(); AstarNodeInit(startNode, null, _startX, _startY, _endX, _endY); AstarAddNode(astar.openHead, startNode); while (astar.openHead.next != null) { currentNode = AstarGetMinCostList(astar); if (currentNode.x == endX && currentNode.y == endY) { break; } else { AstarAddNode(astar.closedHead, currentNode); AstarRemoveNode(astar.openHead, currentNode); for (int i = 0; i < 4; i++) { int x = currentNode.x + offsetX[i]; int y = currentNode.y + offsetY[i]; if (x < 0 || x >= _map.Count || y < 0 || y >= _map[0].Count) { continue; } else { if (!AstarCheckNodeInList(x, y, astar.openHead) && !AstarCheckNodeInList(x, y, astar.closedHead) && !AstarIsBlock(x, y)) { AstarListNode endNode = new AstarListNode(); AstarNodeInit(endNode, currentNode, x, y, endX, endY); AstarAddNode(astar.openHead, endNode); } } } } } if (astar.openHead.next == null && (currentNode.x != endX || currentNode.y != endY)) { astarPathCount = 0; } else { while (currentNode != null) { Vector2i point = new Vector2i(); point.x = currentNode.x; point.y = currentNode.y; //astarPathList.Add(point); astarPathList.Insert(0, point); currentNode = currentNode.father; astarPathCount++; } return(true); } return(false); }
/// <summary> /// 重启A*寻路,最短路径保存在Player1MinRoad或Player2MinRoad中,返回最短路径长度 /// </summary> /// <param name="Player">寻路玩家</param> /// <param name="Location_row">该玩家所在位置行</param> /// <param name="Location_col">该玩家所在位置列</param> /// <returns>最短路径长度</returns> public int AstarRestart(ChessBoard ToAstarSearch, EnumNowPlayer Player, int Location_row, int Location_col) { //bool IfContains = false; System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); // 开始监视代码运行时间 /***************待测代码段****************/ //int TableSearchResult = 0; //string BoardHashCode = LookupRoadAlgorithm.ResultSaveTable.GetHashCode_String( // ToAstarSearch, Player); //if (ResultSaveTable.Search(BoardHashCode, ref TableSearchResult)) //{ // Console.WriteLine("此局面已在存储表中!K值:" + BoardHashCode + "V值:" + TableSearchResult.ToString()); // /***************待测代码段****************/ // stopwatch.Stop(); // 停止监视 // TimeSpan timespan = stopwatch.Elapsed; // 获取当前实例测量得出的总时间 // Console.WriteLine("存储表命中寻路用时:" + timespan.TotalMilliseconds.ToString() + "ms"); // //return TableSearchResult; // IfContains = true; //} //else //{ // /***************待测代码段****************/ // stopwatch.Stop(); // 停止监视 // TimeSpan timespan2 = stopwatch.Elapsed; // 获取当前实例测量得出的总时间 // Console.WriteLine("存储表查询费时:" + timespan2.TotalMilliseconds.ToString() + "ms"); //} //stopwatch.Restart(); /***************待测代码段****************/ Min_DistanceLength = 999; List <AstarList> InitAList = new List <AstarList>(); Astar_Stop = false; AstarList InitGrid = new AstarList(6, 0, 6, Location_row, Location_col); InitAList.Add(InitGrid); int distance = LookupRoad_Astar(ToAstarSearch, Player, InitGrid, 1, new List <AstarList>(), InitAList); /***************待测代码段****************/ stopwatch.Stop(); // 停止监视 TimeSpan timespan3 = stopwatch.Elapsed; // 获取当前实例测量得出的总时间 if (QuoridorEvalution.AIRunTime.Astar_s == 0) { QuoridorEvalution.AIRunTime.Astar_s = timespan3.TotalMilliseconds; } else { QuoridorEvalution.AIRunTime.Astar_s += timespan3.TotalMilliseconds; QuoridorEvalution.AIRunTime.Astar_s /= 2; } QuoridorEvalution.AIRunTime.AstarNum++; //if (!IfContains) // LookupRoadAlgorithm.ResultSaveTable.Add(BoardHashCode, Min_DistanceLength); return(Min_DistanceLength); }
/// <summary> /// A*寻路,最短路径保存在Player1MinRoad或Player2MinRoad中,返回最短路径长度 /// </summary> /// <param name="Player">寻路玩家</param> /// <param name="NowGrid">当前寻路的格子</param> /// <param name="num_renew">迭代次数</param> /// <param name="OpenList">Open列表</param> /// <param name="CloseList">Close列表</param> /// <returns></returns> public int LookupRoad_Astar(ChessBoard ThisChessBoard, EnumNowPlayer Player, AstarList NowGrid, int num_renew, List <AstarList> OpenList, List <AstarList> CloseList) { int Location_row = NowGrid.Grid_row; int Location_col = NowGrid.Grid_col; if (Astar_Stop == true) { return(Min_DistanceLength); } int Row_Destination = 0; #region 设置目的地行 switch (Player) { case EnumNowPlayer.Player1: Row_Destination = 6; break; case EnumNowPlayer.Player2: Row_Destination = 0; break; default: break; } #endregion #region 检查四周能移动的位置添加进P_List_Enable列表 //计算四周能移动的位置的距离 List <Point> P_List_Enable = new List <Point>(); //左 if (Location_col > 0 && !(ThisChessBoard.ChessBoardAll[Location_row, Location_col].IfLeftBoard)) { P_List_Enable.Add(new Point(Location_row, Location_col - 1)); } //右 if (Location_col < 6 && !(ThisChessBoard.ChessBoardAll[Location_row, Location_col + 1].IfLeftBoard)) { P_List_Enable.Add(new Point(Location_row, Location_col + 1)); } //上 if (Location_row > 0 && !(ThisChessBoard.ChessBoardAll[Location_row, Location_col].IfUpBoard)) { P_List_Enable.Add(new Point(Location_row - 1, Location_col)); } //下 if (Location_row < 6 && !(ThisChessBoard.ChessBoardAll[Location_row + 1, Location_col].IfUpBoard)) { P_List_Enable.Add(new Point(Location_row + 1, Location_col)); } #endregion #region 扫描是否有木板,用来减少搜索空间 bool flag_NoBoard = true; bool flag_UpNowBoard = true; bool flag_DownNowBoard = true; for (int k = Location_row + 1; k <= Row_Destination; k++)//下扫 { if (ThisChessBoard.ChessBoardAll[k, Location_col].IfUpBoard) { flag_DownNowBoard = false; break; } } for (int k = Location_row - 1; k >= Row_Destination; k--)//上扫 { if (ThisChessBoard.ChessBoardAll[k + 1, Location_col].IfUpBoard) { flag_UpNowBoard = false; break; } } if (flag_DownNowBoard && flag_UpNowBoard) { flag_NoBoard = true; } else { flag_NoBoard = false; } if (flag_NoBoard) { Astar_Stop = true; Min_DistanceLength = Math.Abs((Row_Destination - Location_row)) + CloseList.Last().G; #region 迭代寻找最短路径 List <Point> MinRoad; if (Player == EnumNowPlayer.Player1) { Player1MinRoad = new List <Point>(); MinRoad = Player1MinRoad; } else { Player2MinRoad = new List <Point>(); MinRoad = Player2MinRoad; } if (Location_row < Row_Destination) { for (int i = Row_Destination; i >= Location_row; i--) { MinRoad.Add(new Point(i, Location_col)); } } else { for (int i = Row_Destination; i <= Location_row; i++) { MinRoad.Add(new Point(i, Location_col)); } } AstarList ALBuff = CloseList.Last(); while (true) { if (ALBuff.Father != null) { MinRoad.Add(new Point(ALBuff.Father.Grid_row, ALBuff.Father.Grid_col)); ALBuff = ALBuff.Father; } else { break; } } #endregion return(Min_DistanceLength); } #endregion #region 搜索树搜索策略——A*算法 List <int> P_Dis = new List <int>(); for (int i = 0; i < P_List_Enable.Count; i++) { P_Dis.Add(999); } int minF = 9999; int minindex = 0; for (int i = 0; i < P_List_Enable.Count && i >= 0; i++) { int Hbuff = Math.Abs(P_List_Enable[i].X - Row_Destination); P_Dis[i] = Hbuff; int Gbuff = num_renew; int Fbuff = Hbuff + Gbuff; bool flag_InClose = false; //检测是否在Close列表里 for (int j = 0; j < CloseList.Count; j++) { if (P_List_Enable[i].X == CloseList[j].Grid_row && P_List_Enable[i].Y == CloseList[j].Grid_col) { P_List_Enable.Remove(P_List_Enable[i]); P_Dis.Remove(P_Dis[i]); i--; flag_InClose = true; break; } } if (flag_InClose) { continue; } bool flag_InOpen = false; //检测是否在Open列表里 for (int j = 0; j < OpenList.Count; j++) { if (P_List_Enable[i].X == OpenList[j].Grid_row && P_List_Enable[i].Y == OpenList[j].Grid_col) { P_List_Enable.Remove(P_List_Enable[i]); P_Dis.Remove(P_Dis[i]); i--; flag_InOpen = true; if (Gbuff < OpenList[j].G) { OpenList[j].G = Gbuff; OpenList[j].F = Fbuff; OpenList[j].H = Hbuff; OpenList[j].Father = NowGrid; } break; } } if (!flag_InOpen && !flag_InClose) { AstarList NewGrid = new AstarList(Hbuff, Gbuff, Fbuff, P_List_Enable[i].X, P_List_Enable[i].Y); NewGrid.Father = NowGrid; OpenList.Add(NewGrid); } } AstarList MinFGrid = new AstarList(-1, -1, -1, -1, -1); for (int i = 0; i < OpenList.Count; i++) { int Fbuff = OpenList[i].F; if (Fbuff < minF) { minF = Fbuff; minindex = i; MinFGrid = OpenList[i]; } } CloseList.Add(MinFGrid); int dislengthbuff = 0; if (MinFGrid.Grid_row == Row_Destination && Astar_Stop == false) { Min_DistanceLength += MinFGrid.G; Astar_Stop = true; return(Min_DistanceLength); } else { if (OpenList.Count > 0) { OpenList.Remove(MinFGrid); dislengthbuff = LookupRoad_Astar(ThisChessBoard, Player, MinFGrid, MinFGrid.G + 1, OpenList, CloseList); } else { return(999); } } #endregion return(dislengthbuff); }