您的位置:首页 > 编程语言 > Java开发

java迷宫

2016-07-03 20:20 399 查看
终于放假了,可以研究一些好玩的东西了,先把之前用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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: