面試題:尋找迷宮出口


題目:給出下面迷宮,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     }
View Code

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         }

運行結果:

初始迷宮:

   

程序找到的路 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM