迷宫生成算法(三)(C++)

三、最小生成树算法之Kruskal算法

        数据结构中的Kruskal算法:将每个顶点视为一棵树,将所有边加入集合,从边的集合中依次选择权最小的边,如果该边两端的顶点属于不同的树,将两棵树合并,并把这条边记录在一个新的集合中;如果两端顶点属于一棵树,舍弃这条边,如此循环直到新集合中边的数量等于顶点数量-1

        迷宫算法中由于所有边的权相等,且需要随机性,所以与数据结构中的Kruskal算法有较大的不同:

        将每个顶点视为一棵树,将所有边加入集合,从边的集合中随机选择一条边,如果该边两端的顶点属于不同的树,将两棵树合并,将这条边移除集合,如果属于相同树,直接舍弃这条边,直到边的集合为空,即所有边都被访问过,结束构造

效果如图

 

        此算法与前两个不同,此算法是面向边来构造迷宫,而前两个是面向顶点构造迷宫。

        由于树的合并问题,我们需要加入并查集这一概念,即在顶点类中加入一个root指针指向它的父顶点,如果root为空说明该顶点是根,合并树就是让其中一棵树根的root指向另一棵树的根。

class Map
{
public:
	int val;//对访问过的顶点进行标记
	int x;//坐标
	int y;
	vector<Map*>next;//存放相连顶点
	Map*root;//指向父顶点
	Map()
	{
		root = NULL;
		val = 0;
		x = 0;
		y = 0;
	}

	Map(int c, int r)
	{
		root = NULL;
		val = 0;
		x = c;
		y = r;
	}

	void push(Map* m)
	{
		next.push_back(m);
	}

	void erase(Map* m)
	{
		for (auto it = next.begin(); it != next.end(); it++)
		{
			if ((*it)->x == m->x&&(*it)->y == m->y)
			{
				next.erase(it);
			}

		}
	}
};

由于要面向边构造迷宫,还需要加入边类

class Side
{
public:
	Map*first;
	Map*second;//两端的顶点

	Side()
	{
		first = NULL;
		second = NULL;
	}

	Side(Map*m1, Map*m2)
	{
		first = m1;
		second = m2;
	}
};

Kruskal算法函数

void Kruskal()
{
	vector<Side>Lib;//把所有边加入容器

	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL - 1; j++)
		{
			Lib.push_back(Side(map[j][i], map[j + 1][i]));
		}
	}
	for (int i = 0; i < COL; i++)
	{
		for (int j = 0; j < ROW - 1; j++)
		{
			Lib.push_back(Side(map[i][j], map[i][j + 1]));
		}
	}

	while (!Lib.empty())//所有边都访问过就结束构造
	{
		Sleep(0);
		int select = rand() % Lib.size();随机选择一条边
		Map*temp1 = Lib[select].first;//用两个临时指针找两端点分属哪个根
		Map*temp2 = Lib[select].second;

		while (temp1->root != NULL)
		{
			temp1 = temp1->root;
		}

		while (temp2->root != NULL)
		{
			temp2 = temp2->root;
		}

		if (temp1->x == temp2->x && temp1->y == temp2->y)//根相同即树相同,将这条边移出容器
		{
			Lib.erase(Lib.begin() + select);
		}
		else
		{
			temp1->root = temp2;//根不同就合并两棵树
			Lib[select].first->push(Lib[select].second);
			Lib[select].second->push(Lib[select].first);//将自己加入对方的相连容器中
			int x = Lib[select].first->x;
			int y = Lib[select].first->y;
			int x2 = Lib[select].second->x;
			int y2 = Lib[select].second->y;
            //以下代码根据两顶点的相对位置移除它们之间的墙
			if (y - 1 == y2)
			{
				solidrectangle(x*(RODE + WALL) - RODE / 2, y*(RODE + WALL) - RODE / 2 - WALL, x*(RODE + WALL) + RODE / 2, y*(RODE + WALL) - RODE / 2);
			}
			else if(y + 1 == y2)
			{
				solidrectangle(x*(RODE + WALL) - RODE / 2, y*(RODE + WALL) + RODE / 2, x*(RODE + WALL) + RODE / 2, y*(RODE + WALL) + RODE / 2 + WALL);
			}
			else if (x - 1 == x2)
			{
				solidrectangle(x*(RODE + WALL) - RODE / 2 - WALL, y*(RODE + WALL) - RODE / 2, x*(RODE + WALL) - RODE / 2, y*(RODE + WALL) + RODE / 2);
			}
			else if (x + 1 == x2)
			{
				solidrectangle(x*(RODE + WALL) + RODE / 2, y*(RODE + WALL) - RODE / 2, x*(RODE + WALL) + RODE / 2 + WALL, y*(RODE + WALL) + RODE / 2);
			}

			Lib.erase(Lib.begin() + select);//这条边已访问过了,移除它
		}
	}

}

