本文介绍
之前的文章讲述了如何将前面建立的生成迷宫、解决迷宫更好的连接起来,使其更美观。(里面有一些println语句,是我在测试和修bug时使用的,有些没有删除,请见谅)
初始化界面
使页面在窗口的中间位置显示,并添加按钮,供玩家选择,添加关闭按钮的监听,添加页面Icon。
void initPanel () {
JFrame newJFrame = new JFrame();
int side = 30;
int width;
int height;
//任务栏高度
double task = 30;
double a = Toolkit.getDefaultToolkit().getScreenSize().getWidth() - task;
double b = Toolkit.getDefaultToolkit().getScreenSize().getHeight() - task;
//添加画布
if (setting == null) {
//这里的6弥补一点宽度
width = widthCount * side + 6;
//这里创建的窗口高度需要加1,也需要留一点位置给按钮
height = heightCount * side + side * 1;
newJFrame.add(new MyPanel(widthCount, heightCount, DFSMethod, newJFrame));
newJFrame.setBounds((int)(a/2) - width/2,(int)(b/2) - height/2,
width,
height);
} else {
width = setting.getWidth() * side + 6;
height = setting.getHeight() * side + side * 1;
newJFrame.add(new MyPanel(setting.getWidth(), setting.getHeight(), setting.getModel(), newJFrame));
newJFrame.setBounds((int)(a/2) - width/2,(int)(b/2) - height/2,
width,
height);
}
this.setVisible(false);
newJFrame.setVisible(true);
newJFrame.setResizable(false);
newJFrame.setTitle("小蝌蚪找妈妈迷宫");
ImageIcon img = new ImageIcon("src\\images\\mazeIcon.jpg");
newJFrame.setIconImage(img.getImage());
newJFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
设置页面
默认开始参数:
设置长为23,宽为23,深度优先遍历产生地图
public Setting (MazeFrame mazeFrame) {
this.mazeFrame = mazeFrame;
int labelX = 10, labelY = 10, labelW = 70, fieldX = 80, fieldY = 10, fieldW = 240, height = 30, hSpace = 35;
int frameW = 350, frameH = 230, btnW = 120;
double a = Toolkit.getDefaultToolkit().getScreenSize().getWidth();
double b = Toolkit.getDefaultToolkit().getScreenSize().getHeight();
frame.setLocation(new Point((int) (a / 2) - 150, (int) (b / 2) - 150));// 设定窗口出现位置
frame.setSize(frameW, frameH);// 设定窗口大小
frame.setContentPane(tabPane);// 设置布局
labelWidth.setBounds(labelX, labelY, labelW, height);
labelHeight.setBounds(labelX, labelY = labelY + hSpace, labelW, height);
label2.setBounds(labelX, labelY = labelY + hSpace, labelW, height);
fieldWidth.setBounds(fieldX, fieldY, fieldW, height);
fieldHeight.setBounds(fieldX, fieldY = fieldY + hSpace, fieldW, height);
comboBox.setBounds(fieldX, fieldY = fieldY + hSpace, fieldW, height);
button.setBounds((frameW-btnW)/2, fieldY = fieldY + hSpace, btnW, height);
button.addActionListener(this);
comboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
String value = comboBox.getSelectedItem().toString();
if ("DFS生成算法".equals(value)) {
model = DFSMethod;
} else {
model = BFSMethod;
}
System.out.println(value);
}
}
});
_ONE.add(labelWidth);
_ONE.add(labelHeight);
_ONE.add(label2);
_ONE.add(fieldWidth);
_ONE.add(fieldHeight);
_ONE.add(comboBox);
_ONE.add(button);
frame.setVisible(true);// 窗口可见
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
tabPane.add("难度设置", _ONE);
fieldWidth.setText("23");
fieldHeight.setText("23");
}
上面是初始化设置的页面展示,因为我是从fieldWidth和fieldHeight中读取数据的,在刚初始化就设定为23,就设定好默认结果了。如果想改变,只需要键盘在文本框中输入就行了。
# 对宽度和高度的限制
我们知道,如果用户输入了一个很大的数,因为地图会根据长宽生成不一样的大小,就会把整个窗口占满,如果输入了一个很小的数,地图就会不好玩。我测试了一下我电脑的大小,将长度设定在7至31范围内,将宽度设定在7至53范围内。以及我们发现,因为生成迷宫需要的长和宽都是奇数,如果用户输入偶数,也会对那个数进行修改(就是调用setText方法改宽和高)。具体代码如下:
按下确定后:
然后进入游戏界面:
private void startPanel() {
String widthValue = fieldWidth.getText();
String HeightValue = fieldHeight.getText();
try {
widthCount = Integer.parseInt(widthValue);
if (widthCount > 53) {
JOptionPane.showMessageDialog(comboBox,"宽度过长,已经帮您修改为53","警告",JOptionPane.WARNING_MESSAGE);
widthCount = 53;
fieldWidth.setText("53");
}
if (widthCount < 7) {
JOptionPane.showMessageDialog(comboBox,"宽度过短,已经帮您修改为7","警告",JOptionPane.WARNING_MESSAGE);
widthCount = 7;
fieldWidth.setText("7");
}
if (widthCount % 2 != 1) {
JOptionPane.showMessageDialog(comboBox,"宽度需要是奇数哦,已经帮您修改数值为" + (widthCount+1),
"警告",JOptionPane.WARNING_MESSAGE);
widthCount += 1;
fieldWidth.setText(String.valueOf(widthCount));
}
System.out.println("宽度" + widthCount);
} catch (NumberFormatException numberFormatException) {
JOptionPane.showMessageDialog(comboBox,"宽度输入格式不正确!","警告",JOptionPane.WARNING_MESSAGE);
}
try {
heightCount = Integer.parseInt(HeightValue);
heightCount = (heightCount % 2 == 1) ? heightCount : heightCount + 1;
if (heightCount > 31) {
JOptionPane.showMessageDialog(comboBox,"长度过长,已经帮您修改为31","警告",JOptionPane.WARNING_MESSAGE);
heightCount = 31;
fieldHeight.setText("31");
}
if (heightCount < 7) {
JOptionPane.showMessageDialog(comboBox,"长度过短,已经帮您修改为7","警告",JOptionPane.WARNING_MESSAGE);
heightCount = 7;
fieldHeight.setText("7");
}
if (heightCount % 2 != 1) {
JOptionPane.showMessageDialog(comboBox,"长度需要是奇数哦,已经帮您修改数值为" + (heightCount+1),
"警告",JOptionPane.WARNING_MESSAGE);
heightCount += 1;
fieldHeight.setText(String.valueOf(heightCount));
}
System.out.println("高度" + heightCount);
} catch (NumberFormatException numberFormatException) {
JOptionPane.showMessageDialog(comboBox,"长度输入格式不正确!","警告",JOptionPane.WARNING_MESSAGE);
}
//new SelectTableToGenerageDialog();触发下一个弹框
frame.dispose();//关闭弹框
}
电脑帮玩
发现仔细的小伙伴以及看到那个按钮了,只要按下那个按钮,电脑会自动帮您走完全部过程,但是只能在起始点才能按,否则会出现这个情况。
具体的代码如下:
void initButton() {
ansButton = new JButton("开启自动寻路");
ansButton.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (go && !buttonOpen) {
JOptionPane.showMessageDialog(null,
"您已经开始,所以无法再帮您寻找通路了",
"警告",JOptionPane.WARNING_MESSAGE);
return;
}
buttonOpen = !buttonOpen;
if (!buttonOpen) {
ansButton.setText("开启自动寻路");
} else {
ansButton.setText("关闭自动寻路");
go = true;
}
map = mapForComputer;
Thread thread = new Thread(new LookWay());
thread.start();
}
});
ansButton.setVisible(true);
ansButton.setFocusable(false);
}
首先说明的是,如果想要点击按钮,然后还想要关闭按钮,需要用到多线程的技术。
我建立了一个内部类,好共用变量。
class LookWay extends Thread {
@Override
public void run() {
while (!isSucceed && buttonOpen) {
//todo
int[][] xy = getSELFxy();
int selfX = xy[0][0];
int selfY = xy[0][1];
moveDirect(selfX, selfY);
//System.out.println(selfX + " " + selfY);
//printMap();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
每个0.1秒执行一次moveDirect方法,这个方法会找到之前传过来的map,与此同时也有一份ansMap,在这里保存了需要的答案,在之前的文章中,介绍了答案的位置是6,所以那个方法仅仅只是遍历四周,然后找到6,执行移动方法即可。(goUp之类的方法在上一个文章中写明,如果需要,请您返回看一下)
private void moveDirect(int x, int y) {
for (int i = 0; i < 4; i++) {
if (map[x + dir[i][0]][y + dir[i][1]] == ANS
|| map[x + dir[i][0]][y + dir[i][1]] == END) {
if (i == 0) {
goUp();
System.out.println(i);
return;
} else if (i == 1) {
goDown();
System.out.println(i);
return;
} else if (i == 2) {
goLeft();
System.out.println(i);
return;
} else if (i == 3) {
goRight();
System.out.println(i);
return;
}
}
}
}
}
当然,如果您想中途暂停,也是可以的,但是暂停以后就无法再使用按钮了。
在起始点点击后的情况:
点击后想再打开:
还有一些细节就请您继续探索啦!如果大佬们能够提出宝贵意见或者进行功能的完善的话,我将感激涕零!
代码地址:
百度网盘地址:
链接:https://pan.baidu.com/s/1YTArg_iub13-qiKqF2e4ig
提取码:xiga