⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mazegame.java

📁 一个迷宫游戏,最大特色是可以随机生成迷宫,可以遍历迷宫得到答案,可以在迷宫中添加追赶者.随机生成迷宫算法和遍历算法比较经典,可提供参考.
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;

/**
 * 一个2D迷宫游戏.
 * 
 * @author 山
 * 
 */
public class MazeGame {// 主方法
	public static void main(String[] args) {
		JFrame frame = new JFrame("迷宫游戏");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		frame.getContentPane().add(new MazeGamePanel());

		frame.pack();
		frame.setVisible(true);
	}
}

class MazeGamePanel extends JPanel {// 主面板:显示迷宫以及定义相关操作.
	private final int DELAY = 10,CHASEDELAY=3500;//定时器延迟时间,无墙模式追赶者移动延迟时间
	private final int checkSizeDefault = 20, widthDefault = 45,
			heightDefault = 25, numberOfChasersDefault = 20,
			tearDownAllowedDefault = 10;// 默认值
	private final int panelWidth = 1024, panelHeight = 750;// 主面板宽,高
	private int checkSize, width, height, numberOfChasers, tearDownAllowed;
	// 迷宫的单位方格大小(以像素为单位),迷宫的宽度(方格数),迷宫的高度(方格数),追赶者数目,玩家可拆墙次数限制
	private Maze maze;// 一个迷宫面板
	private JButton tipButton,solve, newMaze, chase, newSure,newCancel,noWalls;
	// 解答开关按键,生成新迷宫按键,追赶者开关按键,制造新迷宫确定取消按键,无墙模式按键
	private boolean tipControl,solveControl,chaseControl;//开关按键控制:true为目前开启,false为目前关闭
	private JLabel help, tip, tearDownAllowedTimes;// 帮助标签,提示标签
	private Timer timer;// 定时器:每隔10毫秒就获取当前游戏结果和当前提示.注意:迷宫开始,计时器开始;迷宫停止(指玩家输或赢),计时器停止
	// (由于玩家不动也有可能被追赶成功,因此不推荐在每次移动时作出判断)
	private JLabel checkSizeLabel, widthLabel, heightLabel,
			numberOfChasersLabel, tearDownAllowedLabel;// 滑动条提示
	private JSlider checkSizeSlider, widthSlider, heightSlider,
			numberOfChasersSlider, tearDownAllowedSlider;// 滑动条
	private JPanel mazeMaker;// 迷宫制造者:通过滑动条制造迷宫.仅当玩家点击"制造新迷宫"或输或赢时才可见
	private JScrollPane mazeContainer;//存放迷宫面板的滚动窗格
	private boolean noWallsControl;//无墙模式控制

