public List <GridItem> GetNeighbors(GridItem source) { neighbors.Clear(); for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { // 排除自己 if (x == 0 && y == 0) { continue; } int gridX = source.gridX + x; int gridY = source.gridY + y; if (IsValid(gridX, gridY)) { var item = GetGridItem(gridX, gridY); neighbors.Add(item); } } } return(neighbors); }
/* * OPEN //开放列表 * CLOSED //封闭列表 * 把开始节点加入开放列表 * * loop * //找出开放接列表F代价最小的节点 * current = node in OPEN with the lowest f_cost * remove current from OPEN * add current to CLOSED * * if current is the target node //path has been found * return * * // 遍历所有邻居 * foreach neighbour of the current node * // 如果邻居已经遍历过了,或者邻居已经在封闭列表就跳过 * if neighbour is not traversable or neighbour is in CLOSED * skip to the next neighbour * // 如果到这个邻居的路径更短或者这个邻居不在开发列表 * if new path to neighbour is shorter OR neighbour is not in OPEN * set f_cost of neighbour * set parent of neighbour to current * if neighbour is not in OPEN * add neighbour to OPEN */ #endregion /// <summary> /// 输入起始点和结束点,输出路径列表 /// A星算法核心公式就是F值的计算: /// F = G + H /// F - 方块的总移动代价 /// G - 开始点到当前方块的移动代价 /// H - 当前方块到结束点的预估移动代价 /// </summary> public static List <IVisualStep> FindPath_AStar(PathFindManager mgr, GridItem start, GridItem end) { sw.Start(); // Visual Step 算法步骤可视化 List <IVisualStep> outSteps = new List <IVisualStep>(); // ~Visual stuff bool pathSuccess = false; List <GridItem> openSet = new List <GridItem>(); HashSet <GridItem> closeSet = new HashSet <GridItem>(); openSet.Add(start); while (openSet.Count > 0) { var current = openSet[0]; //找出开放列表中F代价最小的节点 todo 优化==》最优队列、或者最小堆 foreach (var item in openSet) { if (item.fCost < current.fCost) { current = item; } } // Visual Step 算法步骤可视化 if (current != start && current != end) { outSteps.Add(new VisitedTileStep(current, mgr)); } // ~Visual stuff openSet.Remove(current); closeSet.Add(current); if (current == end) { sw.Stop(); Debug.Log("AStar found: " + sw.ElapsedMilliseconds + " ms"); pathSuccess = true; break; } foreach (var neighbor in mgr.GetNeighbors(current)) { // 剔除封闭列表元素 if (closeSet.Contains(neighbor) || !neighbor.walkable) { continue; } // 逐个计算邻居的gCost int newCostToNeighbour = current.gCost + GetDistance(current, neighbor); //Debug.LogFormat("newCostToNeighbour:{0},neighbor.gCost:{1}", newCostToNeighbour, neighbor.gCost); if (newCostToNeighbour < neighbor.gCost || !openSet.Contains(neighbor)) { neighbor.gCost = newCostToNeighbour; neighbor.hCost = GetDistance(end, neighbor); neighbor.parent = current;//做成一个链表,最后用来做结果 //neighbor.SetText(string.Format("f:{0}\ng:{1}\nh:{2}", neighbor.fCost, neighbor.gCost,neighbor.hCost)); if (!openSet.Contains(neighbor)) { openSet.Add(neighbor); } // Visual Step 算法步骤可视化 if (neighbor != end) { outSteps.Add(new PushTileInOpenSetStep(neighbor, mgr)); } // ~Visual stuff } } } if (pathSuccess) { var results = ReversePath(start, end); // Visual Step 算法步骤可视化 foreach (var tile in results) { if (tile == start || tile == end) { continue; } outSteps.Add(new MarkPathTileStep(tile, mgr)); } return(outSteps); // ~Visual stuff } return(null); }
public static List <IVisualStep> FindPath_BFS(PathFindManager mgr, GridItem start, GridItem end) { sw.Start(); // Visual Step 算法步骤可视化 List <IVisualStep> outSteps = new List <IVisualStep>(); // ~Visual stuff List <GridItem> frontier = new List <GridItem>(); HashSet <GridItem> visited = new HashSet <GridItem>(); //首先将根节点放入队列中。 bool pathSuccess = false; start.parent = null; frontier.Add(start); visited.Add(start); while (frontier.Count > 0) { //从队列中取出第一个节点,并检验它是否为目标。 var current = frontier[0]; frontier.Remove(current); // Visual Step 算法步骤可视化 if (current != start && current != end) { outSteps.Add(new VisitedTileStep(current, mgr)); } // ~Visual stuff //如果找到目标,则结束搜寻并回传结果。 if (current == end) { sw.Stop(); Debug.Log("BFS found: " + sw.ElapsedMilliseconds + " ms"); pathSuccess = true; break; } ////否则将它所有尚未检验过的直接子节点(邻节点)加入队列中。 foreach (var neighbor in mgr.GetNeighbors(current)) { Debug.Log(neighbor.ToString()); if (!visited.Contains(neighbor)) { visited.Add(neighbor); frontier.Add(neighbor); neighbor.parent = current; // Visual Step 算法步骤可视化 if (neighbor != end) { outSteps.Add(new PushTileInFrontierStep(neighbor, mgr, 0)); } // ~Visual stuff } } } if (pathSuccess) { var results = ReversePath(start, end); // Visual Step 算法步骤可视化 foreach (var tile in results) { if (tile == start || tile == end) { continue; } outSteps.Add(new MarkPathTileStep(tile, mgr)); } return(outSteps); // ~Visual stuff } Debug.Log("BFS Can't Find!"); return(null); //若队列为空,表示整张图都检查过了——亦即图中没有欲搜寻的目标。结束搜寻并回传“找不到目标”。 }
public static List <IVisualStep> FindPath_GreedyBestFirstSearch(PathFindManager mgr, GridItem start, GridItem end) { sw.Start(); // Visual Step 算法步骤可视化 List <IVisualStep> outSteps = new List <IVisualStep>(); // ~Visual stuff List <GridItem> frontier = new List <GridItem>(); HashSet <GridItem> visited = new HashSet <GridItem>(); start.hCost = 0; bool pathSuccess = false; start.parent = null; frontier.Add(start); visited.Add(start); while (frontier.Count > 0) { var current = frontier[0]; //查找cost值最小的顶点A,放入path队列 foreach (var item in frontier) { if (item.hCost < current.hCost) { current = item; } } frontier.Remove(current); // Visual Step 算法步骤可视化 if (current != start && current != end) { outSteps.Add(new VisitedTileStep(current, mgr)); } // ~Visual stuff //如果找到目标,则结束搜寻并回传结果。 if (current == end) { sw.Stop(); Debug.Log("GreedyBestFirstSearch found: " + sw.ElapsedMilliseconds + " ms"); pathSuccess = true; break; } //否则将它所有尚未检验过的直接子节点(邻节点)加入队列中。 foreach (var neighbor in mgr.GetNeighbors(current)) { if (!visited.Contains(neighbor) && neighbor.walkable) { neighbor.hCost = GetDistance(neighbor, end); neighbor.parent = current; visited.Add(neighbor); frontier.Add(neighbor); // Visual Step 算法步骤可视化 if (neighbor != end) { outSteps.Add(new PushTileInFrontierStep(neighbor, mgr, neighbor.hCost)); } // ~Visual stuff } } } if (pathSuccess) { var results = ReversePath(start, end); // Visual Step 算法步骤可视化 foreach (var tile in results) { if (tile == start || tile == end) { continue; } outSteps.Add(new MarkPathTileStep(tile, mgr)); } return(outSteps); // ~Visual stuff } Debug.Log("GreedyBestFirstSearch Can't Find!"); return(null); }
public static List <IVisualStep> FindPath_Dijkstra(PathFindManager mgr, GridItem start, GridItem end) { sw.Start(); // Visual Step 算法步骤可视化 List <IVisualStep> outSteps = new List <IVisualStep>(); // ~Visual stuff List <GridItem> frontier = new List <GridItem>(); HashSet <GridItem> visited = new HashSet <GridItem>(); //初始时,只有起始顶点的预估值cost为0,其他顶点的预估值d都为无穷大 ∞。 foreach (var tile in mgr.GridItems) { tile.gCost = int.MaxValue; } start.gCost = 0; bool pathSuccess = false; start.parent = null; frontier.Add(start); visited.Add(start); while (frontier.Count > 0) { var current = frontier[0]; //查找cost值最小的顶点A,放入path队列 foreach (var item in frontier) { if (item.gCost < current.gCost) { current = item; } } frontier.Remove(current); // Visual Step 算法步骤可视化 if (current != start && current != end) { outSteps.Add(new VisitedTileStep(current, mgr)); } // ~Visual stuff //如果找到目标,则结束搜寻并回传结果。 if (current == end) { sw.Stop(); Debug.Log("Dijkstra found: " + sw.ElapsedMilliseconds + " ms"); pathSuccess = true; break; } //否则将它所有尚未检验过的直接子节点(邻节点)加入队列中。 foreach (var neighbor in mgr.GetNeighbors(current)) { int newCostToNeighbour = current.gCost + neighbor.weight; if (newCostToNeighbour < neighbor.gCost || !visited.Contains(neighbor)) { neighbor.gCost = newCostToNeighbour; neighbor.parent = current; visited.Add(neighbor); frontier.Add(neighbor); // Visual Step 算法步骤可视化 if (neighbor != end) { outSteps.Add(new PushTileInFrontierStep(neighbor, mgr, neighbor.gCost)); } // ~Visual stuff } } } if (pathSuccess) { var results = ReversePath(start, end); // Visual Step 算法步骤可视化 foreach (var tile in results) { if (tile == start || tile == end) { continue; } outSteps.Add(new MarkPathTileStep(tile, mgr)); } return(outSteps); // ~Visual stuff } Debug.Log("Dijkstra Can't Find!"); return(null); }
public IEnumerable <GridItem> GetNeighbors(GridItem tile) { neighbors.Clear(); // 九宫格 //for(int x = -1; x <= 1; x++) //{ // for(int y = -1; y <= 1; y++) // { // // 排除自己 // if(x == 0 && y == 0) // continue; // int gridX = source.gridX + x; // int gridY = source.gridY + y; // if(IsValid(gridX, gridY)) // { // var item = GetGridItem(gridX, gridY); // neighbors.Add(item); // } // } //} // 四格 //for(int i = 0; i < neighborMap.Count; i++) //{ // var array = neighborMap[i]; // int gridX = tile.gridX + array[0]; // int gridY = tile.gridY + array[1]; // if(IsValid(gridX, gridY)) // { // var item = GetGridItem(gridX, gridY); // neighbors.Add(item); // } //} //return neighbors; var right = GetGridItem(tile.gridX, tile.gridY + 1); if (right != null) { yield return(right); } var up = GetGridItem(tile.gridX - 1, tile.gridY); if (up != null) { yield return(up); } var left = GetGridItem(tile.gridX, tile.gridY - 1); if (left != null) { yield return(left); } var down = GetGridItem(tile.gridX + 1, tile.gridY); if (down != null) { yield return(down); } }
/* * OPEN //开放列表 * CLOSED //封闭列表 * 把开始节点加入开放列表 * * loop * //找出开放接列表F代价最小的节点 * current = node in OPEN with the lowest f_cost * remove current from OPEN * add current to CLOSED * * if current is the target node //path has been found * return * * // 遍历所有邻居 * foreach neighbour of the current node * // 如果邻居已经遍历过了,或者邻居已经在封闭列表就跳过 * if neighbour is not traversable or neighbour is in CLOSED * skip to the next neighbour * // 如果到这个邻居的路径更短或者这个邻居不在开发列表 * if new path to neighbour is shorter OR neighbour is not in OPEN * set f_cost of neighbour * set parent of neighbour to current * if neighbour is not in OPEN * add neighbour to OPEN */ #endregion /// <summary> /// 输入起始点和结束点,输出路径列表 /// A星算法核心公式就是F值的计算: /// F = G + H /// F - 方块的总移动代价 /// G - 开始点到当前方块的移动代价 /// H - 当前方块到结束点的预估移动代价 /// </summary> public static List <GridItem> FindPath_AStar(PathFindManager mgr, GridItem start, GridItem end) { sw.Start(); bool pathSuccess = false; openSet = new List <GridItem>(); closeSet = new HashSet <GridItem>(); openSet.Add(start); while (openSet.Count > 0) { var current = openSet[0]; //找出开放列表中F代价最小的节点 todo 优化==》最优队列、或者最小堆 foreach (var item in openSet) { if (item.fCost < current.fCost) { current = item; } } openSet.Remove(current); closeSet.Add(current); if (current == end) { sw.Stop(); Debug.Log("Path found: " + sw.ElapsedMilliseconds + " ms"); pathSuccess = true; break; } var neighbors = mgr.GetNeighbors(current); foreach (var neighbor in neighbors) { // 剔除封闭列表元素 if (closeSet.Contains(neighbor) || !neighbor.walkable) { continue; } // 逐个计算邻居的gCost int newCostToNeighbour = current.gCost + GetDistance(current, neighbor); if (newCostToNeighbour < neighbor.gCost || !openSet.Contains(neighbor)) { neighbor.gCost = newCostToNeighbour; neighbor.hCost = GetDistance(end, neighbor); neighbor.parent = current;//做成一个链表,最后用来做结果 neighbor.SetText(string.Format("f:{0}\ng:{1}\nh:{2}", neighbor.fCost, neighbor.gCost, neighbor.hCost)); if (openSet.Contains(neighbor)) { //openSet } else { openSet.Add(neighbor); } } } } if (pathSuccess) { var results = RetracePath(start, end); pathSuccess = results.Count > 0; return(results); } return(null); }