用不相交集合生成一个迷宫
来源:互联网 发布:拿破仑为什么称帝知乎 编辑:程序博客网 时间:2024/05/16 00:24
最近看到不相交集,使用不相交集写了一个生成迷宫算法,其实想法很简单,就来分享一下,首先我们对迷宫中的每个格子进行编号,从0到n,先画一个n*m的格子版,然后删除一些边打通各个格子,使之变成连通,我们把边分成横边和纵边,我们可以通过计算,标记打通一条边会使两个格子变成连通,然后用不想交集合进行标记。最后使得所有边都连通起来即可:
具体操作:先把所有的边编号,放入一个数组内,然后用随机数打乱整个数组,接着对这个数组进行遍历,检测一条边连接的两个小方格,若其不连通,即不在一同一个不想交集合内,则打通他们,否则则不做任何动作,知道所有格子都被遍历完成,得到的边的数组就是生成迷宫了
不相交集源代码:
/** * Created by v on 16-12-13. */public class DisjSets { private int[] s; public DisjSets(int numElements){ s=new int[numElements]; for(int i=0;i<s.length;i++){ s[i]=-1; } } public void union(int root1,int root2){ if(s[root1]<s[root2]){ s[root2]=root1; }else{ if(s[root1]==s[root2]){ s[root2]--; } s[root1]=root2; } } public int find(int x){ if(s[x]<0){ return x; }else { return s[x]=find(s[x]); } }}
迷宫后台算法:
import java.util.Random;/** * Created by v on 16-12-13. */public class Labyrinth { private boolean[][][] sides; private DisjSets disjSets; /** * * 对于一个n*m的迷宫,纵向边共(1+n)*(1+m)条,横向边也一样, * 因此我们用数组的最后一位表示纵横,z=0为横,z=1为纵 * * @param rows 迷宫格子的行数 * @param lines 迷宫格子的列数 */ public Labyrinth(int lines, int rows){ sides =new boolean[lines+1][rows+1][2]; disjSets=new DisjSets(rows*lines); //去除边框处露出来的边 for(int i=0;i<=rows;i++){ sides[lines][i][0]=true; } for(int i=0;i<=lines;i++){ sides[i][rows][1]=true; } build(lines,rows); //打通入口与出口 sides[0][0][1]=true; sides[lines][rows-1][1]=true; } //产生一个迷宫 private void build(int lines,int rows){ int[] randomNumbers=new int[rows*lines*2]; //先生成一个包含所有边的编号的数组 for(int i=0;i<randomNumbers.length;i++){ randomNumbers[i]=i; } Random random=new Random(); //对整个数组进行打乱处理 for(int i=0;i<randomNumbers.length;i++){ swap(randomNumbers,i,random.nextInt(randomNumbers.length)); } //对迷宫的每一条边进行处理,若边的两头未连通,则删除边 for(int i=0;i<randomNumbers.length;i++){ int x=randomNumbers[i]%lines; int z=randomNumbers[i]/rows/lines; int y=(randomNumbers[i]-z*rows*lines)/lines; //对于位于边界的边,我们不处理 if(y==0&&z==0){continue;} if(x==0&&z==1){continue;} //尝试打通这一条边 if(z==0){ int root1=disjSets.find(x+lines*y); int root2=disjSets.find(x+lines*(y-1)); if(root1!=root2){ disjSets.union(root1,root2); sides[x][y][z]=true; } }else { int root1=disjSets.find(x+lines*y); int root2=disjSets.find(x-1+lines*y); if(root1!=root2){ disjSets.union(root1,root2); sides[x][y][z]=true; } } } } //交换两个值 private final void swap(int[] array,int index1,int index2){ int temp=array[index1]; array[index1]=array[index2]; array[index2]=temp; } //返回迷宫的某一个边是否被打通,若被打通则返回true public boolean getSide(int x,int y,int z){ return sides[x][y][z]; } public int getLines(){ return sides.length; } public int getRows(){ return sides[0].length; }}
迷宫显示的ui:
import javax.swing.*;import java.awt.*;/** * Created by v on 16-12-13. */public class LabyrinthUI extends JApplet { LabyrinthPanel panel; public LabyrinthUI(){ panel=new LabyrinthPanel(40,30); add(panel); } @Override public void init() { super.init(); setSize(600,400); } private class LabyrinthPanel extends JPanel{ private Labyrinth labyrinth; public LabyrinthPanel(int lines,int rows){ labyrinth=new Labyrinth(lines,rows); repaint(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); for(int i=0;i<labyrinth.getLines();i++){ for(int j=0;j<labyrinth.getRows();j++){ if(!labyrinth.getSide(i,j,0)){ g.drawLine(50+i*10,50+j*10, 50+i*10+10,50+j*10); } if(!labyrinth.getSide(i,j,1)){ g.drawLine(50+i*10,50+j*10, 50+i*10,50+j*10+10); } } } } }}
0 0
- 用不相交集合生成一个迷宫
- 用不相交集数据结构生成迷宫
- 不相交集生成随机迷宫
- 应用不相交集类生成迷宫
- 数据结构_不相交集合_绘制迷宫
- 不相交集类以及应用迷宫生成
- 利用不相交集来生成迷宫(只有关键代码)
- 不相交类集算法生成迷宫并求解路径
- 不相交集合
- 不相交集合
- 不相交集合
- 不相交集合
- 不相交集合
- hdu 1272 小希的迷宫(不相交集合森林)
- 利用不相交集画迷宫
- 不相交集合的数据结构
- 不相交集合(转)
- 一个迷宫生成算法
- 带你学开源项目:OkHttp–自己动手实现OkHttp
- [Web前端技术教学]《基于Web标准的网页设计与制作》试题及答案
- spring security 示例
- JAVA基础(三)------变量和运算符
- POJO
- 用不相交集合生成一个迷宫
- MyEclipse设置html代码提示功能
- Spring 3之MVC & Security简单整合开发(一)
- 计算机日常积累
- [译]百里挑一:21个优质Swift开源App
- iOS 融云头像问题
- [转]HTML5离线存储和本地缓存
- layer[申明:来源于网络]
- Shape 画角的原理图