java迷宫

9 篇文章 0 订阅

终于放假了,可以研究一些好玩的东西了,先把之前用c语言写的迷宫用swing重写了下界面,算法部分并没有做什么修改,原来的链接

这个比拼图还要简单,因为并不涉及线程,只要在按键wsad后重绘就行。

尝试了菜单栏的用法,比较奇怪的是JMenu貌似并不能添加监听事件(假设我并没有下拉的子菜单),必须只能给JMenuItem添加监听事件(这就意味着哪怕只有一个选项也必须先写JMen,再在这里面设定一个JMenuItem)

另外注意聚焦的问题,即使用JPanel时需要添加聚焦setFocusable

其余就没什么说的了,按部就班的写下去。生成迷宫算法部分不复杂,大致就是从左上角开始深度优先搜索,但是原来深搜是按照一定模式(比如上下左右)扩展节点,现在我先随机生成一个4个全排列,按照这个顺序随机访问上下左右的点,直到右下角为止,生成一条路径,然后剩下的点大部分(这里设为80%)为墙壁,少部分(这里设为20%)为路径,毕竟不能整个地图空白就是路径,那样一眼就看出来了。

下面贴代码,写的时候思路比较清晰,测试没发现什么明显bug,如果有问题请留言指出哈~~

game类(游戏界面)

public class game extends JFrame implements ActionListener {
    JMenuBar menuBar;//菜单栏对象
    JMenu menu,menu2;//菜单对象
    JMenuItem menuitem,menuitem2,menuitem3;
    Secretmap g;
	public  game(){
		setTitle("我的迷宫");
		setLayout(null);
		setBounds(100,100,700,700);
		g= new Secretmap();//里面包含一个游戏类继承画板
		g.setBounds(0,0,600,600);
		Container container=getContentPane();
		menuBar=new JMenuBar();//创建菜单栏对象
		setJMenuBar(menuBar);//添加菜单栏对象
		menu=new JMenu("开始");//创建菜单对象
		menuBar.add(menu);//将菜单对象添加到菜单栏对象中
		menuitem=new JMenuItem("开始游戏");
		menu.add(menuitem);
		menuitem.addActionListener(this);//添加监听事件
		menu2=new JMenu("设置");
		menuBar.add(menu2);
	    menuitem2=new JMenuItem("设置行数");
		menu2.add(menuitem2);
		menuitem2.addActionListener(this);//添加监听事件
		menuitem3=new JMenuItem("设置列数");
		menu2.add(menuitem3);
		menuitem3.addActionListener(this);//添加监听事件
		container.add(g);
		setVisible(true);
		g.setFocusable(true);//关键之关键,jpanel添加键盘监听事件要聚焦到画板
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
	}
     public void actionPerformed(ActionEvent e){
		 if (e.getSource()==menuitem) {
			g.startgame();//开始游戏
			System.out.println("1");
		}
		if (e.getSource()==menuitem2){//设置行数
			System.out.println("2");
			alert a=new alert(g);
		}
		if (e.getSource()==menuitem3){//设置列数
			System.out.println("3");
			alert2 b=new alert2(g);//这边涉及到窗口的传值,就是把一个对象传进去
		}
	 }
	
	  public static void main(String [] args){
		 new game();
	}

}

Secretmap(迷宫的内部活动类)

