Java迷宫小游戏,老程序员花一天时间完成,你可以吗?

Posted 编程界明世隐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java迷宫小游戏,老程序员花一天时间完成,你可以吗?相关的知识,希望对你有一定的参考价值。

Java迷宫,老程序员又来了

作者简介

作者名:编程界明世隐
简介:CSDN博客专家,从事软件开发多年,精通Java、javascript,博主也是从零开始一步步把学习成长、深知学习和积累的重要性,喜欢跟广大ADC一起打野升级,欢迎您关注,期待与您一起学习、成长、起飞!

系列目录

1. Java俄罗斯方块
2. Java五子棋小游戏
3. 老Java程序员花一天时间写了个飞机大战
4. Java植物大战僵尸
5. 老Java程序员花2天写了个连连看
6. Java消消乐(天天爱消除)
7. Java贪吃蛇小游戏
8. Java扫雷小游戏
9. Java坦克大战

效果图

实现思路

1.创建运行窗口。
2.创建菜单。
3.绘制迷宫的每个单元。
4.通过算法计算迷宫路径,并打通路径,形成迷宫。
5.绘制起点终点。
6.添加键盘事件控制起点方块移动。
7.收尾。

迷宫算法(网上参考的)

  1. 将起点作为当前迷宫单元并标记为已访问
  2. 当还存在未标记的迷宫单元,进行循环
    1).如果当前迷宫单元有未被访问过的的相邻的迷宫单元
       (1).随机选择一个未访问的相邻迷宫单元
       (2).将当前迷宫单元入栈
       (3).移除当前迷宫单元与相邻迷宫单元的墙
       (4).标记相邻迷宫单元并用它作为当前迷宫单元
    2).如果当前迷宫单元不存在未访问的相邻迷宫单元,并且栈不空
       (1).栈顶的迷宫单元出栈
       (2).令其成为当前迷宫单元

**这个算法叫做“深度优先”,简单来说,就是从起点开始走,寻找它的上下左右4个邻居,然后随机一个走,到走不通的时候就返回上一步继续走,直到全部单元都走完。 **

相关图示说明

  1. 每个单元的墙,分为上墙、右墙、下墙、左墙,把这些墙用长度为4的数组表示,元素的值为true则表示墙存在,否则墙不存在,代码里数组的下标方式来确定墙是否存在。
  2. 单元是根据行列来创建的,会用到双循环,类似表格,比如第二行用 i 来表示的话就是 1,第3列用 j 来表示就是2,那第二行第3列的元素组合起来就是(1,2)
  3. 那同理它的上邻居就是(0,2),右邻居(1,3),下邻居(2,2),左邻居(1,1),也就是上下邻居是 i 减加1,左右邻居是 j 减加1。
  4. 正方形4个点的坐标分别为(x1,y1)(x2,y2)(x3,y3)(x4,y4),计算坐标的公式为(其中start为相对偏移量,为了让迷宫两边有些空隙):
//i代表行 j代表列 h为单元高度
//左上角坐标
this.x1=start+j*h;
this.y1=start+i*h;
//右上角坐标
this.x2=start+(j+1)*h;
this.y2=start+i*h;
//右下角坐标
this.x3=start+(j+1)*h;
this.y3=start+(i+1)*h;
//左下角坐标
this.x4=start+j*h;
this.y4=start+(i+1)*h;	

计算坐标,假如每个正方形的宽高都是40,那么(1,2)这个单元的坐标如下图:

5. 墙的处理,之前说到墙是以一个4个元素的数组来表示的,比如数组为:[true,true,true,true],则图为:

如果数组为[false,true,true,true],则图为:

6. 如果要联通右边的邻居要怎么做呢?当前单元去除右墙,右边单元去除左墙,这样就联通了。

去除后就这样,以此类推

代码实现

创建窗口

首先创建一个游戏窗体类GameFrame,继承至JFrame,用来显示在屏幕上(window的对象),每个游戏都有一个窗口,设置好窗口标题、尺寸、布局等就可以。

import javax.swing.JFrame;
/**
 *窗体类
 */
public class GameFrame extends JFrame {
	//构造方法
	public GameFrame(){
		setTitle("迷宫");//设置标题
		setSize(420, 470);//设置窗体大小
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭后进程退出
		setLocationRelativeTo(null);//居中
		setResizable(false);//不允许变大
		//setVisible(true);//设置显示窗体
	}
}

