java迷宫
2016-07-03 20:20
399 查看
终于放假了,可以研究一些好玩的东西了,先把之前用c语言写的迷宫用swing重写了下界面,算法部分并没有做什么修改,原来的链接
这个比拼图还要简单,因为并不涉及线程,只要在按键wsad后重绘就行。
尝试了菜单栏的用法,比较奇怪的是JMenu貌似并不能添加监听事件(假设我并没有下拉的子菜单),必须只能给JMenuItem添加监听事件(这就意味着哪怕只有一个选项也必须先写JMen,再在这里面设定一个JMenuItem)
另外注意聚焦的问题,即使用JPanel时需要添加聚焦setFocusable
其余就没什么说的了,按部就班的写下去。生成迷宫算法部分不复杂,大致就是从左上角开始深度优先搜索,但是原来深搜是按照一定模式(比如上下左右)扩展节点,现在我先随机生成一个4个全排列,按照这个顺序随机访问上下左右的点,直到右下角为止,生成一条路径,然后剩下的点大部分(这里设为80%)为墙壁,少部分(这里设为20%)为路径,毕竟不能整个地图空白就是路径,那样一眼就看出来了。
下面贴代码,写的时候思路比较清晰,测试没发现什么明显bug,如果有问题请留言指出哈~~
game类(游戏界面)
Secretmap(迷宫的内部活动类)
接下去就是几个弹窗
alert类
alert2类
github:https://github.com/fengsigaoju/secretmap
这个比拼图还要简单,因为并不涉及线程,只要在按键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
相关文章推荐
- java计算器实现,百行代码,清晰注释
- 登录案例解析
- 理解JAVA 8的Lambda表达式
- SpringMVC学习--拦截器
- Java注解教程及自定义注解
- 给各阶段Java程序猿的学习建议
- java与Groovy的互调用 实现在当前目录及其子目录删除指定名称的目录
- thymeleaf 模板语言简介
- JavaSE_标识符
- Eclipse中xml配置文件报错原因总结
- Java语法的主要特性
- Spring之IOC和AOP
- Java Web实战03--Spring之HelloWorld
- Java 泛型 泛型代码和虚拟机
- Java Web 入门
- 去掉eclipse的拼写检查
- Java中try catch finally语句中含有return语句的执行情况(总结版)
- 【Java进阶三】理解多态
- Java中没有引用传递只有值传递(在函数中)
- Mac OS版eclipse下JRE System Libreary[jre1.8.0_91](unbound)问题