public class Secretmap extends JPanel implements KeyListener{
	int time;//控制画板的绘画方式
	int row;//行
	int column;//列
	int [][]a;//存储状态的节点
	int [][]visit;
	int []direction=new int[4];
	int Time;
	int personrow;//人当前所在的行
	int personcolumn;//人当前所在的列
	ImageIcon imagecon;
	public Secretmap()
	{   
		time=0;//默认展示背景图片
		Time=0;//默认没有找到路径
		row=column=0;//初始化为0(如果不为0说明可以绘制)
        imagecon=new ImageIcon("./picture/bg.png");//记录完整图片
		repaint();
	}
	public void SetRow(int row)
	{
		this.row=row;
	}
	public void SetColumn(int column)
	{
		this.column=column;
	}
	public void startgame()
	{   
		if ((row!=0)&&(column!=0))//当行数和列数均已经设定
		{   
			this.removeKeyListener(this);
			Time=0;
			System.out.println(row+"  "+column);
			time=1;
			a=new int[row+1][column+1];
			visit=new int[row+1][column+1];
			initsecretmap();//随机生成迷宫的一条线路
			for (int i=0;i<row;i++)
				for (int j=0;j<column;j++)
				{
					if (a[i][j]==0)//如果不在这条线路上
					{
						int m=(int)(Math.random()*100);
						if (m<=20)//除了线路上的点都是空白,肯定还要有一些空白,这个就认为剩下的20%是空白
						a[i][j]=1;
					}
				}
			this.addKeyListener(this);
			personrow=0;
			personcolumn=0;
			repaint();
		}
	}
	public void initsecretmap()
	{
		 for (int i=0;i<row;i++)
			 for (int j=0;j<column;j++)
				 a[i][j]=0;//一开始都标记为不可通行
		 for (int i=0;i<row;i++)
			 for (int j=0;j<column;j++)
				 visit[i][j]=0;
		 a[0][0]=1;//起点标记为可通行(这里默认左上角为起点,可自行修改)
		 visit[0][0]=1;//标记起点已经被访问过
		 DFS(0,0);//开始深搜
		 
	}
	public void DFS(int x,int y)
	{
		int []c={0,0,-1,1};
		int []d={1,-1,0,0};
		int dx,dy,i;
		if ((x==row-1)&&(y==column-1))//如果到达终点
		{
			Time=1;
			return;
		}
		initdirection();//随机生成四个方向(其实就是全排列)
		for (i=0;i<=3;i++)
		{
			dx=x+c[direction[i]];
			dy=y+d[direction[i]];
			if ((dx>=0)&&(dx<row)&&(dy>=0)&&(dy<column)&&(visit[dx][dy]==0)&&(Time==0))
			{
				a[dx][dy]=1;//认为它是通路
				visit[dx][dy]=1;
				DFS(dx,dy);
				if (Time==0)
				a[dx][dy]=0;
			}
		}
	}
	public void initdirection()
	{
	    int i,j,k,ok;
	    for (i=0;i<=3;i++)
	    {
	        j=(int)(Math.random()*4);//注意括号的位置!要先乘再取int
	        ok=1;
	        for (k=0;k<i;k++)
	        if (j==direction[k])
	        ok=0;
	        if (ok==1)
	        direction[i]=j;
	        else
	        i--;
	     }
	}
	
	public boolean isreach()
	{
		if ((personrow==row-1)&&(personcolumn==column-1))
		return true;
		return false;
   }
	@Override
	public void keyPressed(KeyEvent e)
	{
		char c=e.getKeyChar();
		System.out.println(c);
		switch(c)
		{
		case 'w'://如果是向上
			if ((personrow>0)&&(a[personrow-1][personcolumn]==1))//如果上方可以到达
			personrow--;
			if (isreach())
			{
			new alert3();
			Time=0;
			this.removeKeyListener(this);
			}
			break;
		case 's'://如果是向下
			if ((personrow<row-1)&&(a[personrow+1][personcolumn]==1))//如果下方可以到达
			personrow++;
			if (isreach())
			{
			new alert3();
			Time=0;
			this.removeKeyListener(this);
			}
			break;
		case 'a'://如果是向左
			if ((personcolumn>0)&&(a[personrow][personcolumn-1]==1))//如果左方可以到达
			personcolumn--;
			if (isreach())
			{
			new alert3();
			Time=0;
			this.removeKeyListener(this);
			}
			break;
		case 'd'://如果是向右
			if ((personcolumn<column-1)&&(a[personrow][personcolumn+1]==1))//如果右方可以到达
			personcolumn++;
			if (isreach())
			{
				new alert3();
				Time=0;//标记为没有找到
				this.removeKeyListener(this);
			}
			break;
		 }
		repaint();
	}
	public void paint(Graphics g)
	{
		if (time==0)//如果是一开始没有开始游戏时,随便放一张背景图片
		{
			 Image r=imagecon.getImage();
			 g.drawImage(r,0,0,600,600,this);//画出原来的完整图案
		}
		else
		if (time==1)//否则就是在游戏中重绘
		{
			g.clearRect(0,0,600,600);
			for (int i=0;i<row;i++)
				for (int j=0;j<column;j++)
				{
					if ((i==personrow)&&(j==personcolumn))
					{
						Color c=g.getColor();
						g.setColor(Color.RED);//人是红色
						g.fillRect(600/column*j,600/row*i,600/column,600/row);
						g.setColor(c);
					}
					else
					if (a[i][j]==1)
					{
						Color c=g.getColor();
						g.setColor(Color.WHITE);//白色是路
						g.fillRect(600/column*j,600/row*i,600/column,600/row);
						g.setColor(c);
					}
					else
						if (a[i][j]==0)
						{
							Color c=g.getColor();
							g.setColor(Color.GRAY);//灰色是墙壁
							g.fillRect(600/column*j,600/row*i,600/column,600/row);
							g.setColor(c);
						}
					
				}
		}
		
	}
	@Override
	public void keyReleased(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}
}

