实现Kruskal算法连通游戏地图地牢

前置知识 

c分享|并查集从入门到出门 - 力扣(LeetCode)

 彻底搞懂克鲁斯卡尔(Kruskal)算法(附C++代码实现) - QuanHa - 博客园 (cnblogs.com)

 

白色点矩形是地牢,其中白线是按照krsukal算法连接的画总长最短的线连出来的路径

 

 

 

其中关键算法

#include <stdio.h>

#define MAX_VEX 12
#define MAX_EDGE 144

typedef struct edge {
	int startpoint;							// 起点在数组中的序号
	int endpoint;							// 终点在数组中的序号
	int weight;
} edge;

typedef struct link {
	int startx;									// 起点的坐标
	int starty;
	int endx;									// 终点的坐标
	int endy;
	int used;									// 是否已经使用
	int lenth;									// 距离
	edge edgelink;
} link;

typedef struct target {
	int targeti = 0;							// 左上角网格坐标
	int targetj = 0;
	int targetwidth = 0;						// 长宽
	int targetheight = 0;
	int islive = 0;

//	RenderTexture2D* picture;					// 敌人贴图
//	RenderTexture2D picture;					// 敌人贴图

	int** oldmap;								// 局部复原数据

	int** mapv3;								// 像素也当成网格,每个记录像素是否能穿过

	target* area;								// 敌人内部的点

	int arealenth;								// 用于记录范围,lenth是半径
} target;



int find_root(int roots[], int n) {
	while (roots[n] != -1) {
		n = roots[n];
	}
	return n;
}




int main() {

	
	link linkside[12][12];			// 兼容之前参数


	int vex = 12;					//顶点个数
	int edgeside = 12 * 12;			//边个数

	link graph[MAX_EDGE];
	edge graphv2[MAX_EDGE];

//
//	for (int k = 0; k < edgeside; k++) {
//		for (int n = 0; n <= 11; n++) {
//			for (int m = 0; m <= 11; m++) {
//				if (linkside[n][m].used == 0) {
//					graph[k].startx = linkside[n][m].startx;
//					graph[k].starty = linkside[n][m].starty;
//					graph[k].endx = linkside[n][m].endx;
//					graph[k].endy = linkside[n][m].endy;
//					graph[k].lenth = linkside[n][m].lenth;
//					graph[k].used = 1;
//
//					graphv2[k].startpoint=n;
//					graphv2[k].endpoint=m;
//					graph[k].lenth=linkside[n][m].lenth;
//				}
//			}
//		}
//	}


	for (int n = 0; n < 144; n++) {
		graph[n].used = 0;
	}

	int k = 0;
	for (int n = 0; n <= 11; n++) {
		for (int m = 0; m <= 11; m++) {
			if (linkside[n][m].used == 0) {

				graph[k].startx = linkside[n][m].startx;
				graph[k].starty = linkside[n][m].starty;
				graph[k].endx = linkside[n][m].endx;
				graph[k].endy = linkside[n][m].endy;
				graph[k].lenth = linkside[n][m].lenth;
				graph[k].used = 1;

				graph[k].edgelink.startpoint = n;
				graph[k].edgelink.endpoint = m;
				graph[k].edgelink.weight = linkside[n][m].lenth;
				k++;
			}
		}
	}

//	标记不用数据
	for (int n = 0; n < 144; n++) {
		if (graph[n].used == 0) {
			graph[n].lenth = 999999;
			graph[n].edgelink.weight = 999999;
		}
	}

	// 插入排序
	link max;
	int index;
	for (int n = 0; n < 144; n++) {
		index = n;
		max = graph[n];
		for (int m = n + 1; m < 144; m++) {
			if (graph[m].lenth < max.lenth) {
				max = graph[m];
				index = m;
			}
		}
		graph[index] = graph[n];
		graph[n] = max;
	}


	int roots[MAX_VEX];  	//根数组,存放各顶点的根节点,以区别是否属于同一个集合
	edge MST[MAX_EDGE];		//存放最小生成树(minimum spanning tree)
	int count = 0;


	for (int n = 0; n < MAX_VEX; n++) {
		roots[n] = -1;
	}


//	for (int n = 0; n < MAX_EDGE; n++) {
//
//	}

	for (int n = 0; n < MAX_EDGE; n++) {

		if (graph[n].used == 1) {
			int vex_m = find_root(roots, graph[n].edgelink.startpoint);
			int vex_n = find_root(roots, graph[n].edgelink.endpoint);
			if (vex_m != vex_n) {				//如果两者的根节点不同,说明他们属于不同的集合,可以相连
				MST[count] = graph[n].edgelink;//将此边放入MST数组
				count++;
				roots[vex_m] = vex_n;			//将两个树合并,即将顶点vex_n作为vex_m的根节点

			}
			if (count == vex - 1) {
				break;
			}

		}

	}
	
	for (int i = 0; i < vex - 1; i++)
	{
		printf("(%d,%d)%d\n", MST[i].startpoint, MST[i].endpoint, MST[i].weight);   //打印最小生成树
	}
	
	
	return 0;
}
	int vex = 12;					//顶点个数
		int edgeside = 12 * 12;			//边个数

		link graph[MAX_EDGE];
		edge graphv2[MAX_EDGE];

		/*
		//	for (int k = 0; k < edgeside; k++) {
		//		for (int n = 0; n <= 11; n++) {
		//			for (int m = 0; m <= 11; m++) {
		//				if (linkside[n][m].used == 0) {
		//					graph[k].startx = linkside[n][m].startx;
		//					graph[k].starty = linkside[n][m].starty;
		//					graph[k].endx = linkside[n][m].endx;
		//					graph[k].endy = linkside[n][m].endy;
		//					graph[k].lenth = linkside[n][m].lenth;
		//					graph[k].used = 1;
		//
		//					graphv2[k].startpoint=n;
		//					graphv2[k].endpoint=m;
		//					graph[k].lenth=linkside[n][m].lenth;
		//				}
		//			}
		//		}
		//	}
		*/

		for (int n = 0; n < 144; n++) {
			graph[n].used = 0;
		}
