迷宫寻径--试探回溯法

空间区域限定为由n* n个方格组成的迷宫,除了四周的围墙,还有分布其间的若干障碍物;只能水平或垂直移动。我们的任务是,在任意指定的起始格点与目标格点之间,找出一条通路(如果的确存在)。

 1 #pragma once
 2 #define LABY_MAX 24 //最大迷宫尺寸
 3 typedef enum
 4 {
 5     AVAILABLE, //原始可用
 6     ROUTE, //当前路径上的
 7     BACKTRACKED, //所有方向均尝试失败后回溯过的
 8     WALL //
 9 }Status; //迷宫单元格状态
10 typedef enum
11 {
12     UNKNOWN,
13     EAST,
14     SOUTH,
15     WEST,
16     NORTH,
17     NO_WAY
18 }ESWN;
19 
20 struct Cell
21 {
22     int x;
23     int y;
24     Status status;
25     ESWN incoming, outgoing; //进入走出方向
26 };
27 
28 inline ESWN nextESWN(ESWN eswn) { return ESWN(eswn + 1); } //依次转至下一邻接方向
29 
30 inline Cell* neighbor(Cell* cell) { //查询当前位置的相邻格点
31     switch (cell->outgoing) {
32     case EAST: return cell + LABY_MAX; //向东
33     case SOUTH: return cell + 1;        //向南
34     case WEST: return cell - LABY_MAX; //向西
35     case NORTH: return cell - 1;        //向北
36     }
37 }
38 
39 inline Cell* advance(Cell* cell) //从当前位置转入相邻格点
40 { 
41     Cell* next;
42     switch (cell->outgoing) 
43     {
44         case EAST:  next = cell + LABY_MAX; next->incoming = WEST;  break; //向东
45         case SOUTH: next = cell + 1;        next->incoming = NORTH; break; //向南
46         case WEST:  next = cell - LABY_MAX; next->incoming = EAST;  break; //向西
47         case NORTH: next = cell - 1;        next->incoming = SOUTH; break; //向北
48         default:
49             next = nullptr;
50     }
51     return next;
52 }
  1 #include <random>
  2 #include <stack>
  3 #include "Cell.h"
  4 using namespace std;
  5 
  6 
  7 
  8 int labySize;
  9 Cell* startCell;
 10 Cell* goalCell;
 11 Cell laby[LABY_MAX][LABY_MAX]; //迷宫
 12 
 13 void randLaby();
 14 void displayLaby();
 15 void printLabyCell(Cell* elem);
 16 bool labyrinth(Cell Laby[LABY_MAX][LABY_MAX], Cell* s, Cell* t);
 17 
 18 int main()
 19 {
 20     randLaby();
 21     labyrinth(laby, startCell, goalCell) ? //启动算法
 22         printf("\nRoute found\a\n") :
 23         printf("\nNo route found\a\n");
 24     getchar();
 25     return 0;
 26 }
 27 
 28 bool labyrinth(Cell Laby[LABY_MAX][LABY_MAX], Cell* s, Cell* t)//迷宫寻径算法,在起点s和终点t之间寻找一条通路
 29 {
 30     if ((s->status != AVAILABLE) || (t->status != AVAILABLE)) return false;
 31     stack<Cell*> path; //使用栈记录通路
 32     s->incoming = UNKNOWN; s->status = ROUTE;
 33     path.push(s);
 34     do  //从起点出发不断试探、回溯,直到抵达终点,或者穷尽所有可能
 35     {
 36         displayLaby();
 37         getchar();
 38         Cell* c = path.top();
 39         if (c == t) return true; //抵达终点
 40         while (NO_WAY>(c->outgoing= nextESWN(c->outgoing)))
 41         {
 42             Cell* neighborCell = neighbor(c);
 43             if (neighborCell->status == AVAILABLE) break;;
 44         }
 45         if (c->outgoing >= NO_WAY)
 46         {
 47             c->status = BACKTRACKED;
 48             c = path.top(); path.pop(); //回溯一步
 49         }
 50         else //向前试探一步
 51         {
 52             c = advance(c);
 53             path.push(c);
 54             c->outgoing = UNKNOWN;
 55             c->status = ROUTE;
 56         }
 57     } while (!path.empty());
 58     return false;
 59 }
 60 void randLaby() { //生成随机的迷宫
 61     labySize = LABY_MAX / 2 + rand() % (LABY_MAX / 2); /*DSA*/printf("Using a laby of size %d ...\n", labySize); getchar();
 62     for (int i = 0; i < labySize; i++)
 63         for (int j = 0; j < labySize; j++) {
 64             laby[i][j].x = i;
 65             laby[i][j].y = j;
 66             laby[i][j].incoming =
 67                 laby[i][j].outgoing = UNKNOWN;
 68             laby[i][j].status = WALL; //边界格点必须是墙
 69         }
 70     for (int i = 1; i < labySize - 1; i++)
 71         for (int j = 1; j < labySize - 1; j++)
 72             if (rand() % 4) laby[i][j].status = AVAILABLE; //75%的格点为空可用
 73     startCell = &laby[rand() % (labySize - 2) + 1][rand() % (labySize - 2) + 1];
 74     goalCell = &laby[rand() % (labySize - 2) + 1][rand() % (labySize - 2) + 1];
 75     startCell->status = goalCell->status = AVAILABLE; //起始格点必须可用
 76 }
 77 /******************************************************************************************
 78 *   输出某一迷宫格的信息
 79 ******************************************************************************************/
 80 void printLabyCell(Cell* elem) {
 81     printf("%d -> (%d, %d) -> %d\n",
 82         ((Cell*)elem)->incoming,
 83         ((Cell*)elem)->x,
 84         ((Cell*)elem)->y,
 85         ((Cell*)elem)->outgoing);
 86 }
 87 
 88 /******************************************************************************************
 89 * 显示迷宫
 90 ******************************************************************************************/
 91 void displayLaby() { //┘└┐┌│─
 92     static char*   pattern[5][5] = {
 93         "", "", "", "", "",
 94         "", "  ", "", "", "",
 95         "", "", "  ", "", "",
 96         "", "", "", "  ", "",
 97         "", "", "", "", "  "
 98     };
 99     system("cls");
100     printf("  ");
101     for (int j = 0; j < labySize; j++)
102         (j < 10) ? printf("%2X", j) : printf(" %c", 'A' - 10 + j);
103     printf("\n");
104     for (int j = 0; j < labySize; j++) {
105         (j < 10) ? printf("%2X", j) : printf(" %c", 'A' - 10 + j);
106         for (int i = 0; i < labySize; i++)
107             if (goalCell == &laby[i][j])
108                 printf("");
109             else
110                 switch (laby[i][j].status) {
111                 case WALL:  printf("");   break;
112                 case BACKTRACKED: printf("");   break;
113                 case AVAILABLE: printf("  ");   break;
114                 default: printf("%s", pattern[laby[i][j].outgoing][laby[i][j].incoming]);   break;
115                 }
116         printf("\n");
117     }//for
118 }//displayLaby

 

猜你喜欢

转载自www.cnblogs.com/larry-xia/p/10391673.html