空间区域限定为由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