//
		int k = 0;
		for (int n = 0; n <= 11; n++) {
			for (int m = 0; m <= 11; m++) {
				if (linkside[n][m].used == 0) {

					graph[k].startx = linkside[n][m].startx;
					graph[k].starty = linkside[n][m].starty;
					graph[k].endx = linkside[n][m].endx;
					graph[k].endy = linkside[n][m].endy;
					graph[k].lenth = linkside[n][m].lenth;
					graph[k].used = 1;

					graph[k].edgelink.startpoint = n;
					graph[k].edgelink.endpoint = m;
					graph[k].edgelink.weight = linkside[n][m].lenth;
					k++;
				}
			}
		}

//	标记不用数据
		for (int n = 0; n < MAX_EDGE; n++) {
			if (graph[n].used == 0) {
				graph[n].lenth = 999999;
				graph[n].edgelink.weight = 999999;
			}
		}

		// 插入排序
		link max;
		int index;
		for (int n = 0; n < MAX_EDGE; n++) {
			index = n;
			max = graph[n];
			for (int m = n + 1; m < MAX_EDGE; m++) {
				if (graph[m].lenth < max.lenth) {
					max = graph[m];
					index = m;
				}
			}
			graph[index] = graph[n];
			graph[n] = max;
		}


		int roots[MAX_VEX];  	//根数组,存放各顶点的根节点,以区别是否属于同一个集合
		edge MST[MAX_EDGE];		//存放最小生成树(minimum spanning tree)
		int count = 0;


		for (int n = 0; n < MAX_VEX; n++) {
			roots[n] = -1;
		}

		for (int n = 0; n < MAX_EDGE; n++) {

			if (graph[n].used == 1) {
				int vex_m = find_root(roots, graph[n].edgelink.startpoint);
				int vex_n = find_root(roots, graph[n].edgelink.endpoint);
				if (vex_m != vex_n) {				//如果两者的根节点不同,说明他们属于不同的集合,可以相连
					MST[count] = graph[n].edgelink;//将此边放入MST数组
					count++;
					roots[vex_m] = vex_n;			//将两个树合并,即将顶点vex_n作为vex_m的根节点

				}
				if (count == vex - 1) {
					break;
				}

			}
		}

		for (int k = 0; k < vex - 1; k++) {
//			printf("(%d,%d)%d\n", MST[k].startpoint, MST[k].endpoint, MST[k].weight);   //打印最小生成树

			int start = MST[k].startpoint;
			int end = MST[k].endpoint;

			for (int n = 0; n < 10; n++) {
				drawline(linkside[start][end].starty+n,
				         linkside[start][end].startx,
				         linkside[start][end].endy+n,
				         linkside[start][end].endx, 
					enemy[i].mapv3, 254, enemy[i].targetheight*pixnum, enemy[i].targetwidth*pixnum);
				drawline(linkside[start][end].starty,
					linkside[start][end].startx+n,
					linkside[start][end].endy,
					linkside[start][end].endx+n, 
					enemy[i].mapv3, 254, enemy[i].targetheight*pixnum, enemy[i].targetwidth*pixnum);
				
			}

		}

 

 完整代码