创建面板容器GamePanel继承至JPanel

import javax.swing.JMenuBar;
import javax.swing.JPanel;

/*
 * 画布类
 */
public class GamePanel extends JPanel{
	private JMenuBar jmb = null;
	private GameFrame mainFrame = null;
	private GamePanel panel = null;
	private String gameFlag="start";//游戏状态
	//构造方法
	public GamePanel(GameFrame mainFrame){
		this.setLayout(null);
		this.setOpaque(false);
		this.mainFrame=mainFrame;
		this.panel =this;
	}
}

再创建一个Main类,来启动这个窗口。

//Main类
public class Main {

	public static void main(String[] args) {
		GameFrame frame = new GameFrame();
		GamePanel panel = new GamePanel(frame);
		frame.add(panel);
		frame.setVisible(true);
	}
}

右键执行这个Main类,窗口建出来了

创建菜单及菜单选项

创建菜单

private Font createFont(){
	return new Font("思源宋体",Font.BOLD,18);
}
//创建菜单
private void createMenu() {
	//创建JMenuBar
	jmb = new JMenuBar();
	//取得字体
	Font tFont = createFont(); 
	//创建游戏选项
	JMenu jMenu1 = new JMenu("游戏");
	jMenu1.setFont(tFont);
	//创建帮助选项
	JMenu jMenu2 = new JMenu("帮助");
	jMenu2.setFont(tFont);
	
	JMenuItem jmi1 = new JMenuItem("新游戏");
	jmi1.setFont(tFont);
	JMenuItem jmi2 = new JMenuItem("退出");
	jmi2.setFont(tFont);
	//jmi1 jmi2添加到菜单项“游戏”中
	jMenu1.add(jmi1);
	jMenu1.add(jmi2);
	
	JMenuItem jmi3 = new JMenuItem("操作帮助");
	jmi3.setFont(tFont);
	JMenuItem jmi4 = new JMenuItem("胜利条件");
	jmi4.setFont(tFont);
	//jmi13 jmi4添加到菜单项“游戏”中
	jMenu2.add(jmi3);
	jMenu2.add(jmi4);
	
	
	jmb.add(jMenu1);
	jmb.add(jMenu2);
	
	mainFrame.setJMenuBar(jmb);
	//添加监听
	jmi1.addActionListener(this);
	jmi2.addActionListener(this);
	jmi3.addActionListener(this);
	jmi4.addActionListener(this);
	//设置指令
	jmi1.setActionCommand("restart");
	jmi2.setActionCommand("exit");
	jmi3.setActionCommand("help");
	jmi4.setActionCommand("win");
}

实现ActionListener并重写方法actionPerformed

此时GamePanel是报错的,需重写actionPerformed方法。
actionPerformed方法的实现

@Override
public void actionPerformed(ActionEvent e) {
	String command = e.getActionCommand();
	System.out.println(command);
	UIManager.put("OptionPane.buttonFont", new FontUIResource(new Font("思源宋体", Font.ITALIC, 18)));
	UIManager.put("OptionPane.messageFont", new FontUIResource(new Font("思源宋体", Font.ITALIC, 18)));
	if ("exit".equals(command)) {
		Object[] options = { "确定", "取消" };
		int response = JOptionPane.showOptionDialog(this, "您确认要退出吗", "",
				JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null,
				options, options[0]);
		if (response == 0) {
			System.exit(0);
		} 
	}else if("restart".equals(command)){
		restart();
	}else if("help".equals(command)){
		JOptionPane.showMessageDialog(null, "通过键盘的上下左右来移动",
				"提示!", JOptionPane.INFORMATION_MESSAGE);
	}else if("win".equals(command)){
		JOptionPane.showMessageDialog(null, "移动到终点获得胜利",
				"提示!", JOptionPane.INFORMATION_MESSAGE);
	}	
}

此时的GamePanel代码如下:

package main;

import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.plaf.FontUIResource;

/*
 * 画布类
 */
