用不相交集数据结构生成迷宫

         之前提到的不相交集数据结构(: http://blog.csdn.net/zhutulang/article/details/7791804。)的一个应用的例子是迷宫的生成。如下图所示就是一个50*50的迷宫。

迷宫

        它的开始点位于图上的左上角,而终止点在图上的右下角。可以把这个迷宫看成是由50*50个单元组成的矩形,左上角的单元被连通到右下角的单元,而且这些单元与邻近的单元通过墙壁分隔开来。生成迷宫的一个简单算法是:不断地随机选择一面墙壁,如果被该墙分割的单元彼此不连通,那么就把这面墙拆掉。重复这个过程直到开始单元和终止单元连通。

        画迷宫的代码如下,里面单元的坐标、要拆去的墙的坐标,先自己在纸上画一个简单的,找一找规律就能确定了。要用到的不相交集的数据结构的代码,之前已经放了,这里就不重复了,在http://blog.csdn.net/zhutulang/article/details/7791804,使用的是有“路径压缩”的那个DisjSets.java,这里只放Maze.java.。

package com.test;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Maze extends JFrame {

	
	private static final long serialVersionUID = 4581809619616228704L;
	//迷宫尺寸
	int m=50,n=50;
	//迷宫房间尺寸(正方形)
	int rSize=10;
	//迷宫起点距离窗口距离(离左、上的距离d*rSize)
	int d=10;
	//窗口尺寸
	static int wHeight=700;
	static int wWidth=700;
	JPanel panel=new JPanel();
	
	public Maze(){
		
		panel.setLayout(null);
		//panel.setBorder(BorderFactory.createTitledBorder("迷宫:")); 
		add(panel, BorderLayout.CENTER);
	}
	
	public void paint(Graphics g){
		
		//背景成白色
		g.setColor(Color.white);
		g.fillRect(0, 0, wWidth, wHeight);
		g.setColor(Color.black);
		
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++)
				{
				  //画房间
				  g.drawRect(rSize*(i+d),rSize*(j+d), rSize, rSize);
				}
		//迷宫的出口和入口打开
		g.setColor(Color.white);
		//入口横墙      -1、+1是为了不在隔壁墙上留下小缺口(后面画线时同理)
		g.drawLine(rSize*d, rSize*d, rSize*(d+1)-1,rSize*d); 
		//入口竖墙
		g.drawLine(rSize*d, rSize*d, rSize*d,rSize*(d+1)-1); 
		//出口横墙
		g.drawLine((n-1+d)*rSize+1, (m+d)*rSize, (n+d)*rSize,(m+d)*rSize); 
		//出口竖墙
		g.drawLine((n+d)*rSize, (m-1+d)*rSize+1, (n+d)*rSize,(m+d)*rSize);
		
		//不相交集定义
		DisjSets dSets=new DisjSets(m*n);
		Random random=new Random();
		
		
		//房间0、mn-1没有连通
		while(dSets.find(0)!=dSets.find(m*n-1)){
			
			//随机生成一个房间号a  0<=a<=mn-1
			int a=random.nextInt(m*n);
			//a的相邻房间用list存放
			List<Integer> neighbor=new ArrayList<Integer>();
			//分别判断a的上、右、下、左房间是否存在,若存在放入neighbor
			if(a-n>=0)
				neighbor.add(a-n);
			if( a+1<( (int)(a/n)+1 )*n )
				neighbor.add(a+1);
			if(a+n<m*n)
				neighbor.add(a+n);
			if( a-1>=( (int)(a/n) )*n )
			    neighbor.add(a-1);
			//生成随机数index, 0<=index<=neighbor.size()-1
			int index=random.nextInt(neighbor.size());
			//b房间是a的相邻房间号,我们考察这两个房间是否连通
			int b=neighbor.get(index);
			
			//a、b是否连通 
			if(dSets.find(a)==dSets.find(b))
				//a、b连通的话重新考察新的房间
			  continue;  
			else{
			 //a、b不连通,union它们的集合
				int seta=dSets.find(a);
				int setb=dSets.find(b);
				dSets.union(seta, setb);
			 //接下来拆掉它们之间的"墙"
				//首先得到较小房间号
				int s=Math.min(a, b);
				//计算"墙"的坐标
				  int x1,y1,x2,y2;
				  //两房间编号差是1,隔开它们的是竖墙
				if(Math.abs(a-b)==1)
				{
					
					//起点 					
					if(s<n)
						x1=(s+1+d)*rSize;
					else 
						x1=(s%n+1+d)*rSize;
					y1=( (int)(s/n)+d )*rSize+1;
					//终点
					x2=x1;
					y2=( (int)(s/n)+1+d )*rSize-1;
				}else {
					//否则是横墙
					//起点
					if(s<n)
						x1=(s+d)*rSize+1;
					else
						x1=(s%n+d)*rSize+1;
					y1=( (int)(s/n)+1+d )*rSize;
					//终点
					if(s<n)
						x2=(s+1+d)*rSize-1;
					else
						x2=(s%n+1+d)*rSize-1;
					y2=y1;
				}
			 //拆墙,实际上是用白线把墙抹掉
				g.setColor(Color.white);
				g.drawLine(x1, y1, x2, y2);
				
			}
		}		 
	}
		
	public static void main(String[] args) {

		Maze maze=new Maze();
		maze.setTitle("迷宫");
		maze.setSize(wWidth,wHeight);
		maze.setVisible(true);
		maze.setLocationRelativeTo(null);
		maze.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       		
	}
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值