一、 游戏实现的主要功能
1、用户可以选择级别并且重新开始游戏;
2、具有计时功能,即显示用户完成所有扫雷任务所使用的时间;
3、可显示剩余雷数,当用户插旗后雷数减1;
4、左键点击打开空格,右键点击插旗,左右键双击翻开周围未插旗的空格;
5、当找出全部的雷后,提示游戏结束。
二、游戏设计与实现
1 扫雷游戏界面设计
系统的整体布局为:空布局,采用了菜单、按钮、面板、标签等组件,菜单主要包括开始游戏、选择级别、退出等选项;按钮包括雷区按钮、笑脸按钮、数字按钮等,面板是标签的容器包括雷的数量、时间等信息。- package com.game.mine;
- import java.awt.*;
- import java.awt.event.*;
- import javax.swing.*;
- /**
- * 功能:游戏窗口
- */
- public class GameFrame extends JFrame implements ActionListener
- {
- private GamePanel panel;
- JMenuItem JEasy, JNormal, JHigh;
- public GameFrame()
- {
- try
- {
- //窗口
- this.setTitle("扫雷");
- this.setLayout(null);
- this.setBackground(Color.WHITE);
- this.setResizable(false);
- this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- //菜单
- JMenuBar JMine = new JMenuBar();
- JMenu JGame = new JMenu("游戏");
- JGame.setFont(new Font("宋体",Font.PLAIN,14));
- JMenuItem JNew = JGame.add(" 开始");
- JNew.setFont(new Font("宋体",Font.PLAIN,14));
- JNew.addActionListener(this);
- JNew.setActionCommand("new");
- JGame.addSeparator();
- this.JEasy = JGame.add("√ 初级");
- this.JEasy.setFont(new Font("宋体",Font.PLAIN,14));
- this.JEasy.addActionListener(this);
- this.JEasy.setActionCommand("easy");
- this.JNormal = JGame.add(" 中级");
- this.JNormal.setFont(new Font("宋体",Font.PLAIN,14));
- this.JNormal.addActionListener(this);
- this.JNormal.setActionCommand("normal");
- this.JHigh = JGame.add(" 高级");
- this.JHigh.setFont(new Font("宋体",Font.PLAIN,14));
- this.JHigh.addActionListener(this);
- this.JHigh.setActionCommand("hard");
- JGame.addSeparator();
- JMenuItem JExit = JGame.add(" 退出");
- JExit.setFont(new Font("宋体",Font.PLAIN,14));
- JExit.addActionListener(this);
- JExit.setActionCommand("exit");
- JMine.add(JGame);
- JMenu JHelp = new JMenu("帮助");
- JHelp.setFont(new Font("宋体",Font.PLAIN,14));
- JMenuItem JAbout = JHelp.add("关于");
- JAbout.setFont(new Font("宋体",Font.PLAIN,14));
- JAbout.addActionListener(this);
- JAbout.setActionCommand("about");
- JMine.add(JHelp);
- this.setJMenuBar(JMine);
- //面板
- this.panel = new GamePanel();
- this.add(this.panel);
- //显示
- this.panel.setLevel(this.panel.EASY);
- this.setSize(this.panel.getWidth() + 15,this.panel.getHeight() + 60);
- this.setLocationRelativeTo(null);
- this.setVisible(true);
- }
- catch(Exception e)
- {
- JOptionPane.showMessageDialog(this,"程序出现异常错误,即将退出!\r\n\r\n"+ e,
- "提示",JOptionPane.ERROR_MESSAGE);
- System.exit(0);
- }
- }
- @Override
- public void actionPerformed(ActionEvent e)
- {
- String command = e.getActionCommand();
- if("new".equals(command))
- {
- this.panel.newGame();
- }
- else if("easy".equals(command))
- {
- this.JEasy.setText("√ 初级");
- this.JNormal.setText(" 中级");
- this.JHigh.setText(" 高级");
- this.panel.setLevel(this.panel.EASY);
- this.setSize(this.panel.getWidth() + 15,this.panel.getHeight() + 60);
- this.setLocationRelativeTo(null);
- }
- else if("normal".equals(command))
- {
- this.JEasy.setText(" 初级");
- this.JNormal.setText("√ 中级");
- this.JHigh.setText(" 高级");
- this.panel.setLevel(this.panel.NORMAL);
- this.setSize(this.panel.getWidth() + 15,this.panel.getHeight() + 60);
- this.setLocationRelativeTo(null);
- }
- else if("hard".equals(command))
- {
- this.JEasy.setText(" 初级");
- this.JNormal.setText(" 中级");
- this.JHigh.setText("√ 高级");
- this.panel.setLevel(this.panel.HARD);
- this.setSize(this.panel.getWidth() + 15,this.panel.getHeight() + 60);
- this.setLocationRelativeTo(null);
- }
- else if("exit".equals(command))
- {
- System.exit(0);
- }
- else if("about".equals(command))
- {
- JOptionPane.showMessageDialog(this,
- "1、左键用于打开安全的格子,推进游戏进度;右键用于标记地雷,以辅助判断,或为接下来的双击做准备;\n" +
- "双击在一个数字周围的地雷标记完时,相当于对数字周围未打开的方块均进行一次左键单击操作:\n" +
- "2、左键单击:在判断出不是雷的方块上按下左键,可以打开该方块。如果方块上出现数字,则该数字表示\n" +
- "其周围3×3区域中的地雷数(一般为8个格子,对于边块为5个格子,对于角块为3个格子。所以扫雷中最大\n" +
- "的数字为8);如果方块上为空(相当于0),则可以递归地打开与空相邻的方块;如果踩雷,则游戏结束。\n" +
- "3、右键单击:在判断为地雷的方块上按下右键,可以标记地雷(显示为小红旗)。重复一次或两次操作可\n" +
- "标记?或取消标记。\n" +
- "4、双击:同时按下左键和右键完成双击。当双击位置周围已标记雷数等于该位置数字时操作有效,相当于\n" +
- "对该数字周围未打开的方块均进行一次左键单击操作。地雷未标记完全时使用双击无效。若数字周围有标错\n" +
- "的地雷,则游戏结束,标错的地雷上会显示一个判断错误标志。","提示",JOptionPane.INFORMATION_MESSAGE);
- }
- }
- }
复制代码 2 雷区的设计
GamePanel类是JPanel容器的子类,实现了ActionListener和MouseListener接口所创建的对象:GamePanel()构造方法是GamePanel类中最重要的成员之一。其中GamePanel类的主要方法如下:
(1)initGame()方法可根据参数提供的数据设置雷区的宽度、高度、雷的数目以及计时器置零、初始化游戏界面。
(2)loadImage()方法加载数字图片、空格图片、雷图片、小红旗图片以及各种需要的图片。
(3)setLevel(int level)方法根据传入的参数根据不同的游戏难度重新设置主面板尺寸、重新设置组件位置、重新设置雷数、重新放置地雷位置以及时间清零等。
(4)newGame()方法调用initGame()方法初始化界面然后开始新游戏。
(5)actionPerformed(ActionEvent e)是GamePanel类实现的ActionListener接口中的方法。当用户单击雷区中的中的某个方块时,游戏开始定时器开始计时,单击笑脸按钮初始游戏界面开始新游戏。
(6)mousePressed(MouseEvent e)方法是GamePanel类实现的MouseListener接口中的方法,当用户按下鼠标时如果游戏结束退出游戏,如果游戏未开始,开始新游戏。
(7)mouseReleased(MouseEvent e)方法是GamePanel类实现的MouseListener
接口中的方法,分别定义了鼠标左键或右键后程序所执行的动作。
(8)GamePanel()构造方法对面板,雷区组件以及游戏难度等进行初始化。
[code]package com.game.mine;import java.awt.*;import java.util.Map;import java.util.HashMap;import java.awt.event.*;import javax.swing.*;/** * 功能:游戏面板
*/public class GamePanel extends JPanel implements MouseListener,ActionListener{ private final GameLogic logic; /** 初级难度(9×9,10个地雷) */ final int EASY = 1; /** 中级难度(16×16,40个地雷) */ final int NORMAL = 2; /** 高级难度(30×16,99个地雷) */ final int HARD = 3; /** 上次游戏难度 */ private int oldLevel = -1; /** 网格行数 */ int gridRows; /** 网格列数 */ int gridColumns; /** 网格尺寸 */ final int gridSize = 30; /** 地雷数 */ int mineNum; /** 提示区面板 */ private final JPanel panelTip = new JPanel(); /** 地雷区面板 */ private final JPanel panelMine = new JPanel(); /** 笑脸按钮 */ private final JButton buttonFace = new JButton(); /** 地雷数提示标签 */ JLabel[] labelMineTip = new JLabel[3]; /** 时间提示标签 */ JLabel[] labelTimeTip = new JLabel[3]; /** 地雷按钮数组 */ JButton[][] buttonMine = new JButton[16][30]; /** * 地雷信息数组 * number->地雷数:-1-地雷,0到8-周围地雷数 * flag->地雷状态:0-未打开,1-已打开,2-插小旗,3-插问号 */ @SuppressWarnings("unchecked") //数组不支持泛型 Map[][] mapMine = new Map[16][30]; /** 笑脸图片 */ private final ImageIcon[] imageIconFace = new ImageIcon[2]; /** 时间、雷数提示图片 */ ImageIcon[] imageIconNumberTip = new ImageIcon[10]; /** 数字图片 */ ImageIcon[] imageIconNumber = new ImageIcon[9]; /** 空白图片 */ ImageIcon imageIconBlank = new ImageIcon("res/resource/mine/blank.gif"); /** 方格图片 */ ImageIcon imageIconCell = new ImageIcon("res/resource/mine/cell.gif"); /** 红旗图片 */ ImageIcon imageIconFlag = new ImageIcon("res/resource/mine/flag.gif"); /** 问号图片 */ ImageIcon imageIconQuestion = new ImageIcon("res/resource/mine/question.gif"); /** 地雷图片 */ ImageIcon imageIconMine = new ImageIcon("res/resource/mine/mine.gif"); /** 爆炸图片 */ ImageIcon imageIconBomb = new ImageIcon("res/resource/mine/bomb.gif"); /** 找雷错误图片 */ ImageIcon imageIconWrongMine = new ImageIcon("res/resource/mine/wrong mine.gif"); /** 时间提示数字 */ int timeTip = 0; /** 扫雷提示数字 */ int mineTip = 0; /** 计时器 */ Timer timer = new Timer(1000,this); /** 游戏是否开始(true-开始,false-未开始) */ boolean isStart = false; /** 游戏是否结束(true-结束,false-未结束) */ boolean isGameOver = true; public GamePanel() { //主面板初始化 this.setBackground(Color.LIGHT_GRAY); this.setBorder(BorderFactory.createRaisedBevelBorder()); //边框凸起 this.setLayout(null); //自由布局 //提示区面板初始化 this.panelTip.setBackground(Color.LIGHT_GRAY); this.panelTip.setBorder(BorderFactory.createLoweredBevelBorder()); //边框下凹 this.panelTip.setLayout(null); this.add(this.panelTip); //地雷区面板初始化 this.panelMine.setBackground(Color.LIGHT_GRAY); this.panelMine.setBorder(BorderFactory.createLoweredBevelBorder()); //边框下凹 this.add(this.panelMine); //地雷数提示标签初始化 for(int i=0;i |