//author @ bilibili 民用级脑的研发记录
// 开发环境 小熊猫c++ 2.25.1  raylib 版本 4.5
// 2024-7-14
// AABB 碰撞检测 在拖拽,绘制,放大缩小中
// 2024-7-20
// 直线改每帧打印一个点,生长的直线,直线炮弹
// 2024-8-4
// 实现敌人追击与敌人死亡与mapv2 敌人轨迹不绘制
#include <raylib.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>


#define MAX_VEX 12
#define MAX_EDGE 144

// 重整原因:解决新函数放大缩小之下,raylib 的网格采样部分,选择数组的一部分刷新倒缓冲区里
// 从直接建立缓冲区,到先在数组里进行移动,然后再设置检查缓冲区
// 最大距离 - 当前坐标,实现坐标系变化,同时对应最顶上,变成新坐标下的最底下,可750-1=749数数得到

// 炮弹
typedef struct lineboom {
	int playeriv2 = 0;						// 一开始发射炮弹的玩家坐标
	int playerjv2 = 0;
	int drawiv2 = 0;						// 发射目标位置坐标
	int drawjv2 = 0;
	int oldx = 0;							// 记录上一格子,用于覆盖旧黑色点,产生炮弹轨迹
	int oldy = 0;
	int atking = 0;							// 是否正在攻击,因为有好几个炮弹,命中之后就结束炮弹运行
	int timev3 = 0;							// 记录运行时间或者长度,到达位置,炮弹爆炸。v3是沿用time,和之前代码变量名字一样
//	int toward = -1;						// 朝向,在剥离代码发现不同朝向,直线代码不同,结束比较符号不同
	int isboom = 0;							// 是否到了爆炸的时机,在修改直线代码中发现的可以合并重复代码,产生的控制变量
} lineboom;
// 随机敌人
typedef struct target {
	int targeti = 0;							// 左上角网格坐标
	int targetj = 0;
	int targetwidth = 0;						// 长宽
	int targetheight = 0;
	int islive = 0;

//	RenderTexture2D* picture;					// 敌人贴图
	RenderTexture2D picture;					// 敌人贴图

	int** oldmap;								// 局部复原数据

	int** mapv3;								// 像素也当成网格,每个记录像素是否能穿过

	target* area;								// 敌人内部的点

	int arealenth;								// 用于记录范围,lenth是半径
} target;
// 边
//typedef struct link {
//	int startx;									// 起点
//	int starty;
//	int endx;									// 终点
//	int endy;
//	int used;									// 是否已经使用
//	int lenth;									// 距离
//
//} link;

// 边
typedef struct edge {
	int startpoint;							// 起点在数组中的序号
	int endpoint;							// 终点在数组中的序号
	int weight;
} edge;
// 边
typedef struct link {
	int startx;									// 起点的坐标
	int starty;
	int endx;									// 终点的坐标
	int endy;
	int used;									// 是否已经使用
	int lenth;									// 距离
	edge edgelink;								// 需要查点,记录所在数组位置
} link;
// 并查集查是否连通
int find_root(int roots[], int n) {
	while (roots[n] != -1) {
		n = roots[n];
	}
	return n;
}

