題目:給出下面迷宮,0表示通路,1表示障礙物,請找出入口(0,0)至出口(7,7)的路
思路:
1.設置三個指針,last ,now,next 起始位置都設置在入口。
2.實現一個尋找候選點的方法,候選點中不應該包含當前點的位置
3.判斷是否有候選點,且是否為出口。
4.如果沒有候選點,退回一步,判斷是不是入口。
5.如果上一個點不是入口,刪除上一個點的第一個候選點,然后試上一個點的第二個候選點
6.如果上一個點沒有其他的候選點,再退回一步,從路徑中刪除這些錯誤的點
7.重復步驟,直達找到出口
Step 1 :先實現一個Point類:

1 class Point 2 { 3 int x; 4 int y; 5 public int Position_X 6 { 7 get { return x; } 8 set { x = value; } 9 } 10 public int Position_Y 11 { 12 get { return y; } 13 set { y = value; } 14 } 15 public Point() { } 16 public Point(int x, int y) 17 { 18 Position_X = x; 19 Position_Y = y; 20 } 21 }
Step 2 :定義全局變量,保存可以走的點的List和這些點的可以走的下一個點的List 以及三個指針和是否結束的flag
1 List<Point> way = new List<Point>(); 2 List<List<Point>> candicates = new List<List<Point>>(); 3 Point sureLast = null; 4 Point sureNow = null; 5 Point notSureNext = null; 6 bool finish = false;
Step 3 :判斷一個點是否是出口
1 public bool IsExit(Point p, int[][] maze) 2 { 3 if (p.Position_X == maze.Length - 1 && p.Position_Y == maze[maze.Length - 1].Length - 1) return true; 4 else return false; 5 }
Step 4:獲取候選點,並且把上一步走的點排除在候選點之外
1 public bool GetNextCandicates(Point p, int[][] maze, ref List<Point> nextp) 2 { 3 //如果上下左右的點是邊界上的點時,將其設為1,即為不可行 4 int up = p.Position_X - 1 > 0 ? maze[p.Position_X - 1][p.Position_Y] : 1; 5 int down = p.Position_X + 1 < maze[p.Position_X].Length ? maze[p.Position_X + 1][p.Position_Y] : 1; 6 int left = p.Position_Y - 1 > 0 ? maze[p.Position_X][p.Position_Y - 1] : 1; 7 int right = p.Position_Y + 1 < maze.Length ? maze[p.Position_X][p.Position_Y + 1] : 1; 8 if (up == 1 && down == 1 && left == 1 && right == 1) return false; //如果上下左右都不可行,返回false沒有候選點 9 else 10 { 11 if (right != 1) 12 { 13 Point Right = new Point(p.Position_X, p.Position_Y + 1); 14 if ((sureNow == null)|| (Right.Position_X != sureNow.Position_X || Right.Position_Y != sureNow.Position_Y)) 15 { 16 nextp.Add(Right); 17 } 18 } 19 if (down != 1) 20 { 21 Point Down = new Point(p.Position_X + 1, p.Position_Y); 22 if ((sureNow == null) || (Down.Position_X != sureNow.Position_X || Down.Position_Y != sureNow.Position_Y)) 23 { 24 nextp.Add(Down); 25 } 26 } 27 if (left != 1) 28 { 29 Point Left = new Point(p.Position_X, p.Position_Y - 1); 30 if ((sureNow == null) || (Left.Position_X != sureNow.Position_X || Left.Position_Y != sureNow.Position_Y)) 31 { 32 nextp.Add(Left); 33 } 34 } 35 if (up != 1) 36 { 37 Point Up = new Point(p.Position_X - 1, p.Position_Y); 38 if ((sureNow == null) || (Up.Position_X != sureNow.Position_X || Up.Position_Y != sureNow.Position_Y)) 39 { 40 nextp.Add(Up); 41 } 42 } 43 if (nextp.Count > 0) { return true; } 44 else return false; 45 } 46 }
Step 5 :處理一個錯誤的點
1 public bool DealWithWrongPoint (ref Point candicate) 2 { 3 bool isBreak = false; 4 way.Remove(sureNow); //刪除保存的路里面的這個點 5 candicates.Remove(candicates[candicates.Count - 1]); //刪除candates里面這個點的候選點 6 candicates[candicates.Count - 1].Remove(sureNow); //將這個點從上一個點的候選點里刪掉 7 sureNow = sureLast; 8 if (way.Count > 2) 9 { 10 sureLast = way[way.Count - 2]; 11 if (candicates[candicates.Count - 1].Count > 0) 12 { 13 notSureNext = candicates[candicates.Count - 1][0]; 14 candicate = notSureNext; 15 return false; 16 } 17 else DealWithWrongPoint(ref candicate); 18 } 19 else 20 { 21 Console.WriteLine("There is no way to exit!"); 22 isBreak = true; 23 } 24 return isBreak; 25 }
Step 6 :尋找通路
1 public void FindWay(Point candicate, int[][] maze) 2 { 3 while (!finish) 4 { 5 List<Point> nextp = new List<Point>(); 6 if (IsExit(candicate, maze)) 7 { 8 way.Add(candicate); 9 Console.WriteLine("Here you find the exit!"); 10 finish = true; 11 Print(maze); 12 break; 13 } 14 else 15 { 16 if (GetNextCandicates(candicate, maze, ref nextp))//如果有候選點 17 { 18 if (way.Count == 0) 19 { 20 //如果是起點,last和now不動 21 sureLast = new Point(0, 0); 22 sureNow = sureLast; 23 } 24 else if (way.Count == 1) 25 { 26 //如果是起點的下一個點,last不動 27 sureNow = candicate; 28 } 29 else 30 { 31 sureLast = sureNow; 32 sureNow = candicate; 33 } 34 way.Add(candicate); 35 notSureNext = nextp[0]; 36 candicates.Add(nextp); 37 //Console.WriteLine("last point is ({0},{1}) , now point is ({2},{3}) , next will try ({4},{5})", sureLast.Position_X, sureLast.Position_Y, sureNow.Position_X, sureNow.Position_Y, notSureNext.Position_X, notSureNext.Position_Y); 38 FindWay(notSureNext, maze); 39 } 40 else //沒有候選點 41 { 42 43 if (candicate.Position_X == 0 && candicate.Position_Y == 0)//如果當前點為起點且找不到下一個可行點 44 { 45 Console.WriteLine("There is no way to exit!"); 46 break; 47 } 48 else 49 { 50 candicates[candicates.Count - 1].Remove(candicate); 51 if (candicates[candicates.Count - 1].Count > 0)//如果sureNow還有候選的下一個點 52 { 53 notSureNext = candicates[way.IndexOf(sureNow)][0]; 54 FindWay(notSureNext, maze); 55 } 56 else //SureNow 沒有下一個候選點 57 { 58 if (DealWithWrongPoint(ref candicate)) 59 { 60 break; 61 } 62 else continue; 63 } 64 } 65 } 66 } 67 } 68 69 }
Step 7 :打印迷宮
1 public void Print(int[][] maze) 2 { 3 for (int i = 0; i <maze.Length; i++) 4 { 5 for (int j = 0; j < maze[maze.Length - 1].Length; j++) 6 { 7 if (way.Where(a => a.Position_X == i && a.Position_Y == j).ToList().Count > 0) 8 { 9 Console.Write("■"); 10 } 11 else Console.Write("O"); 12 } 13 Console.Write("\n"); 14 } 15 }
主函數,初始化迷宮獲取出路
1 static void Main(string[] args) 2 { 3 int[][] maze = new int[8][]; 4 maze[0] = new int[] { 0, 1, 0, 0, 1, 1, 1, 1 }; 5 maze[1] = new int[] { 0, 1, 1, 0, 1, 0, 0, 1 }; 6 maze[2] = new int[] { 0, 0, 0, 0, 1, 0, 1, 1 }; 7 maze[3] = new int[] { 1, 1, 0, 0, 0, 0, 1, 1 }; 8 maze[4] = new int[] { 1, 1, 1, 1, 0, 1, 1, 1 }; 9 maze[5] = new int[] { 1, 0, 1, 0, 0, 0, 0, 1 }; 10 maze[6] = new int[] { 1, 0, 0, 0, 1, 1, 0, 1 }; 11 maze[7] = new int[] { 1, 1, 1, 0, 1, 1, 0, 0 }; 12 Program pg = new Program(); 13 pg.FindWay(new Point(0, 0), maze); 14 Console.ReadKey(); 15 }
運行結果:
初始迷宮:
程序找到的路