接下去就是几个弹窗

alert类

public class alert extends JDialog {
	 int row;
	 public alert(Secretmap g){
		setTitle("注意!");
		setLayout(null);
		setBounds(300,300,400,400);
		Container container=getContentPane();
		container.setBackground(Color.white);
		JLabel jl= new JLabel("请输入新的行数");
		jl.setBounds(50,50,300,100);
	    JTextField jt=new JTextField("");
	    jt.setBounds(50,150,300,50);
	    JButton jb=new JButton("确定");
	    jb.setBounds(100,250,150,75);
        jb.addActionListener(new ActionListener() {//设立确定按钮的点击事件
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stu9b
			  String s=jt.getText();
			  if (s.matches("\\d+"))//如果是数字
			  row=Integer.valueOf(s);
			  System.out.println(row);
			  g.SetRow(row);
			  setVisible(false);
			}
		});
	    container.add(jl);
	    container.add(jt);
	    container.add(jb);
	    setVisible(true);
	    }
	
	 
	
}

alert2类

public class alert2 extends JDialog {
	 int column;
	 public alert2(Secretmap g){
		setTitle("注意!");
		setLayout(null);
		setBounds(300,300,400,400);
		Container container=getContentPane();
		container.setBackground(Color.white);
		JLabel jl= new JLabel("请输入新的列数");
	    jl.setBounds(50,50,300,100);
	    JTextField jt=new JTextField("");
	    jt.setBounds(50,150,300,50);
	    JButton jb=new JButton("确定");
	    jb.setBounds(100,250,150,75);
       jb.addActionListener(new ActionListener() {//设立确定按钮的点击事件
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stu9b
			  String s=jt.getText();
			  if (s.matches("\\d+"))//如果是数字
			  column=Integer.valueOf(s);
			  System.out.println(column);
			  g.SetColumn(column);
			  setVisible(false);
			 }
		});
	    container.add(jl);
	    container.add(jt);
	    container.add(jb);
	    setVisible(true);
	    }
	
	 
	
}
alert3类

public class alert3 extends JDialog {
			ImageIcon li;
			public alert3(){
				win g=new win();
				g.setBounds(0,0,400,400);
				setTitle("you win!");
				setLayout(null);
				setBounds(400,300,450,400);
				Container container=getContentPane();
				container.add(g);
				container.setBackground(Color.white);
			    setVisible(true);
			    }
			
	}
 
	

win类

 public class win extends JPanel{
		  	 ImageIcon li;
		  	 public win(){
		  		 li=new ImageIcon("./picture/you win.png");
		  		 repaint();
		  	 }
		  	 public void paint(Graphics g)
		  	 {
		  		 Image r=li.getImage();
		  	     g.drawImage(r,0,0,400,400,this);
		  	 }
 }


github: https://github.com/fengsigaoju/secretmap

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值