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;
}

  

posted @ 2013-06-20 13:21  盗草人  阅读(1919)  评论(0编辑  收藏  举报