// 检测碰撞,AABB碰撞检测,检测到碰撞时,碰撞产生矩形,左上角的坐标是 bangi j ,碰撞长宽是 bangwidth, bangheight
// 复制粘贴自碰撞检测
int bang(int drawi, int drawj, int mousewidth, int mouseheight, int targeti, int targetj, int targetwidth, int targetheight, int *bangi, int *bangj, int *bangwidth, int *bangheight) {
	int isbang = 0;					// 如果碰撞,就返回1
// +变- i 变 j
	if (drawi >= targeti && targeti >= drawi - mouseheight) {
		// 左上角重叠
		if (targeti - targetheight <= drawi - mouseheight) {
			if (drawj <= targetj && targetj <= drawj + mousewidth) {
				// 左上角重叠
				if (targetj + targetwidth >= drawj + mousewidth) {
//					for (int i = 0; i <  mouseheight - (drawi - targeti) ; i++) {
//						for (int j = 0; j <  mousewidth - ( targetj - drawj); j++) {
//							map[targeti - i][targetj + j] = 2024;
//						}
							map[targeti - i][targetj] = 2024;
//					}
//						for (int j = 0; j <  mousewidth - ( targetj - drawj); j++) {
//							map[targeti][targetj + j] = 2024;
//						}
//					左上角位置
					*bangi = targeti;
					*bangj = targetj;
//					长度,就是注释掉的循环的次数
					*bangwidth = mousewidth - (targetj - drawj);
					*bangheight = -(mouseheight - (drawi - targeti));
					isbang = 1;
				}
				//被包围了
				else if (targetj + targetwidth < drawj + mousewidth) {
//					for (int i = 0; i <  mouseheight - (drawi - targeti) ; i++) {
					map[targeti - i][targetj] = 2024;
//						for (int j = 0; j < targetwidth; j++) {
//							map[targeti - i][targetj + j] = 2024;
//						}
//					}
					*bangi = targeti;
					*bangj = targetj;
					// 注意负号,代表向下
					*bangwidth = targetwidth;
					*bangheight = -(mouseheight - (drawi - targeti));
					isbang = 1;
				}

			} else if (targetj <= drawj && drawj <= targetj + targetwidth) {
				// 右下角重叠
				if (targetj + targetwidth >= drawj + mousewidth) {
//					for (int i = 0; i <  mouseheight - (drawi - targeti) ; i++) {
					map[targeti - i][targetj] = 2024;
//						for (int j = 0; j < mousewidth ; j++) {
//							map[targeti - i][drawj + j] = 2024;
//						}
//					}
					*bangi = targeti;
					*bangj = drawj;
					*bangwidth = mousewidth;
					*bangheight = -(mouseheight - (drawi - targeti));
					isbang = 1;
				}
//			//被包围了
				else if (targetj + targetwidth < drawj + mousewidth) {

//					for (int i = 0; i <  mouseheight - (drawi - targeti) ; i++) {
					map[targeti - i][targetj] = 2024;
//						for (int j = 0; j < targetwidth - (drawj - targetj); j++) {
//							map[targeti - i][drawj + j] = 2024;
//						}
//					}
					*bangi = targeti;
					*bangj = drawj;
					*bangheight = -(mouseheight - (drawi - targeti));
					*bangwidth = targetwidth - (drawj - targetj);
					isbang = 1;
				}
			}
//				for (int i = 0; i <  mouseheight - (drawi - targeti) ; i++) {
//					map[targeti - i][targetj] = 2024;
//				}
		}
		//被包围了
		else if (targeti - targetheight > drawi - mouseheight) {
//				for (int i = 0; i < targetheight; i++) {
//					map[targeti - i][targetj] = 2024;
//				}
			if (drawj <= targetj && targetj <= drawj + mousewidth) {
				// 左上角重叠
				if (targetj + targetwidth >= drawj + mousewidth) {
//					for (int i = 0; i < targetheight; i++) {
							map[targeti - i][targetj] = 2024;
//						for (int j = 0; j <  mousewidth - ( targetj - drawj); j++) {
//							map[targeti - i][targetj + j] = 2024;
//						}
//					}
					*bangi = targeti;
					*bangj = targetj;
					*bangwidth = mousewidth - (targetj - drawj);
					*bangheight = -targetheight;
					isbang = 1;
				}
				//被包围了
				else if (targetj + targetwidth < drawj + mousewidth) {
//					for (int i = 0; i < targetheight; i++) {
							map[targeti - i][targetj] = 2024;
//						for (int j = 0; j < targetwidth; j++) {
//							map[targeti - i][targetj + j] = 2024;
//						}
//					}
					*bangi = targeti;
					*bangj = targetj;
					*bangwidth = targetwidth;
					*bangheight = targetheight;
					isbang = 1;
				}

			} else if (targetj <= drawj && drawj <= targetj + targetwidth) {
				// 右下角重叠
				if (targetj + targetwidth >= drawj + mousewidth) {
//					for (int i = 0; i < targetheight; i++) {
							map[targeti - i][targetj] = 2024;
//						for (int j = 0; j < mousewidth ; j++) {
//							map[targeti - i][drawj + j] = 2024;
//						}
//					}
					*bangi = targeti;
					*bangj = drawj;
					*bangwidth = mousewidth;
					*bangheight = targetheight;
					isbang = 1;
				}
//			//被包围了
				else if (targetj + targetwidth < drawj + mousewidth) {
//					for (int i = 0; i < targetheight; i++) {
							map[targeti - i][targetj] = 2024;
//						for (int j = 0; j < targetwidth - (drawj - targetj); j++) {
//							map[targeti - i][drawj + j] = 2024;
//						}
//					}
					*bangi = targeti;
					*bangj = drawj;
					*bangwidth = targetwidth - (drawj - targetj);
					*bangheight = -targetheight;
					isbang = 1;
				}
			}
		}
	} else if (targeti >= drawi && drawi >= targeti - targetheight) {
		// 被包围了
		if (targeti - targetheight <= drawi - mouseheight) {
//				for (int i = 0; i < mouseheight  ; i++) {
//					map[drawi - i][targetj] = 2024;
//				}
			if (drawj <= targetj && targetj <= drawj + mousewidth) {
				// 左上角重叠
				if (targetj + targetwidth >= drawj + mousewidth) {
//					for (int i = 0; i < mouseheight  ; i++) {
							map[drawi - i][targetj] = 2024;
//						for (int j = 0; j <  mousewidth - ( targetj - drawj); j++) {
//							map[drawi - i][targetj + j] = 2024;
//						}
//					}
					*bangi = drawi;
					*bangj = targetj;
					*bangwidth = mousewidth - ( targetj - drawj);
					*bangheight = -mouseheight;
					isbang = 1;
				}
				//被包围了
				else if (targetj + targetwidth < drawj + mousewidth) {
//					for (int i = 0; i < mouseheight  ; i++) {
							map[drawi - i][targetj] = 2024;
//						for (int j = 0; j < targetwidth; j++) {
//							map[drawi - i][targetj + j] = 2024;
//						}
//					}
					*bangi = drawi;
					*bangj = targetj;
					*bangwidth = targetwidth;
					*bangheight = -mouseheight;
					isbang = 1;
				}

			} else if (targetj <= drawj && drawj <= targetj + targetwidth) {
				// 右下角重叠
				if (targetj + targetwidth >= drawj + mousewidth) {
//					for (int i = 0; i < mouseheight  ; i++) {
							map[drawi - i][targetj] = 2024;
//						for (int j = 0; j < mousewidth ; j++) {
//							map[drawi - i][drawj + j] = 2024;
//						}
//					}
					*bangi = drawi;
					*bangj = drawj;
					*bangwidth = mousewidth;
					*bangheight = -mouseheight;
					isbang = 1;
				}
//			//被包围了
				else if (targetj + targetwidth < drawj + mousewidth) {
//					for (int i = 0; i < mouseheight  ; i++) {
							map[drawi - i][targetj] = 2024;
//						for (int j = 0; j < targetwidth - (drawj - targetj); j++) {
//							map[drawi - i][drawj + j] = 2024;
//						}
//					}
					*bangi = drawi;
					*bangj = drawj;
					*bangwidth = targetwidth - (drawj - targetj);
					*bangheight = -mouseheight;
					isbang = 1;
				}
			}
		}

//			//被包围了
		else if (targeti - targetheight > drawi - mouseheight) {
//			for (int i = 0; i < targetheight - ( targeti - drawi ); i++) {
//				map[drawi - i][targetj] = 2024;
//			}
			if (drawj <= targetj && targetj <= drawj + mousewidth) {
				// 左上角重叠
				if (targetj + targetwidth >= drawj + mousewidth) {
//					for (int i = 0; i < targetheight - ( targeti - drawi ); i++) {
							map[drawi - i][targetj] = 2024;
//						for (int j = 0; j <  mousewidth - ( targetj - drawj); j++) {
//							map[drawi - i][targetj + j] = 2024;
//						}
//					}
					*bangi = drawi;
					*bangj = targetj;
					*bangwidth = mousewidth - ( targetj - drawj);
					*bangheight = -(targetheight - ( targeti - draw
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值