寻路效果如图

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
迷宫的随机生成算法有多种方法,其中一个常见的方法是使用深度优先搜索(DFS)算法。下面是一个使用C++实现的迷宫随机生成算法的示例: ```cpp #include <iostream> #include <vector> #include <stack> #include <random> using namespace std; // 迷宫的大小(假设为正方形) const int SIZE = 10; // 迷宫格子的状态 enum class CellState { Wall, Path }; // 迷宫格子的结构体 struct Cell { int row, col; CellState state; Cell(int r, int c, CellState s) : row(r), col(c), state(s) {} }; // 获取一个随机数 int getRandomInt(int min, int max) { static random_device rd; static mt19937 gen(rd()); uniform_int_distribution<> dis(min, max); return dis(gen); } // 初始化迷宫 void initializeMaze(vector<vector<Cell>>& maze) { for (int i = 0; i < SIZE; ++i) { maze.push_back(vector<Cell>()); for (int j = 0; j < SIZE; ++j) { maze[i].push_back(Cell(i, j, CellState::Wall)); } } } // 判断一个格子是否在迷宫的边界内 bool isInBounds(int row, int col) { return row >= 0 && row < SIZE && col >= 0 && col < SIZE; } // 获取一个格子的邻居格子 vector<Cell*> getNeighbors(const Cell& cell, const vector<vector<Cell>>& maze) { vector<Cell*> neighbors; // 上 if (isInBounds(cell.row - 1, cell.col)) { neighbors.push_back(&maze[cell.row - 1][cell.col]); } // 下 if (isInBounds(cell.row + 1, cell.col)) { neighbors.push_back(&maze[cell.row + 1][cell.col]); } // 左 if (isInBounds(cell.row, cell.col - 1)) { neighbors.push_back(&maze[cell.row][cell.col - 1]); } // 右 if (isInBounds(cell.row, cell.col + 1)) { neighbors.push_back(&maze[cell.row][cell.col + 1]); } return neighbors; } // 使用深度优先搜索算法随机生成迷宫 void generateMaze(vector<vector<Cell>>& maze) { stack<Cell*> stack; Cell* current = &maze[0][0]; current->state = CellState::Path; do { vector<Cell*> unvisitedNeighbors; vector<Cell*> neighbors = getNeighbors(*current, maze); // 寻找未访问的邻居 for (Cell* neighbor : neighbors) { if (neighbor->state == CellState::Wall) { unvisitedNeighbors.push_back(neighbor); } } if (!unvisitedNeighbors.empty()) { // 随机选择一个未访问的邻居 int randomIndex = getRandomInt(0, unvisitedNeighbors.size() - 1); Cell* next = unvisitedNeighbors[randomIndex]; // 打开墙,连接当前格子和下一个格子 int wallRow = (current->row + next->row) / 2; int wallCol = (current->col + next->col) / 2; maze[wallRow][wallCol].state = CellState::Path; next->state = CellState::Path; stack.push(current); current = next; } else if (!stack.empty()) { current = stack.top(); stack.pop(); } } while (!stack.empty()); } // 打印迷宫 void printMaze(const vector<vector<Cell>>& maze) { for (int i = 0; i < SIZE; ++i) { for (int j = 0; j < SIZE; ++j) { if (maze[i][j].state == CellState::Wall) { cout << "■ "; } else { cout << " "; } } cout << endl; } } int main() { vector<vector<Cell>> maze; initializeMaze(maze); generateMaze(maze); printMaze(maze); return 0; } ``` 此示例使用深度优先搜索算法随机生成迷宫。它首先初始化一个大小为SIZE的迷宫,然后从起点开始,不断选择一个未访问的邻居格子,打开墙,连接两个格子,直到无法继续前进或者所有格子都被访问过为止。最终打印出生成迷宫。注意,此示例中迷宫的大小为10x10,你可以根据需要调整SIZE的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值