C++数据结构大作业之用并查集随机生成迷宫及深搜深宫路径
头文件Maze.h
#include<iostream> #include <ctime> #ifndef MAZE_H #define MAZE_H const char resultSymbol = '#'; const char wallSymbolH = '-'; const char wallSymbolV = '|'; const char wallCorner = '+'; const char roomSymbol = ' '; class Maze { public: char **maze; //迷宫动态二维数组 int row; //迷宫动态二维数组一行的长度 int column; //迷宫动态二维数组一列的长度 int *unionFindSet; //生成迷宫用的并查集 int UFSLength; //并查集的长度,也是房间的总个数 Maze(int row, int column); //构造函数 ~Maze(); //析构函数 void initMaze(int row, int column, char**& maze); //初始化迷宫 void makeMaze(char**& maze); //随机首先迷宫 void solveMaze(char**& maze); //解决迷宫 void solveMazeSecond(char**& maze); //解决迷宫 int DFAlgorithm(char**& maze, int i, int j, char& step); //深搜算法用于生成的搜索步骤 int DFAlgorithmSecond(char**& maze, int i, int j, char& step); //深搜算法用于生成第二个迷宫的解法 void initUnionFindSet(int*& unionFindSet); //初始化并查集 int mazeAdapter(int i_column, int j_row); //把二维数组“房间”下标转为适合并查集的下标 int findSet(int x); //并查集:查找集合 void uionSet(int x, int y); //并查集:合并集合 bool isJioned(int x, int y); //判断两个集合(元素、点)是否连通 void printMaze(char** maze); //打印迷宫 void printOriginalMaze(); //打印原始迷宫 void printResultOfMaze(); //打印迷宫走法 void printStepOfMaze(); //打印迷宫步骤 void printUnionFindSet(); //打印并查集 void reStore(char**& maze); //恢复原始迷宫 static void test(); //用于测试迷宫算法 }; #endif
函数实现文件Maze.cpp
#include "Maze.h" using namespace std; Maze::Maze(int pRow, int pColumn) { row = 2*pRow + 1; column = 2*pColumn + 1; UFSLength = pRow * pColumn; initMaze(pRow, pColumn, maze); initUnionFindSet(unionFindSet); makeMaze(maze); cout<<"迷宫矩阵初始化完成"<<endl; } Maze::~Maze() { for (int i = 0; i < column; i++) delete[] maze[i]; delete[] maze; maze = NULL; delete unionFindSet; unionFindSet = NULL; } void Maze::initMaze(int row, int column, char**& maze) { int realRow = 2*row + 1; int realColumn = 2*column + 1; maze = new char*[realColumn]; for (int i = 0; i < realColumn; i++) { maze[i] = new char[realRow]; } //初始化原始迷宫布局 for (int i = 0; i < realColumn; i++) { for (int j = 0; j < realRow; j++) { if (i%2==0 && j%2==0) { maze[i][j] = wallCorner; } else if (i%2==0 && j%2==1) { maze[i][j] = wallSymbolH; } else if (i%2==1 && j%2==0) { maze[i][j] = wallSymbolV; } else { maze[i][j] = roomSymbol; } } } maze[0][1] = roomSymbol; maze[realColumn - 1][realRow - 2] = roomSymbol; } void Maze::initUnionFindSet(int*& unionFindSet) { unionFindSet = new int[UFSLength]; for (int i = 0; i < UFSLength; i++) { unionFindSet[i] = i; } } void Maze::makeMaze(char**& maze) { srand((unsigned)time(0)); while (!isJioned(mazeAdapter(1,1), mazeAdapter(column-2, row-2)))//起点和终点不连通 { int i = rand()%(column-1); int j = rand()%(row-1); if (i != 0 && i != column && j != 0 && j != row) // 非边界墙 { if ((i%2 != 1 && j%2 != 0))//遇到“墙”:"|" { // cout<<"遇到“墙”:\"|\""<<endl; uionSet(mazeAdapter(i-1,j), mazeAdapter(i+1, j)); maze[i][j] = roomSymbol; } else if ((i%2 != 0 && j%2 != 1))//遇到“墙”:"-" { // cout<<"遇到“墙”:\"-\""<<endl; uionSet(mazeAdapter(i,j-1), mazeAdapter(i, j+1)); maze[i][j] = roomSymbol; } } } } void Maze::solveMaze(char**& maze) { reStore(maze); int i = 1; int j = 1; char step = '0'; DFAlgorithm(maze, i, j, step); cout<<endl; } void Maze::solveMazeSecond(char**& maze) { reStore(maze); int i = 1; int j = 1; char step = resultSymbol; DFAlgorithmSecond(maze, i, j, step); maze[i][j] = step; maze[i-1][j] = step; maze[column-1][row-2] = step; for (int i = 0; i < column; i++) { for (int j = 0; j < row; j++) { if ((i%2 == 1 && j%2 == 1) && maze[i][j] == '$') { maze[i][j] = roomSymbol; } } } cout<<endl; } int Maze::DFAlgorithm(char**& maze, int i, int j, char& step) { maze[i][j] = step; if (step == '9') step = '0'; else step++; if ((i == column - 2) && (j == row - 2)) return 1; else { if (maze[i][j-1] == roomSymbol && maze[i][j-2] == roomSymbol && DFAlgorithm(maze, i, j-2, step))//left return 1; if (maze[i+1][j] == roomSymbol && maze[i+2][j] == roomSymbol && DFAlgorithm(maze, i+2, j, step))//down return 1; if (maze[i][j+1] == roomSymbol && maze[i][j+2] == roomSymbol && DFAlgorithm(maze, i, j+2, step))//right return 1; if (maze[i-1][j] == roomSymbol && (i != 1 && j!= 1) && maze[i-2][j] == roomSymbol && DFAlgorithm(maze, i-2, j, step))//up return 1; } return 0; } int Maze::DFAlgorithmSecond(char**& maze, int i, int j, char& step) { maze[i][j] = '$'; if ((i == column - 2) && (j == row - 2)) { maze[i][j] = step; return 1; } else { if (maze[i][j-1] == roomSymbol && maze[i][j-2] == roomSymbol && DFAlgorithmSecond(maze, i, j-2, step))//left { maze[i][j-1] = step; maze[i][j-2] = step; return 1; } if (maze[i+1][j] == roomSymbol && maze[i+2][j] == roomSymbol && DFAlgorithmSecond(maze, i+2, j, step))//down { maze[i+1][j] = step; maze[i+2][j] = step; return 1; } if (maze[i][j+1] == roomSymbol && maze[i][j+2] == roomSymbol && DFAlgorithmSecond(maze, i, j+2, step))//right { maze[i][j+1] = step; maze[i][j+2] = step; return 1; } if (maze[i-1][j] == roomSymbol && (i != 1 && j!= 1) && maze[i-2][j] == roomSymbol && DFAlgorithmSecond(maze, i-2, j, step))//up { maze[i-1][j] = step; maze[i-2][j] = step; return 1; } } return 0; } int Maze::mazeAdapter(int i_column, int j_row) { return (row - 1)/2 * ((i_column+1)/2 - 1) + ((j_row+1)/2 -1); } int Maze::findSet(int x) { //查找根结点 int r = x; while (r != unionFindSet[r]) r = unionFindSet[r]; //路径压缩 int i = x; int j; while (i != r) { j = unionFindSet[i]; unionFindSet[i] = r; i = j; } //返回根结点 return r; } void Maze::uionSet(int x, int y) { //查找x和y的父结点 int fx = findSet(x), fy = findSet(y); if (fx != fy)//如果x和y的父结点不相同 unionFindSet[fx] = fy; } bool Maze::isJioned(int x, int y) { //查找x和y的父结点 int fx = findSet(x), fy = findSet(y); // cout<<"fx:"<<fx<<" fy:"<<fy<<endl; if (fx == fy)//如果x和y的父结点不相同 return true; else return false; } void Maze::printMaze(char** maze) { for (int i = 0; i < column; i++) { for (int j = 0; j < row; j++) { cout<<maze[i][j]; } cout<<endl; } } void Maze::printOriginalMaze() { reStore(maze); printMaze(maze); } void Maze::printResultOfMaze() { solveMazeSecond(maze); printMaze(maze); } void Maze::printStepOfMaze() { solveMaze(maze); printMaze(maze); } void Maze::printUnionFindSet() { for (int i = 0; i < UFSLength; i++) { cout<<unionFindSet[i]<<" "; } cout<<endl; } void Maze::reStore(char**& maze) { for (int i = 0; i < column; i++) { for (int j = 0; j < row; j++) { if ((maze[i][j] != wallCorner) && (maze[i][j] != wallSymbolH) && (maze[i][j] != wallSymbolV)) { maze[i][j] = roomSymbol; } } } } void Maze::test() { int row; int column; cout<<"欢迎进入迷宫游戏!"<<endl; cout<<"请在下面输入想要挑战的迷宫的宽度和高度"<<endl; cout<<"请输入想要挑战的迷宫的宽度:"<<endl; while (cin>>row) { if (row < 1) cout<<"输入错误,请重新输入想要挑战的迷宫的宽度:"<<endl; else break; } cout<<"请输入想要挑战的迷宫的高度:"<<endl; while (cin>>column) { if (column < 1) cout<<"输入错误,请重新输入想要挑战的迷宫的高度:"<<endl; else break; } Maze *maze = new Maze(row, column); maze->printOriginalMaze(); cout<<endl<<"下面是迷宫解法:"<<endl; maze->printResultOfMaze(); cout<<endl<<"下面是迷宫搜索步骤:"<<endl; maze->printStepOfMaze(); }
最后一个是main.cpp
#include "Maze.h" using namespace std; int main() { Maze::test(); return 0; }