bool checkPos(Pos cur, int dx, int dy) { var o_score = astar_search[cur.y + dy, cur.x + dx]; if (o_score != null && o_score.closed) { return(false); } var cur_score = astar_search[cur.y, cur.x]; Pos o_pos = new Pos(cur.x + dx, cur.y + dy); if (mapInstance.map[cur.y + dy, cur.x + dx] == 8) { var a = new AScore(cur_score.G + 1, 0); a.parent = cur; astar_search[cur.y + dy, cur.x + dx] = a; Debug.Log("寻路完成。"); return(true); } if (mapInstance.map[cur.y + dy, cur.x + dx] == 0) { if (o_score == null) {// 在open表中没有该节点,计算该节点的h与g值,并把 var a = new AScore(cur_score.G + 1, Pos.AStarDistance(o_pos, mapInstance.endPos)); a.parent = cur; astar_search[cur.y + dy, cur.x + dx] = a; list.Add(o_pos); } else if (o_score.G > cur_score.G + 1) {// 在Open表中有该节点,比较两个x的G值,更新目标节点的G值。 o_score.G = cur_score.G + 1; o_score.parent = cur; if (!list.Contains(o_pos)) {// 如果检查列表中没有该节点,加入 list.Add(o_pos); } } } return(false); }
IEnumerator Astar_search() { astar_search = new AScore[map.GetLength(0), map.GetLength(1)]; List <Pos> list = new List <Pos>(); astar_search[StartPosition.y, StartPosition.x] = new AScore(0, 0); list.Add(StartPosition); // 每一个点的处理函数 Func func = (Pos cur, int ox, int oy) => { var o_score = astar_search[cur.y + oy, cur.x + ox]; if (o_score != null && o_score.closed) { return(false); } var cur_score = astar_search[cur.y, cur.x]; Pos o_pos = new Pos(cur.x + ox, cur.y + oy); if (map[cur.y + oy, cur.x + ox] == EndPoint) { var a = new AScore(cur_score.G + 1, 0); a.parent = cur; astar_search[cur.y + oy, cur.x + ox] = a; Debug.Log("寻路完成"); return(true); } if (map[cur.y + oy, cur.x + ox] == 0) { if (o_score == null) { var a = new AScore(cur_score.G + 1, Pos.AStarDistance(o_pos, EndPosition)); a.parent = cur; astar_search[cur.y + oy, cur.x + ox] = a; list.Add(o_pos); } else if (o_score.G > cur_score.G + 1) { o_score.G = cur_score.G + 1; o_score.parent = cur; if (!list.Contains(o_pos)) { list.Add(o_pos); } } } return(false); }; while (list.Count > 0) { list.Sort((Pos p1, Pos p2) => { AScore a1 = astar_search[p1.y, p1.x]; AScore a2 = astar_search[p2.y, p2.x]; //return a1.H.CompareTo(a2.H); return(a1.CompareTo(a2)); }); Pos cur = list[0]; list.RemoveAt(0); astar_search[cur.y, cur.x].closed = true; if (cur.y > 0) { if (func(cur, 0, -1)) { break; } } if (cur.y < Height - 1) { if (func(cur, 0, 1)) { break; } } if (cur.x > 0) { if (func(cur, -1, 0)) { break; } } if (cur.x < Width - 1) { if (func(cur, 1, 0)) { break; } } short[,] temp_map = new short[map.GetLength(0), map.GetLength(1)]; for (int i = 0; i < Height; ++i) { for (int j = 0; j < Width; ++j) { temp_map[i, j] = short.MaxValue; //if (map_search[i,j] != null && map_search[i,j].closed) if (astar_search[i, j] != null) { temp_map[i, j] = (short)astar_search[i, j].F; } } } Show_Search(temp_map); yield return(new WaitForSeconds(0.01f)); } yield return(null); }
//===============-BFS-================================================================================ #endregion #region DFS //===============-DFS-================================================================================ IEnumerator DFS() { bfs_search = new short[map.GetLength(0), map.GetLength(1)]; // map_search和map一样大小,每个元素的值:32767(short.MaxValue)代表不可通过或者未探索,其他值代表移动的步数 for (int i = 0; i < H; ++i) { for (int j = 0; j < W; ++j) { bfs_search[i, j] = short.MaxValue; //先初始化一个标记数组。 } } List <Pos> queue = new List <Pos>(); Func func = (Pos cur, int ox, int oy) => { //END=9/START=8 if (map[cur.y + oy, cur.x + ox] == END) //到达END=9 { bfs_search[cur.y + oy, cur.x + ox] = (short)(bfs_search[cur.y, cur.x] + 1); //==-32768 Debug.Log("Done"); return(true); } //起始点的下一个点不为墙并且在地图内 if (map[cur.y + oy, cur.x + ox] == 0) //bfs_search[startpos,startpos]=[0,0]下面设置,这里判断是否在地图内和不是墙 { if (bfs_search[cur.y + oy, cur.x + ox] > bfs_search[cur.y, cur.x] + 1) //最初始的bfs_search[cur.y,cur.x]=0; { bfs_search[cur.y + oy, cur.x + ox] = (short)(bfs_search[cur.y, cur.x] + 1); //搜索过的地方变成1,标记将去的点为已走过 queue.Add(new Pos(cur.x + ox, cur.y + oy)); //第二个点入队列表示为current了 } } return(false); }; bfs_search[startPos.y, startPos.x] = 0; //设置起始点的步数为0 queue.Add(startPos); while (queue.Count > 0) { int min_i = 0; Pos cur = queue[min_i]; float min_dist = Pos.AStarDistance(cur, endPos); for (int i = 0; i < queue.Count; i++) { float d = Pos.AStarDistance(queue[i], endPos); if (d < min_dist) { min_i = i; cur = queue[i]; min_dist = 0; } } queue.RemoveAt(min_i); //上 if (cur.y > 0) { //000 //000 //000 ->2 往上移动为2-1=1 变成第一行 if (func(cur, 0, -1)) { break; } } //下 if (cur.y < H - 1) { if (func(cur, 0, 1)) { break; } } //左 if (cur.x > 0) { if (func(cur, -1, 0)) { break; } } //右 if (cur.x < W - 1) { if (func(cur, 1, 0)) { break; } } if (bfs_search[cur.y, cur.x] > cur_depth) //最初cur_depth=0 第一次后变成1 { cur_depth = bfs_search[cur.y, cur.x]; RefreshPath(bfs_search); yield return(new WaitForSeconds(0.1f)); } } gameState = GameState.ShowPath; yield return(null); }
private AScore[,] astar_search; //是一个而为的点的信息,点里包含权重,F = G + H ; G为点要走过自身的格子距离,H为到目标点的距离 IEnumerator AStar() { astar_search = new AScore[map.GetLength(0), map.GetLength(1)]; //确保星可以遍布在地图每个点 List <Pos> MapTargetPoslist = new List <Pos>(); //只用来保存要涉及到的点的坐标 astar_search[startPos.y, startPos.x] = new AScore(0, 0); //让第一个起始点的G和H为0 MapTargetPoslist.Add(startPos); //将起始点记录进我们路线 ,因为是从此出发 Func func = (Pos curPos, int ox, int oy) => { var tar_Score = astar_search[curPos.y + oy, curPos.x + ox]; //表示下一个去的点; if (tar_Score != null && tar_Score.closed) { return(false); } var cur_Score = astar_search[curPos.y, curPos.x]; //表示当前所在的点 Pos nextPos = new Pos(curPos.x + ox, curPos.y + oy); if (map[curPos.y + oy, curPos.x + ox] == END) { var end_Score = new AScore(cur_Score.G + 1, 0); end_Score.parent = curPos; astar_search[curPos.y + oy, curPos.x + ox] = end_Score; Debug.Log("Done"); return(true); } if (map[curPos.y + oy, curPos.x + ox] == 0) //表示下一个点我们还没走过 { if (tar_Score == null) { var a = new AScore(cur_Score.G + 1, Pos.AStarDistance(nextPos, endPos)); //AStarDistance计算了下一个点 中点到endPos的距离放在H里,然后创建下个点 a.parent = curPos; astar_search[curPos.y + oy, curPos.x + ox] = a; MapTargetPoslist.Add(nextPos); //Debug.Log("next "+curPos.x+" "+curPos.y); } } return(false); }; while (MapTargetPoslist.Count > 0) { MapTargetPoslist.Sort((Pos p1, Pos p2) => { AScore a1 = astar_search[p1.y, p1.x]; AScore a2 = astar_search[p2.y, p2.x]; return(a1.CompareTo(a2)); }); //得到F最小的点放在list[0] Pos cur = MapTargetPoslist[0]; MapTargetPoslist.RemoveAt(0); astar_search[cur.y, cur.x].closed = true; //标记当前点为 以访问; // 上 if (cur.y > 0) { if (func(cur, 0, -1)) { break; } } // 下 if (cur.y < H - 1) { if (func(cur, 0, 1)) { break; } } // 左 if (cur.x > 0) { if (func(cur, -1, 0)) { break; } } // 右 if (cur.x < W - 1) { if (func(cur, 1, 0)) { break; } } short[,] temp_map = new short[map.GetLength(0), map.GetLength(1)]; for (int i = 0; i < H; ++i) { for (int j = 0; j < W; ++j) { temp_map[i, j] = short.MaxValue; //if (map_search[i,j] != null && map_search[i,j].closed) if (astar_search[i, j] != null) { temp_map[i, j] = (short)astar_search[i, j].F; } } } RefreshPath(temp_map); yield return(0); } Debug.Log("开始显示路线"); gameState = GameState.ShowPath; yield return(null); }
IEnumerator DFS() { bfs_search = new short[map.GetLength(0), map.GetLength(1)]; // map_search和map一样大小,每个元素的值:32767(short.MaxValue)代表不可通过或者未探索,其他值代表移动的步数 for (int i = 0; i < H; ++i) { for (int j = 0; j < W; ++j) { bfs_search[i, j] = short.MaxValue; } } List <Pos> queue = new List <Pos>(); Func func = (Pos cur, int ox, int oy) => { if (map[cur.y + oy, cur.x + ox] == END) { bfs_search[cur.y + oy, cur.x + ox] = (short)(bfs_search[cur.y, cur.x] + 1); Debug.Log("寻路完成"); return(true); } if (map[cur.y + oy, cur.x + ox] == 0) { if (bfs_search[cur.y + oy, cur.x + ox] > bfs_search[cur.y, cur.x] + 1) { bfs_search[cur.y + oy, cur.x + ox] = (short)(bfs_search[cur.y, cur.x] + 1); queue.Add(new Pos(cur.x + ox, cur.y + oy)); } } return(false); }; bfs_search[startPos.y, startPos.x] = 0; queue.Add(startPos); while (queue.Count > 0) { int min_i = 0; Pos cur = queue[min_i]; float min_dist = Pos.AStarDistance(cur, endPos); for (int i = 0; i < queue.Count; ++i) { float d = Pos.AStarDistance(queue[i], endPos); if (d < min_dist) { min_i = i; cur = queue[i]; min_dist = d; } } queue.RemoveAt(min_i); int last_count = queue.Count; // 上 bool flag = false; if (cur.y > 0) { if (func(cur, 0, -1)) { break; } } // 下 if (cur.y < H - 1) { if (func(cur, 0, 1)) { break; } } // 左 if (cur.x > 0) { if (func(cur, -1, 0)) { break; } } // 右 if (cur.x < W - 1) { if (func(cur, 1, 0)) { break; } } RefreshPath(bfs_search); yield return(new WaitForSeconds(0.05f)); } gameState = GameState.ShowPath; yield return(null); }
IEnumerator initDFS() { for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { dfs[i, j] = short.MaxValue; } } dfs[mapInstance.startPos.y, mapInstance.startPos.x] = 0; quene.Add(mapInstance.startPos); while (quene.Count > 0) { int min_i = 0; Pos cur = quene[min_i]; float min_dist = Pos.AStarDistance(cur, mapInstance.endPos); for (int i = 0; i < quene.Count; i++) { float d = Pos.AStarDistance(quene[i], mapInstance.endPos); if (d < min_dist) { min_i = i; cur = quene[i]; min_dist = d; } } quene.RemoveAt(min_i); int last_Count = quene.Count; if (cur.y > 0) { if (checkPos(cur, 0, -1, 0)) { break; } } if (cur.y < Height - 1) { if (checkPos(cur, 0, 1, 1)) { break; } } if (cur.x > 0) { if (checkPos(cur, -1, 0, 2)) { break; } } if (cur.x < Width - 1) { if (checkPos(cur, 1, 0, 3)) { break; } } Refresh(); yield return(new WaitForSeconds(0.05f)); } yield return(null); for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { allbfs += dfs[i, j].ToString() + ' '; } allbfs += '\n'; } // Refresh(); System.IO.File.WriteAllText(Application.dataPath + "//" + "dfsMap.txt", allbfs, Encoding.UTF8); StartCoroutine(visualPath()); }