随风而动,随遇而安......
Java实现扫雷小游戏一
05/18
本文最后更新于
2022年08月13日,已超过
849天没有更新。如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!
实现
项目结构分析
主界面
主窗体(com.main/MainFrame.java)
包含菜单栏、计数区panel和雷区panel。
(1)构造方法
public MainFrame() {
init();
this.setIconImage(Tools.getImageIcon().getImage()); // 设置图标
this.setTitle("扫雷"); // 设置标题
this.setSize(new Dimension(220,300)); // 窗口大小
this.setResizable(false); // 这样让窗口不可放大
this.setLocationRelativeTo(null);
this.setLocation(new Point(800,300)); // 设置窗口位置
this.setVisible(true); // 设置窗口显示
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭窗口
}
(2)初始化方法
private void init() {
// 菜单栏
this.setJMenuBar(menuBar);
}
菜单栏(com.panel/BombJMenuBar.java)
(1)添加菜单、菜单项等
public class BombJMenuBar extends JMenuBar {
// 菜单项
JMenu menuGame = new JMenu("游戏(G)");
JMenuItem menuItemStart = new JMenuItem("开局(N)");
JMenuItem menuItemLow = new JMenuItem("初级(B)");
JMenuItem menuItemMid = new JMenuItem("中级(I)");
JMenuItem menuItemHigh = new JMenuItem("高级(E)");
JMenu menuHero = new JMenu("英雄榜(T)");
JMenuItem menuHeroLow = new JMenuItem("初级英雄榜");
JMenuItem menuHeroMid = new JMenuItem("中级英雄榜");
JMenuItem menuHeroHigh = new JMenuItem("高级英雄榜");
JMenuItem menuItemOrder = new JMenuItem("自定义(C)");
JMenuItem menuItemExit = new JMenuItem("退出(X)");
JMenu menuHelp = new JMenu("帮助(H)");
JMenuItem menuItemAbout = new JMenuItem("关于扫雷(A)");
JMenuItem menuItemHole = new JMenuItem("外挂(W)");
// 需要在类中声明主窗体变量(属性):作为菜单栏与主窗体交互的媒介
// 声明主窗体对象
MainFrame mainframe;
// 编写构造函数和初始化界面方面
public BombJMenuBar(MainFrame mainframe) {
this.mainframe = mainframe;
init();
}
(2)初始化方法
public void init() {
// 设置快捷键
menuGame.setMnemonic('G'); // Alt + G
menuItemStart.setMnemonic('N');
menuItemLow.setMnemonic('B');
menuItemMid.setMnemonic('I');
menuItemHigh.setMnemonic('E');
menuHero.setMnemonic('T');
menuItemOrder.setMnemonic('C');
menuItemExit.setMnemonic('X');
menuHelp.setMnemonic('H');
menuItemAbout.setMnemonic('A');
menuItemHole.setMnemonic('W');
// 把菜单添加到菜单栏
// 游戏菜单
this.add(menuGame);
menuGame.add(menuItemStart);
menuGame.addSeparator(); // 添加分隔线
menuGame.add(menuItemLow);
menuGame.add(menuItemMid);
menuGame.add(menuItemHigh);
menuGame.addSeparator();
menuGame.add(menuHero);
menuHero.add(menuHeroLow);
menuHero.add(menuHeroMid);
menuHero.add(menuHeroHigh);
menuGame.addSeparator();
menuGame.add(menuItemOrder);
menuGame.addSeparator();
menuGame.add(menuItemExit);
// 帮助菜单
this.add(menuHelp);
menuHelp.add(menuItemAbout);
menuHelp.addSeparator();
menuHelp.add(menuItemHole);
}
运行
雷区(com.panel/BombJPanel)
雷区是由小方格组成,在众多小方格中随机布雷。(先设计MineLable)
(1)MineLable
public class MineLabel extends JLabel {
private boolean mineTag = false; // 判断是否是雷
private boolean expendTag = false; // 判断雷块是否展开
private boolean flagTag = false; // 判断雷块是否插了旗子
private int rowx; // 雷块所在的行
private int coly; // 雷块所在的列
private int countAround; // 计算雷块周围的雷数
private int rightClickCount; // 记录右键点击次数
}
(2)编写构造方法
public class BombJPanel extends JPanel {
// 定义属性
MineLabel[][] labels = new MineLabel[9][9];
// 声明主窗体对象
MainFrame mainframe;
MouListener listener;
public BombJPanel(MainFrame mainframe) {
this.mainframe = mainframe;
//定义布局方式,网格布局
this.setLayout(new GridLayout(Tools.rows, Tools.cols));
listener = new MouListener(labels,mainframe);
init();
}
程序写到这里很多地方都需要要到图片以及雷区行列数等,故定义工具类定义好一些可能在程序中多次用到且后期会改变的资源或者变量。见工具类Tools
(3)初始化
private void init() {
// 实例化小方格
for(int i = 0;i<labels.length;i++) {
for(int j = 0; j<labels[i].length;j++) {
labels[i][j] = new MineLabel(i, j);
labels[i][j].setIcon(Tools.blank);
this.add(labels[i][j]);
labels[i][j].addMouseListener(listener);
}
}
创建一个合成边框,指定了用于外部和内部边缘的 border 对象
在init() 里插入
// 实现边框效果
Border lowerBorder = BorderFactory.createLoweredBevelBorder();
Border emptyBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5); //边框大小
CompoundBorder compoundBorder = BorderFactory.createCompoundBorder(emptyBorder, lowerBorder);
this.setBorder(compoundBorder);
this.setBackground(Color.LIGHT_GRAY);
createLoweredBevelBorder();
创建一个具有凹入斜面边缘的边框,将组件当前背景色的较亮的色度用于高亮显示,较暗的色度用于阴影。
(在凹入边框中,阴影位于顶部,高亮显示位于其下。)
BorderFactory.createEmptyBorder(5, 5, 5, 5);
创建占用空间但不绘制的空边框,指定顶部、左侧、底部和右侧的宽度。
运行
在MainFrame的构造函数中添加 this.pack();
public MainFrame() {
init();
......
this.pack(); // 使控件更紧凑,窗口自动适应大小
......
}
运行
计数区(com.panel/FaceJPanel)
(1)定义雷的数量与时间显示
public class FaceJPanel extends JPanel {
// 雷数
private JLabel labelCountG = new JLabel(); // 个位
private JLabel labelCountS = new JLabel(); // 十位
private JLabel labelCountB = new JLabel(); // 百位
// 笑脸
private JLabel labelFace = new JLabel();
// 时间
private JLabel labelTimeG = new JLabel(); // 个位
private JLabel labelTimeS = new JLabel(); // 十位
private JLabel labelTimeB = new JLabel(); // 百位
// // 声明主窗体对象
MainFrame mainframe;
(2)编写构造方法
public FaceJPanel(MainFrame mainframe) {
this.mainframe = mainframe;
this.setLayout(new BorderLayout());
this.setVisible(true);
init();
}
(3)初始化
private void init() {
JPanel panel = new JPanel();
// 布局盒子
BoxLayout boxLayout = new BoxLayout(panel, BoxLayout.LINE_AXIS);
panel.setLayout(boxLayout);
labelFace.addMouseListener(new FacelabelListener()); // 添加表情按钮监听器
// 添加计数区监听器
panel.addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent arg0) {
if(!Tools.isBoom) {
labelFace.setIcon(Tools.face2);
}
}
public void mouseReleased(MouseEvent arg0) {
if(!Tools.isBoom) {
labelFace.setIcon(Tools.face0);
}
}
});
Icon icon0 = new ImageIcon("./image/d0.gif");
// 计算雷的每位数图片
Icon icon3 = new ImageIcon("./image/d" + Tools.allcount / 100 + ".gif");// 百位
Icon icon2 = new ImageIcon("./image/d" + Tools.allcount /10%10 + ".gif"); // 十位
Icon icon1 = new ImageIcon("./image/d" + Tools.allcount % 10 + ".gif"); // 个位
Icon iconSmile = new ImageIcon("./image/face0.gif");
// 雷数显示图片
labelCountG.setIcon(icon1);
labelCountS.setIcon(icon2);
labelCountB.setIcon(icon3);
// 时间显示图片
labelTimeG.setIcon(icon0);
labelTimeS.setIcon(icon0);
labelTimeB.setIcon(icon0);
// 表情显示图片
labelFace.setIcon(iconSmile);
// 添加控件到panel
panel.add(Box.createHorizontalStrut(2)); // 最左侧
panel.add(labelCountB);
panel.add(labelCountS);
panel.add(labelCountG);
panel.add(Box.createHorizontalGlue()); // 添加水平方向的构件,占位
panel.add(labelFace);
panel.add(Box.createHorizontalGlue());
panel.add(labelTimeB);
panel.add(labelTimeS);
panel.add(labelTimeG);
panel.add(Box.createHorizontalStrut(2)); // 最右侧
// 实现边框效果
Border borderLow = BorderFactory.createLoweredBevelBorder();
// 内边框
Border borderEmpty = BorderFactory.createEmptyBorder(2, 2, 2, 2);
Border borderCom1 = BorderFactory.createCompoundBorder(borderLow, borderEmpty);
panel.setBorder(borderCom1);
panel.setBackground(Color.LIGHT_GRAY);
// 外边框
Border borderEmpty1 = BorderFactory.createEmptyBorder(5, 5, 0, 5);
this.setBorder(borderEmpty1);
this.setBackground(Color.LIGHT_GRAY);
this.add(panel);
}
(4)在主窗体MainFrame中添加FaceJPanel
public class MainFrame extends JFrame{
......
private BombJMenuBar menuBar = new BombJMenuBar(this);
FaceJPanel faceJPanel = new FaceJPanel(this);
BombJPanel bombJPanel = new BombJPanel(this);
......
}
在init方法中插入
private void init() {
......
this.add(faceJPanel,layout.NORTH);
......
}
运行
工具类(com.tools/Tools)
public class Tools {
// 窗口图标
public static ImageIcon imageIcon = new ImageIcon("./image/icon.gif");
public static ImageIcon getImageIcon() {
return imageIcon;
}
public static int rows = 9; // 雷区行数
public static int cols = 9; // 雷区列数
public static int timecount = 0; // 计时
public static int allcount = 10; // 所有雷的数量
public static int bombCount = allcount; // 剩余为未被标记雷数
public static boolean isBoom = false; // 是否踩雷
public static boolean isStart = false; // 是否开始
public static boolean isHole = false; // 是否开启后门外挂
// 排行榜
public static int time = 0;
// 初级
public static int time1= 999;
public static int time2= 999;
public static int time3= 999;
public static String name1="匿名";
public static String name2="匿名";
public static String name3="匿名";
// 中级
public static int time01= 999;
public static int time02= 999;
public static int time03= 999;
public static String name01="匿名";
public static String name02="匿名";
public static String name03="匿名";
// 高级
public static int time001= 999;
public static int time002= 999;
public static int time003= 999;
public static String name001="匿名";
public static String name002="匿名";
public static String name003="匿名";
// 游戏等级
public static final String LOWER_LEVEL = "初级";
public static final String MIDDLE_LEVEL = "中级";
public static final String HEIGHT_LEVEL = "高级";
public static final String CUSTOM_LEVEL = "自定义";
// 游戏当前等级
public static String currentLevel = LOWER_LEVEL;
// 用来存放0-8地雷数字标签图片
public static ImageIcon mineCount[];
// 用来存放时间数字标签图片
public static ImageIcon timeCount[];
// 静态块
static {
mineCount = new ImageIcon[9];
for (int i = 0; i <= 8; i++) {
mineCount[i] = new ImageIcon("./image/" + i + ".gif");
}
timeCount = new ImageIcon[11];
for (int i = 0; i < 10; i++) {
timeCount[i] = new ImageIcon("./image/d" + i + ".gif");
}
timeCount[10] = new ImageIcon("./image/d10.gif");
}
// 笑脸表情标签图片
public static ImageIcon face0 = new ImageIcon("./image/face0.gif");
public static ImageIcon face1 = new ImageIcon("./image/face1.gif");
public static ImageIcon face2 = new ImageIcon("./image/face2.gif");
public static ImageIcon face3 = new ImageIcon("./image/face3.gif");
public static ImageIcon face4 = new ImageIcon("./image/face4.gif");
public static ImageIcon face5 = new ImageIcon("./image/face5.gif");
public static ImageIcon face6 = new ImageIcon("./image/face6.gif");
public static ImageIcon face7 = new ImageIcon("./image/face7.gif");
public static ImageIcon face8 = new ImageIcon("./image/face8.gif");
// 分别对应 mine雷标签图片
public static ImageIcon mine = new ImageIcon("./image/mine.gif");
public static ImageIcon mine0 = new ImageIcon("./image/mine0.gif");
public static ImageIcon mine1 = new ImageIcon("./image/mine1.gif");
//分别对应 ask问号标签图片
public static ImageIcon ask = new ImageIcon("./image/ask.gif");
public static ImageIcon ask1 = new ImageIcon("./image/ask1.gif");
public static ImageIcon iconTemp = new ImageIcon("./image/icon.gif");
public static Image icon = iconTemp.getImage();
public static ImageIcon blank = new ImageIcon("./image/blank.gif");
public static ImageIcon blood = new ImageIcon("./image/blood.gif");
public static ImageIcon error = new ImageIcon("./image/error.gif");
// 旗子标签图片
public static ImageIcon flag = new ImageIcon("./image/flag.gif");
// hole外挂标签图片
public static ImageIcon hole = new ImageIcon("./image/hole.gif");
}