zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    Iterator迭代器与增强for循环
    java中的集合
    基本类型包装类、System类
    java之Calendar类
    java二维数组
    java学习之字符串缓冲区
    java学习之内部类、包与代码块
    DataGridView列增加单选按钮、输入框
    DataGridView加上默认的序号
    数据结构简介
  • 原文地址:https://www.cnblogs.com/daocaowu/p/3145813.html
Copyright © 2011-2022 走看看