	public MazeGamePanel() {
		checkSize = checkSizeDefault;// 初始化一个迷宫:方格边长:20像素
		width = widthDefault;// 宽35个方格
		height = heightDefault;// 高25个方格.即迷宫面板大小为500*700
		numberOfChasers = numberOfChasersDefault;// 默认两个追赶者
		tearDownAllowed = tearDownAllowedDefault;// 默认不能拆墙

		maze = new Maze(checkSize, width, height, numberOfChasers,
				tearDownAllowed);// 根据上面的设置来初始化迷宫

		tipButton=new JButton("开启/关闭 提示");
		tipControl=false;
		chase = new JButton("开启/关闭 追赶者");
		chaseControl=true;
		solve = new JButton("开启/关闭 答案");
		solveControl=false;
		
		newMaze = new JButton("制造新迷宫");
		
		noWalls=new JButton("无墙模式");
		noWallsControl=false;//默认有墙模式
		
		newSure = new JButton("确定");
		newCancel = new JButton("取消");
		help = new JLabel(maze.help()+ "请 按 方 向 建 移 动. 按 W,S,A,D 拆除 上,下,左,右 墙.");
		//按键功能与Maze类无关
		tip = new JLabel(maze.currentTip());
		tearDownAllowedTimes = new JLabel("剩余可拆墙次数:"
				+ maze.tearDownAllowedTimes());

		timer = new Timer(DELAY, new TimerListener());
		timer.start();// 注意:迷宫开始,计时器开始;迷宫停止(指玩家输或赢),计时器停止

		maze.addKeyListener(new KeyBoardListener());// 迷宫面板添加键盘监听器
		maze.setFocusable(true);

		checkSizeSlider = new JSlider(JSlider.HORIZONTAL, 5, 50,
				checkSizeDefault);
		checkSizeSlider.setMajorTickSpacing(5);
		checkSizeSlider.setPaintTicks(true);
		checkSizeSlider.setPaintLabels(true);
		checkSizeSlider.setAlignmentX(Component.LEFT_ALIGNMENT);

		widthSlider = new JSlider(JSlider.HORIZONTAL, 10, 50, widthDefault);
		widthSlider.setMajorTickSpacing(5);
		widthSlider.setPaintTicks(true);
		widthSlider.setPaintLabels(true);
		widthSlider.setAlignmentX(Component.LEFT_ALIGNMENT);

		heightSlider = new JSlider(JSlider.HORIZONTAL, 10, 40, heightDefault);
		heightSlider.setMajorTickSpacing(5);
		heightSlider.setPaintTicks(true);
		heightSlider.setPaintLabels(true);
		heightSlider.setAlignmentX(Component.LEFT_ALIGNMENT);

		numberOfChasersSlider = new JSlider(JSlider.HORIZONTAL, 0, 50,
				numberOfChasersDefault);
		numberOfChasersSlider.setMajorTickSpacing(5);
		numberOfChasersSlider.setPaintTicks(true);
		numberOfChasersSlider.setPaintLabels(true);
		numberOfChasersSlider.setAlignmentX(Component.LEFT_ALIGNMENT);

		tearDownAllowedSlider = new JSlider(JSlider.HORIZONTAL, -1, 30,
				tearDownAllowedDefault);
		tearDownAllowedSlider.setMajorTickSpacing(5);
		tearDownAllowedSlider.setPaintTicks(true);
		tearDownAllowedSlider.setPaintLabels(true);
		tearDownAllowedSlider.setAlignmentX(Component.LEFT_ALIGNMENT);
		
		maze.setPreferredSize(new Dimension(panelWidth,panelHeight));
		//用setPreferredSize设置加入到滚动窗格的面板的大小才可以使滚动窗格有效
		mazeContainer=new JScrollPane(maze);//迷宫面板放到滚动窗格中
		mazeContainer.setEnabled(false);//这样可以使JScrollPane不响应键盘,只响应鼠标.这样走迷宫会好一点

		SliderListener listener = new SliderListener();
		checkSizeSlider.addChangeListener(listener);
		widthSlider.addChangeListener(listener);
		heightSlider.addChangeListener(listener);
		numberOfChasersSlider.addChangeListener(listener);
		tearDownAllowedSlider.addChangeListener(listener);

		checkSizeLabel = new JLabel("小方格边长(以像素为单位):" + checkSizeDefault);
		widthLabel = new JLabel("宽度(方格数):" + widthDefault);
		heightLabel = new JLabel("高度(方格数):" + heightDefault);
		numberOfChasersLabel = new JLabel("追赶者数目(可设为0):"
				+ numberOfChasersDefault);
		tearDownAllowedLabel = new JLabel("可拆墙限制次数(设为-1则不限次数,设为0则不能拆墙):"
				+ tearDownAllowedDefault);

		ButtonListener bListener = new ButtonListener();
		chase.addActionListener(bListener);
		solve.addActionListener(bListener);
		tipButton.addActionListener(bListener);
		newMaze.addActionListener(bListener);
		noWalls.addActionListener(bListener);
		newSure.addActionListener(bListener);
		newCancel.addActionListener(bListener);// 添加按键监听器

		JLabel title=new JLabel("迷     宫     制     造     者");
		mazeMaker = new JPanel();
		mazeMaker.setLayout(new BoxLayout(mazeMaker, BoxLayout.Y_AXIS));
		mazeMaker.add(title);
		mazeMaker.add(Box.createRigidArea(new Dimension(0, 50)));
		mazeMaker.add(checkSizeLabel);
		mazeMaker.add(checkSizeSlider);
		mazeMaker.add(Box.createRigidArea(new Dimension(0, 30)));
		mazeMaker.add(widthLabel);
		mazeMaker.add(widthSlider);
		mazeMaker.add(Box.createRigidArea(new Dimension(0, 30)));
		mazeMaker.add(heightLabel);
		mazeMaker.add(heightSlider);
		mazeMaker.add(Box.createRigidArea(new Dimension(0, 30)));
		mazeMaker.add(numberOfChasersLabel);
		mazeMaker.add(numberOfChasersSlider);
		mazeMaker.add(Box.createRigidArea(new Dimension(0, 30)));
		mazeMaker.add(tearDownAllowedLabel);
		mazeMaker.add(tearDownAllowedSlider);
		JPanel controls = new JPanel();
		controls.setLayout(new BoxLayout(controls, BoxLayout.X_AXIS));
		controls.add(newSure);
		controls.add(newCancel);
		mazeMaker.add(Box.createRigidArea(new Dimension(0, 50)));
		mazeMaker.add(controls);
		mazeMaker.add(Box.createRigidArea(new Dimension(0, panelHeight)));
		// 加上以上语句,在显示mazeMaker的时候就不会显示到迷宫,比较美观
		mazeMaker.setPreferredSize(new Dimension(panelWidth, panelHeight));
		mazeMaker.setVisible(false);// 仅当玩家点击"制造新迷宫"或输或赢时才可见

		JPanel labels = new JPanel();
		labels.setLayout(new BoxLayout(labels, BoxLayout.Y_AXIS));
		labels.add(tip);
		labels.add(tearDownAllowedTimes);
		labels.add(help);

		JPanel controlPanel = new JPanel();// 控制面板
		controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS));
		controlPanel.add(tipButton);
		controlPanel.add(chase);
		controlPanel.add(solve);
		controlPanel.add(newMaze);
		controlPanel.add(noWalls);

		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		add(mazeMaker);//迷宫制造者面板
		add(Box.createRigidArea(new Dimension(0, 20)));
		add(mazeContainer);//存放迷宫的滚动窗格
		add(Box.createRigidArea(new Dimension(0, 20)));
		add(labels);//所有标签存放的面板
		add(Box.createRigidArea(new Dimension(0, 20)));
		add(controlPanel);//控制面板:追赶者开关,答案开关,新迷宫按键
		setPreferredSize(new Dimension(panelWidth, panelHeight));
	}

	private class TimerListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			if(tipControl==true)
			tip.setText(maze.currentTip());// 提示和可拆墙剩余次数最好都随时更新
			else
				tip.setText("提示已关闭");
				
			tearDownAllowedTimes.setText("剩余可拆墙次数:"
					+ maze.tearDownAllowedTimes());

			// 以下为判断当前玩家输赢状态
			if (maze.currentResult() == 1) {// 玩家已经到达终点
				timer.stop();
				// 必须要在此停止,否则因为timer仍在计时且两个if其中之一直成立
				int another = JOptionPane.showConfirmDialog(null,
						"恭喜到达终点! 现在要生成一个新迷宫并重新开始?");
				if (another == JOptionPane.YES_OPTION) {
					timer.stop();
					mazeMaker.setVisible(true);// 玩家确认制造新迷宫,则把迷宫制造者设为可见
				}
				maze.requestFocusInWindow();// 迷宫面板必须要重获焦点(不能把这句放在if语句外,因为timer定时执行,会使maze不断获得焦点)
			} else if (maze.currentResult() == -1) {// 玩家输了
				timer.stop();
				// 必须要在此停止,否则因为timer仍在计时且两个if其中之一直成立
				int another = JOptionPane.showConfirmDialog(null,
						"你输啦! 现在要生成一个新迷宫并重新开始?");
				if (another == JOptionPane.YES_OPTION) {
					timer.stop();
					mazeMaker.setVisible(true);// 玩家确认制造新迷宫,则把迷宫制造者设为可见
				}
				maze.requestFocusInWindow();// 迷宫面板必须要重获焦点(不能把这句放在if语句外,因为timer定时执行,会使maze不断获得焦点)
			}
		}
	}

	private class KeyBoardListener extends KeyAdapter {
		public void keyPressed(KeyEvent e) {
			switch (e.getKeyCode()) {
			case KeyEvent.VK_UP:
				maze.move(2);
				break;
			case KeyEvent.VK_DOWN:
				maze.move(4);
				break;
			case KeyEvent.VK_LEFT:
				maze.move(1);
				break;
			case KeyEvent.VK_RIGHT:
				maze.move(3);
				break;
			case KeyEvent.VK_W: {
				maze.tearDown(2);
				tearDownAllowedTimes.setText("剩余可拆墙次数:"
						+ maze.tearDownAllowedTimes());
			}
				break;
			case KeyEvent.VK_S: {
				maze.tearDown(4);
				tearDownAllowedTimes.setText("剩余可拆墙次数:"
						+ maze.tearDownAllowedTimes());
			}
				break;
			case KeyEvent.VK_A: {
				maze.tearDown(1);
				tearDownAllowedTimes.setText("剩余可拆墙次数:"
						+ maze.tearDownAllowedTimes());
			}
				break;
			case KeyEvent.VK_D: {
				maze.tearDown(3);
				tearDownAllowedTimes.setText("剩余可拆墙次数:"
						+ maze.tearDownAllowedTimes());
			}
				break;
			case KeyEvent.VK_I://保护
				maze.protectEnabled(true);
				break;
			case KeyEvent.VK_O://非保护
				maze.protectEnabled(false);
				break;
			case KeyEvent.VK_P://可变范围拆墙
				maze.variableTearDown(3, 3);
				break;
			}
		}
	}

	private class ButtonListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			if (e.getSource() == chase){
				if(chaseControl==false){
				maze.chaseOn();chaseControl=true;}
				else 
					{maze.chaseOff();chaseControl=false;}
				}
			else if (e.getSource() == solve){
				if(solveControl==false){
				maze.solveOn();solveControl=true;}
				else {
					maze.solveOff();solveControl=false;}
			}
			else if (e.getSource() == tipButton){
				if(tipControl==true)tipControl=false;
				else
					tipControl=true;//在timer监听器中判断即可
			}
			else if (e.getSource() == newSure) {
				if(noWallsControl==true){
				mazeMaker.setVisible(false);// 玩家能点击到这个按键说明已被设为可见,现在要重设为不可见
				maze.noWalls(checkSizeSlider.getValue(),
						widthSlider.getValue(), heightSlider.getValue(),
						numberOfChasersSlider.getValue(),CHASEDELAY);
				timer.start();// 计时器与迷宫一起启动
				}else{
					mazeMaker.setVisible(false);// 玩家能点击到这个按键说明已被设为可见,现在要重设为不可见
					maze.newMaze(checkSizeSlider.getValue(),
							widthSlider.getValue(), heightSlider.getValue(),
							numberOfChasersSlider.getValue(), tearDownAllowedSlider
									.getValue());
					timer.start();// 计时器与迷宫一起启动
				}
				if(tipControl==true)tipControl=false;
				if(chaseControl==false)chaseControl=true;
				if(solveControl==true)solveControl=false;//重置
			} else if (e.getSource() == newCancel)
				mazeMaker.setVisible(false);// 玩家能点击到这个按键说明已被设为可见,现在要重设为不可见
			else if(e.getSource()==noWalls){
				timer.stop();
				noWallsControl=true;//设为无墙模式
				mazeMaker.setVisible(true);// 玩家点击制造无墙迷宫,则把迷宫制造者设为可见
			}
			else {//玩家按newMaze
				timer.stop();
				noWallsControl=false;//设为有墙模式
				mazeMaker.setVisible(true);// 玩家点击制造新迷宫,则把迷宫制造者设为可见
			}
			maze.requestFocusInWindow();// 在按了键后迷宫面板必须要重获焦点
		}
	}

	private class SliderListener implements ChangeListener {
		public void stateChanged(ChangeEvent e) {// 注意:此方法若可执行,说明mazeMaker此时必定可见
			checkSizeLabel.setText("小方格边长(以像素为单位):"
					+ checkSizeSlider.getValue());
			widthLabel.setText("宽度(方格数):" + widthSlider.getValue());
			heightLabel.setText("高度(方格数):" + heightSlider.getValue());
			numberOfChasersLabel.setText("追赶者数目(可设为0):"
					+ numberOfChasersSlider.getValue());
			tearDownAllowedLabel.setText("可拆墙限制次数(设为-1则不限次数,设为0则不能拆墙):"
					+ tearDownAllowedSlider.getValue());
		}

	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -