1.java扫雷设计

1.项目介绍

这是一个简单的自主开发的扫雷游戏,可以实现基本的游戏功能,比如正常游戏、重开、选择难度、计时。

2.前期调查

我主要是向复刻经典windows小游戏扫雷,前期调查也就是按照经典游戏

可以看到,界面大体是这样的

3.项目功能框架图

4.主要功能流程图

5.UML图

MainFrame类

开始游戏和重开游戏。

游戏菜单栏

InfoView类

显示游戏进行过程中的信息,比如得分和时间。

StaticTools类

存放一些全局变量,比如加载图片,游戏的行款列宽等

CreateMine类

用于随机生成地雷

MyTimer类

计时工具

MyMouseListener类

鼠标监听器,用于监听鼠标的点击并完成一系列活动

MineButton类

地雷以按钮的形式存放,这个类存放了每个地雷的属性、get和set方法。

UML类图

6.运行截图

失败

成功

高级难度

7.关键模块

(1)首先创建MineButtons[][]对象,将每个格子的初始化。

public class MineButton extends JButton {
private boolean mineTag; //有雷
private boolean expendTag; //被占了
private boolean flagTag; //插旗
private int rowx; //x坐标
private int coly; //y坐标
private int counAround; //周围的地雷数
private int clickRightCount=0;//点击右键次数
public MineButton(int x, int y) {
this.rowx = x;
this.coly = y;

}

(2)创建CreateMine类的对象,并调用其构造方法,生成地雷并随机分布。

if(mineButtons[x][y].isMineTag()false&&mineButtons[x][y].isExpendTag()false){
mineButtons[x][y].setMineTag(true); //埋下地雷
mineButtons[x][y].setCounAround(9); //一个位置周围最多8个地雷,周围地雷数设为9,表示这个位置就是地雷
count++; //只有设置地雷成功count才会添加成功,避免了重复设置地雷
mineButtons[x][y].setIcon(StaticTools.hole);
}

for (int i = 0; i < mineButtons.length; i++) {
for (int j = 0; j < mineButtons[i].length; j++) {
if (mineButtons[i][j].isMineTag() == false) {
int count = 0;
//计算每个格子周围的雷数
for (int x = Math.max(0, i - 1); x <= Math.min(StaticTools.allrow - 1, i + 1); x++) {
for (int y = Math.max(0, j - 1); y <= Math.min(StaticTools.allcol - 1, j + 1); y++) {
if (mineButtons[x][y].isMineTag() == true) {
count++;
}
}
}
mineButtons[i][j].setCounAround(count);
}

(3)选择格子进行点击,专门定义了MyMouseListener类,实现MouseListener的接口,并覆盖相关的方法。

右键点击一个区域插旗,点击两次取消插旗
if (e.getModifiersEx() == InputEvent.BUTTON3_DOWN_MASK
&& !mineButton.isExpendTag() && StaticTools.isStart) {
//右键点击一个没有旗子的区域
if (mineButton.getClickRightCount() == 0) {
mineButton.setFlagTag(true);
mineButton.setIcon(StaticTools.flag);
StaticTools.bombCount--; //剩余雷数-1
mineButton.setClickRightCount(1);
if (mineButton.isMineTag()) {
//System.out.println("猜对了");
StaticTools.rightCount++;
}
mainFrame.getInfoView().setScoreJl(StaticTools.bombCount);
isWin();
点击一个空白区域,如果没有地雷,则显示周围地雷数,如果点中地雷,则游戏结束
if (e.getModifiersEx() == InputEvent.BUTTON1_DOWN_MASK
&& !mineButton.isFlagTag() && StaticTools.isStart) {
//左键点击一个没有旗子的区域
if (!mineButton.isExpendTag() && !mineButton.isMineTag()) {
//如果这个地方没有被点
expand(x, y);
System.out.println("从expand回来了");
}
if (e.getModifiersEx() == InputEvent.BUTTON1_DOWN_MASK
&& mineButton.isMineTag() && StaticTools.isStart) {
//踩到雷了
bombAction(mineButton.getRowx(), mineButton.getColy());
mainFrame.getInfoView().startBut.setIcon(StaticTools.lossIcon);
mainFrame.getInfoView().getTimer().stop();
System.out.println("踩到雷了");
}

(4)expand的递归实现标记安全区

一般的扫雷游戏,点击一个格子,可能会将一部分安全区标记,为了实现这一功能,我写了一个expand方法,递归这个方法,可以将安全区标出。
点击一个格子,如果这个格子周围是没有地雷的,则会遍历周围8个格子,并递归调用expand方法。以此来标记安全区。
if (mineButtons[x][y].isExpendTag() == false && mineButtons[x][y].isFlagTag() == false) {
System.out.println("2");
if (count == 0) {
System.out.println("3");
mineButtons[x][y].setIcon(StaticTools.num[count]);
mineButtons[x][y].setExpendTag(true);
for (int i = Math.max(0, x - 1); i <= Math.min(mineButtons.length - 1, x + 1); i++) {
for (int j = Math.max(0, y - 1); j <= Math.min(mineButtons[x].length - 1, y + 1); j++) {
System.out.println("4");
expand(i, j);
}
}

8.项目总结

本次课设,我没有组队,而是采用单人开发的模式,单人开发在代码整合部分是比较简单的,因为各个模块都是自己写的,都符合自己的编程习惯。但是因为只有一个人开发,功能相对不全,界面也不够美观。因为时间关系,在系统中没有接入数据库,也就没有实现旁行榜的功能。
这次课设没有接入数据库,也没有实现排名的功能,比较遗憾,但是开发扫雷游戏我感觉很有趣,玩了这么多年扫雷,终于算是理解了扫雷里面的原理,后续我会完善我的游戏,加入排名等功能,并接入数据库。