java迷宫

来源:互联网 发布:源码下载网站 编辑:程序博客网 时间:2024/06/08 01:11

终于放假了,可以研究一些好玩的东西了,先把之前用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;   }@Overridepublic 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);//画出原来的完整图案}elseif (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);}elseif (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);}elseif (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);}}}}@Overridepublic void keyReleased(KeyEvent arg0) {// TODO Auto-generated method stub}@Overridepublic 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() {//设立确定按钮的点击事件@Overridepublic 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() {//设立确定按钮的点击事件@Overridepublic 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

0 0
原创粉丝点击