public class GamePanel extends JPanel implements ActionListener{
	private JMenuBar jmb = null;
	private GameFrame mainFrame = null;
	private GamePanel panel = null;
	private String gameFlag="start";//游戏状态
	//构造方法
	public GamePanel(GameFrame mainFrame){
		this.setLayout(null);
		this.setOpaque(false);
		this.mainFrame=mainFrame;
		this.panel =this;
		//创建菜单
		createMenu();
	}
	private Font createFont(){
		return new Font("思源宋体",Font.BOLD,18);
	}
	//创建菜单
	private void createMenu() {
		//创建JMenuBar
		jmb = new JMenuBar();
		//取得字体
		Font tFont = createFont(); 
		//创建游戏选项
		JMenu jMenu1 = new JMenu("游戏");
		jMenu1.setFont(tFont);
		//创建帮助选项
		JMenu jMenu2 = new JMenu("帮助");
		jMenu2.setFont(tFont);
		
		JMenuItem jmi1 = new JMenuItem("新游戏");
		jmi1.setFont(tFont);
		JMenuItem jmi2 = new JMenuItem("退出");
		jmi2.setFont(tFont);
		//jmi1 jmi2添加到菜单项“游戏”中
		jMenu1.add(jmi1);
		jMenu1.add(jmi2);
		
		JMenuItem jmi3 = new JMenuItem("操作帮助");
		jmi3.setFont(tFont);
		JMenuItem jmi4 = new JMenuItem("胜利条件");
		jmi4.setFont(tFont);
		//jmi13 jmi4添加到菜单项“游戏”中
		jMenu2.add(jmi3);
		jMenu2.add(jmi4);
		
		
		jmb.add(jMenu1);
		jmb.add(jMenu2);
		
		mainFrame.setJMenuBar(jmb);
		//添加监听
		jmi1.addActionListener(this);
		jmi2.addActionListener(this);
		jmi3.addActionListener(this);
		jmi4.addActionListener(this);
		//设置指令
		jmi1.setActionCommand("restart");
		jmi2.setActionCommand("exit");
		jmi3.setActionCommand("help");
		jmi4.setActionCommand("win");
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		String command = e.getActionCommand();
		System.out.println(command);
		UIManager.put("OptionPane.buttonFont", new FontUIResource(new Font("思源宋体", Font.ITALIC, 18)));
		UIManager.put("OptionPane.messageFont", new FontUIResource(new Font("思源宋体", Font.ITALIC, 18)));
		if ("exit".equals(command)) {
			Object[] options = { "确定", "取消" };
			int response = JOptionPane.showOptionDialog(this, "您确认要退出吗", "",
					JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null,
					options, options[0]);
			if (response == 0) {
				System.exit(0);
			} 
		}else if("restart".equals(command)){
			restart();
		}else if("help".equals(command)){
			JOptionPane.showMessageDialog(null, "通过键盘的上下左右来移动",
					"提示!", JOptionPane.INFORMATION_MESSAGE);
		}else if("win".equals(command)){
			JOptionPane.showMessageDialog(null, "移动到终点获得胜利",
					"提示!", JOptionPane.INFORMATION_MESSAGE);
		}	
	}
	
	void restart(){
		
	}
	
}

运行它

绘制迷宫的每个单元

  1. 初始化相关参数
public final int ROWS=20;//行
public final int COLS=20;//列
public final int H=20;//每一块的宽高
Block[][] blocks = null;//存储每个单元的二维数组
  1. 创建迷宫单元类(如果对坐标计算不明白,可以往上翻,有图示说明解释)
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
/*
 * 迷宫单元类
 */
public class Block {
	private GamePanel panel = null;
	private int i=0;//二维数组的下标i
	private int j=0;//二维数组的下标j
	private int h=0;//宽高
	private int start=6;//偏移像素
	//4个顶点坐标
	private int x1=0;//x1坐标
	private int y1=0;//y1坐标
	private int x2=0;//x2坐标
	private int y2=0;//y2坐标
	private int x3=0;//x3坐标
	private int y3=0;//y3坐标
	private int x4=0;//x4坐标
	private int y4=0;//y4坐标
	//上下左右4个墙是否显示,true:显示&

以上是关于Java迷宫小游戏,老程序员花一天时间完成,你可以吗?的主要内容,如果未能解决你的问题,请参考以下文章

Java拼图游戏,老程序员花两天搞定,你呢?

JavaWeb图书管理系统,老程序员花一天一夜回忆学生时代

C系列Unity3D | 花一天时间做个经典小游戏Pacman

花一天时间做一个高质量飞机大战游戏,过万字Unity完整教程!漂亮学妹看了直呼666!

花一天时间做一个高逼格打飞机游戏,过万字Unity完整教程!漂亮学妹看了直呼打飞机666!

520,花一夜给女神写走迷宫游戏