走迷宫

来源:互联网 发布:windows7查看mac地址 编辑:程序博客网 时间:2024/05/01 07:14

走迷宫

 

         2013年9月,在一次实验课上碰到了这个问题。迷宫是一个二维数组,用递归回溯走,小迷宫可以这样走,大迷宫这样走就不行了。能力有限,没用最短路径去做。

         结果截图:

 



代码如下:

//深度优先遍历(DFS)算法走迷宫。堆栈操作由操作系统完成,程序中不出现push()和pop()。//囧为要寻找的目的地,□为可行路径,■为不可行障碍(墙壁)。//找出迷宫中所有目的地囧和出口(即位于迷宫边缘的□)。#include <iostream>#include <conio.h>using namespace std;#define ROW 27 //迷宫行数,若修改下面矩阵则这里也要随之修改。#define RANK 39 //命令行窗口一行最多显示80个单字节字符,或20个双字节字符,故设置的迷宫列数最大只能到39。#define Dir_num 4 //4个方向,也是枚举类型Dir的模。#define ■ '0' //wall#define □ '1' //way#define 囧 'D' //destination#define ㊣ 'a' //reached destination//#define ⊙ 'T' //testing point#define ¤ 'e' //tested point#define ↑ 'u' //direction mark#define → 'r'#define ↓ 'd'#define ← 'l'#define └ '2' //turning point mark#define ┌ '3'#define ┐ '4'#define ┘ '5'char Puzzle[ROW][RANK] = {■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,  □,□,□,□,□,□,□,□,□,■,□,□,□,□,□,□,□,□,□,■,□,□,□,□,□,□,□,□,囧,■,□,□,□,□,□,□,□,□,□,  ■,■,■,■,□,□,■,□,□,■,■,■,□,■,□,□,■,□,□,■,■,■,□,■,□,□,■,□,□,■,■,■,□,■,□,□,■,□,■,  □,□,□,■,□,□,□,■,□,■,■,□,□,■,□,□,□,■,□,■,■,□,□,■,□,□,□,■,□,■,■,□,□,■,□,□,□,■,■,  ■,■,□,□,■,■,■,■,□,□,□,□,■,□,□,□,□,■,□,■,■,■,■,□,□,□,□,■,□,■,■,■,■,□,□,□,□,■,■,  ■,□,□,□,□,□,□,■,□,■,□,□,□,□,□,□,□,□,■,■,■,□,□,□,□,□,□,□,■,■,■,□,□,□,□,□,□,□,■,  ■,□,□,■,□,□,□,■,□,■,□,□,□,■,□,□,□,□,□,■,■,□,□,■,□,□,□,□,□,■,■,□,□,■,□,□,□,□,■,  ■,□,■,■,■,■,■,■,□,■,□,□,■,■,■,■,■,■,□,■,■,□,■,■,■,■,■,■,□,■,■,□,■,■,■,■,■,■,■,  ■,□,■,■,■,■,■,■,□,■,□,□,■,■,■,■,■,■,■,■,■,□,■,■,■,■,■,■,■,■,■,□,■,■,■,■,■,■,■,  ■,□,□,□,□,□,□,■,□,■,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,■,■,□,■,■,■,■,■,■,■,  ■,■,□,■,□,□,■,□,□,■,■,■,□,■,□,□,■,□,□,■,■,■,□,■,□,□,■,□,□,■,□,□,□,□,□,□,□,□,■,  ■,□,□,■,□,□,□,■,□,□,■,□,□,■,□,□,□,■,□,■,■,□,□,■,□,□,□,■,□,■,■,■,□,■,□,□,■,□,■,  ■,■,■,□,□,□,□,■,□,□,■,■,■,□,□,□,□,■,□,■,■,■,■,□,□,□,□,■,□,■,■,□,□,■,□,□,□,■,■,  ■,□,□,□,□,□,□,□,■,□,■,□,□,□,□,□,□,□,■,■,■,□,□,□,□,□,□,□,■,■,■,■,■,□,□,□,□,■,■,  ■,□,□,■,□,□,□,□,■,□,□,□,□,■,□,□,□,□,□,■,■,□,□,□,□,□,□,□,□,■,■,□,□,□,□,□,□,□,■,  ■,□,■,■,■,■,■,■,■,■,■,□,■,■,■,■,■,■,□,■,■,□,■,□,■,■,■,■,□,■,■,□,□,■,□,□,□,□,■,  ■,□,■,■,■,■,■,■,□,□,□,■,■,■,■,■,■,■,■,■,■,□,■,■,■,■,□,■,■,■,■,□,■,■,■,■,■,■,■,  ■,□,□,□,□,□,□,□,□,■,□,□,□,□,□,□,□,□,□,■,□,□,□,□,□,□,□,□,□,■,■,□,□,□,□,□,□,□,■,  ■,■,□,■,□,□,■,□,□,□,■,■,□,■,□,□,■,□,□,■,□,■,□,■,□,□,■,□,□,□,■,□,■,■,■,■,■,■,■,  ■,□,□,■,□,□,□,■,□,□,■,□,□,■,■,□,□,■,□,■,■,□,□,■,□,□,□,■,□,■,□,□,□,□,□,□,□,□,■,  ■,■,■,□,□,□,□,■,□,□,■,■,■,□,囧,■,□,■,□,■,□,■,■,□,□,□,□,■,□,■,■,■,□,■,□,□,■,□,■,  ■,□,□,□,□,□,□,□,■,□,■,□,□,□,□,■,□,□,■,■,□,□,□,□,□,□,□,□,■,■,□,□,□,■,□,□,□,■,■,  ■,□,□,■,□,□,□,□,□,□,■,□,□,■,□,□,□,□,□,■,□,□,□,■,□,□,□,□,□,■,■,■,■,□,□,□,□,■,■,  ■,□,□,■,□,□,□,■,□,■,■,□,■,■,■,■,■,■,□,■,□,□,■,□,□,■,■,■,■,□,□,□,□,□,□,□,□,□,■,  ■,□,■,■,■,■,■,■,■,■,■,□,□,□,□,□,□,□,■,■,□,□,■,■,■,■,□,□,■,□,■,□,□,■,□,□,□,□,□,  ■,□,■,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,□,■,□,■,■,■,■,■,■,■,  ■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■,■, };  //迷宫矩阵。int pos_row  = 1; //记录起点行位置。int pos_rank = 0; //记录起点列位置。enum Dir {U, R, D, L}; //用来索引方向数组的枚举值,只用来作为定位vec[4]数组的偏移值。Dir to;    //设这个变量只是为了减少重复计算,以及使vec[]的下标短一点。class Cod //Coordinate{public:int x;int y;Cod(int a=0, int b=0):x(a), y(b) {};}; const Cod vec[Dir_num] = {Cod(-1, 0), Cod(0, 1), Cod(1, 0), Cod(0, -1)}; //方向数组,可以用下标来控制移动方向。void display() //直观地输出当前路径。{int i, j;cout << '\n';for(i = 0; i < ROW; i++){ for(j = 0; j < RANK; j++) switch(Puzzle[i][j])   { //case ⊙:{ cout << "⊙"; break;};     case ■:{ cout << "■"; break;};     case □:{ cout << "  "; break;};     case 囧:{ cout << "囧"; break;};     case ㊣:{ cout << "囧"; break;};     case ¤:{ cout << "  "; break;};     case ↑:{ cout << "↑"; break;};     case →:{ cout << "→"; break;};     case ↓:{ cout << "↓"; break;};     case ←:{ cout << "←"; break;};  case └:{ cout << "└"; break;};  case ┌:{ cout << "┌"; break;};  case ┐:{ cout << "┐"; break;};  case ┘:{ cout << "┘"; break;};    default :{};   }; //switch  cout << '\n';}; //for(i)cout << endl;};void seek(const int& x,const int& y,const Dir& from) //递归函数。{//下面两个if为递归结束条件。if( ! ((x >= 0) && (x < ROW) && (y >= 0) && (y < RANK)))return; //下标越界,返回上级函数。if((Puzzle[x][y] != 囧) && (Puzzle[x][y] != □))return; //只要遇到不是目的地囧或可行位置□,便返回上级函数。//下面这个if为找到目的地(囧)或遇到出口(位于迷宫边缘的□)时的提示。if(Puzzle[x][y] == 囧){ Puzzle[x][y] = ㊣; //这里标记一下纯粹是因为接下来要display(),不然就不能画出当前找到的目的地囧。  cout << '\n' <<"----------------------------------------------------------------------------" << '\n';  cout << '(' << x << ',' << y << ')' <<"is a destination." << endl;      display();  cout << "按任意键继续走...";  _getch();}else if((Puzzle[x][y] == □) && ((x == 0) || (x == ROW-1) || (y == 0) || (y == RANK-1)) && ((x != pos_row) || (y != pos_rank))){ switch(from)  //同上,为画出当前出口。{ case U:{ Puzzle[x][y] = ↓; break; };          case R:{ Puzzle[x][y] = ←; break; };          case D:{ Puzzle[x][y] = ↑; break; };          case L:{ Puzzle[x][y] = →; break; };  default:{};        }; //switch  cout << '\n' <<"----------------------------------------------------------------------------" << '\n';  cout << "An exit found:" << '(' << x << ',' << y << ")." <<endl;  display();  cout << "按任意键继续走...";  _getch();};//搜索当前位置上的除from方向的三个方向的格子,并按方向标记当前位置。to = Dir((from + 2) % Dir_num);if(Puzzle[x][y] != ㊣)switch(from){ case U:{ Puzzle[x][y] = ↓; break; };  case R:{ Puzzle[x][y] = ←; break; };  case D:{ Puzzle[x][y] = ↑; break; };  case L:{ Puzzle[x][y] = →; break; };  default:{};}; //switchseek(x + vec[to].x, y + vec[to].y, Dir((to + 2) % Dir_num)); //搜寻from方向的【对侧】方向的格子。to = Dir((from + 1) % Dir_num);if(Puzzle[x][y] != ㊣)switch(from){ case U:{ Puzzle[x][y] = └; break; };  case R:{ Puzzle[x][y] = ┌; break; };  case D:{ Puzzle[x][y] = ┐; break; };  case L:{ Puzzle[x][y] = ┘; break; };  default:{};}; //switchseek(x + vec[to].x, y + vec[to].y, Dir((to + 2) % Dir_num)); //搜寻from方向的【后续】方向的格子。第三个参数是避免递归函数回头又搜寻来时的方向,下同。to = Dir((from + 3) % Dir_num);if(Puzzle[x][y] != ㊣)switch(from){ case U:{ Puzzle[x][y] = ┘; break; };  case R:{ Puzzle[x][y] = └; break; };  case D:{ Puzzle[x][y] = ┌; break; };  case L:{ Puzzle[x][y] = ┐; break; };  default:{};}; //switchseek(x + vec[to].x, y + vec[to].y, Dir((to + 2) % Dir_num)); //搜寻from方向的【前驱】方向的格子。if(Puzzle[x][y] != ㊣) //对已遍历完三个方向的位置,标记为已遍历完(¤),以免重复检查该位置。Puzzle[x][y] = ¤;};void main(){display();seek(pos_row, pos_rank, R);if(Puzzle[pos_row][pos_rank] == ㊣) //如果上一个seek()因为方向不对而不能继续遍历迷宫,则肯定会改变入口位置的状态,为了使接下来按反方向遍历的seek()顺利遍历,需把入口位置变回原来状态。Puzzle[pos_row][pos_rank] = 囧;else if(Puzzle[pos_row][pos_rank] == ¤)Puzzle[pos_row][pos_rank] = □;seek(pos_row, pos_rank, L); //为了防止上面的seek()因为方向不对而不能继续遍历,这里按反方向遍历。cout << '\n' << "终于走完了~~" << '\n' << endl;} //main()


0 0
原创粉丝点击