游戏需要的图片放置在末尾需要的拿,游戏共分为三个关卡,困难普通简单三类。该游戏代码我分成了好七个类。游戏需要的图片我放到了末尾处。

游戏截图如下:

游戏分为三个关卡

这个是简单关卡

 

这个是普通关卡的

这个是困难关卡的也就是最难的

 

踩到雷后就直接输了,左上角的是地雷的数量.右上角是计时函数,中间的是开始按钮失败后点击即可复原关卡继续闯关。

测试类代码如下,该类主要用于运行与调用其它类。
package com.sxt; import javax.swing.*; import java.awt.*; import
java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class
GameWin extends JFrame { int wigth = 2 * GameUtil.OFFSET + GameUtil.MAP_W *
GameUtil.SQUARE_LENGTH; int height = 4 * GameUtil.OFFSET + GameUtil.MAP_H *
GameUtil.SQUARE_LENGTH; Image offScreenImage = null; MapBottom mapBottom = new
MapBottom(); MapTop mapTop = new MapTop(); GameSelect gameSelect = new
GameSelect(); //是否开始,f未开始,t开始 boolean begin=false; void launch(){
GameUtil.START_TIME=System.currentTimeMillis(); this.setVisible(true);
if(GameUtil.state==3){ this.setSize(500,500); }else {
this.setSize(wigth,height); } this.setLocationRelativeTo(null);
this.setTitle("花~盗的扫雷游戏"); this.setDefaultCloseOperation(EXIT_ON_CLOSE); //鼠标事件
this.addMouseListener(new MouseAdapter() { @Override public void
mouseClicked(MouseEvent e) { super.mouseClicked(e); switch (GameUtil.state){
case 0 : if(e.getButton()==1){ GameUtil.MOUSE_X = e.getX(); GameUtil.MOUSE_Y =
e.getY(); GameUtil.LEFT = true; } if(e.getButton()==3) { GameUtil.MOUSE_X =
e.getX(); GameUtil.MOUSE_Y = e.getY(); GameUtil.RIGHT = true; } case 1 : case 2
: if(e.getButton()==1){ if(e.getX()>GameUtil.OFFSET +
GameUtil.SQUARE_LENGTH*(GameUtil.MAP_W/2) && e.getX()<GameUtil.OFFSET +
GameUtil.SQUARE_LENGTH*(GameUtil.MAP_W/2) + GameUtil.SQUARE_LENGTH &&
e.getY()>GameUtil.OFFSET && e.getY()<GameUtil.OFFSET+GameUtil.SQUARE_LENGTH){
mapBottom.reGame(); mapTop.reGame(); GameUtil.FLAG_NUM=0;
GameUtil.START_TIME=System.currentTimeMillis(); GameUtil.state=0; } }
if(e.getButton()==2){ GameUtil.state=3; begin=true; } break; case 3:
if(e.getButton()==1){ GameUtil.MOUSE_X = e.getX(); GameUtil.MOUSE_Y = e.getY();
begin = gameSelect.hard(); } break; default: } } }); while (true){ repaint();
begin(); try { Thread.sleep(40); } catch (InterruptedException e) {
e.printStackTrace(); } } } void begin(){ if(begin){ begin=false;
gameSelect.hard(GameUtil.level); dispose(); GameWin gameWin = new GameWin();
GameUtil.START_TIME = System.currentTimeMillis(); GameUtil.FLAG_NUM=0;
mapBottom.reGame(); mapTop.reGame(); gameWin.launch(); } } @Override public
void paint(Graphics g) { if(GameUtil.state==3){ g.setColor(Color.white);
g.fillRect(0,0,500,500); gameSelect.paintSelf(g); }else { offScreenImage =
this.createImage(wigth, height); Graphics gImage =
offScreenImage.getGraphics(); //设置背景颜色 gImage.setColor(Color.orange);
gImage.fillRect(0, 0, wigth, height); mapBottom.paintSelf(gImage);
mapTop.paintSelf(gImage); g.drawImage(offScreenImage, 0, 0, null); } } public
static void main(String[] args) { GameWin gameWin = new GameWin();
gameWin.launch(); } }
游戏地图类
package com.sxt; import java.awt.*; /** * 底层地图 * 绘制游戏相关组件 */ public class
MapBottom { BottomRay bottomRay = new BottomRay(); BottomNum bottomNum = new
BottomNum(); { bottomRay.newRay(); bottomNum.newNum(); } //重置游戏 void reGame(){
for (int i = 1; i <=GameUtil.MAP_W ; i++) { for (int j = 1; j <=GameUtil.MAP_H
; j++) { GameUtil.DATA_BOTTOM[i][j]=0; } } bottomRay.newRay();
bottomNum.newNum(); } //绘制方法 void paintSelf(Graphics g){ g.setColor(Color.red);
//画竖线 for (int i = 0; i <= GameUtil.MAP_W; i++) { g.drawLine(GameUtil.OFFSET +
i * GameUtil.SQUARE_LENGTH, 3*GameUtil.OFFSET,
GameUtil.OFFSET+i*GameUtil.SQUARE_LENGTH,
3*GameUtil.OFFSET+GameUtil.MAP_H*GameUtil.SQUARE_LENGTH); } //画横线 for (int i =
0; i <=GameUtil.MAP_H; i++){ g.drawLine(GameUtil.OFFSET,
3*GameUtil.OFFSET+i*GameUtil.SQUARE_LENGTH,
GameUtil.OFFSET+GameUtil.MAP_W*GameUtil.SQUARE_LENGTH,
3*GameUtil.OFFSET+i*GameUtil.SQUARE_LENGTH); } for (int i = 1; i <=
GameUtil.MAP_W ; i++) { for (int j = 1; j <= GameUtil.MAP_H; j++) { //雷 if
(GameUtil.DATA_BOTTOM[i][j] == -1) { g.drawImage(GameUtil.lei, GameUtil.OFFSET
+ (i - 1) * GameUtil.SQUARE_LENGTH + 1, GameUtil.OFFSET * 3 + (j - 1) *
GameUtil.SQUARE_LENGTH + 1, GameUtil.SQUARE_LENGTH - 2, GameUtil.SQUARE_LENGTH
- 2, null); } //数字 if (GameUtil.DATA_BOTTOM[i][j] >=0) {
g.drawImage(GameUtil.images[GameUtil.DATA_BOTTOM[i][j]], GameUtil.OFFSET + (i -
1) * GameUtil.SQUARE_LENGTH + 15, GameUtil.OFFSET * 3 + (j - 1) *
GameUtil.SQUARE_LENGTH + 5, null); } } } //绘制数字 剩余雷数,倒计时
GameUtil.drawWord(g,""+(GameUtil.RAY_MAX-GameUtil.FLAG_NUM), GameUtil.OFFSET,
2*GameUtil.OFFSET,30,Color.red);
GameUtil.drawWord(g,""+(GameUtil.END_TIME-GameUtil.START_TIME)/1000,
GameUtil.OFFSET + GameUtil.SQUARE_LENGTH*(GameUtil.MAP_W-1),
2*GameUtil.OFFSET,30,Color.red); switch (GameUtil.state){ case 0:
GameUtil.END_TIME=System.currentTimeMillis(); g.drawImage(GameUtil.face,
GameUtil.OFFSET + GameUtil.SQUARE_LENGTH * (GameUtil.MAP_W/2), GameUtil.OFFSET,
null); break; case 1: g.drawImage(GameUtil.win, GameUtil.OFFSET +
GameUtil.SQUARE_LENGTH * (GameUtil.MAP_W/2), GameUtil.OFFSET, null); break;
case 2: g.drawImage(GameUtil.over, GameUtil.OFFSET + GameUtil.SQUARE_LENGTH *
(GameUtil.MAP_W/2), GameUtil.OFFSET, null); break; default: } } }
底层数据类
package com.sxt; /** * 底层数字类 */ public class BottomNum { void newNum() { for
(int i = 1; i <=GameUtil.MAP_W ; i++) { for (int j = 1; j <=GameUtil.MAP_H ;
j++) { if(GameUtil.DATA_BOTTOM[i][j]==-1){ for (int k = i-1; k <=i+1 ; k++) {
for (int l = j-1; l <=j+1 ; l++) { if(GameUtil.DATA_BOTTOM[k][l]>=0){
GameUtil.DATA_BOTTOM[k][l]++; } } } } } } } }
工具类如下:
package com.sxt; import java.awt.*; /** * 工具类 * 存放静态参数 * 工具方法 */ public class
GameUtil { //地雷个数 static int RAY_MAX = 100; //地图的宽 static int MAP_W = 36;
//地图的高 static int MAP_H = 17; //雷区偏移量 static int OFFSET = 45; //格子边长 static int
SQUARE_LENGTH = 50; //插旗数量 static int FLAG_NUM = 0; //鼠标相关 //坐标 static int
MOUSE_X; static int MOUSE_Y; //状态 static boolean LEFT = false; static boolean
RIGHT = false; //游戏状态 0 表示游戏中 1 胜利 2 失败 3 难度选择 static int state = 3; //游戏难度
static int level; //倒计时 static long START_TIME; static long END_TIME; //底层元素 -1
雷 0 空 1-8 表示对应数字 static int[][] DATA_BOTTOM = new int[MAP_W+2][MAP_H+2]; //顶层元素
-1 无覆盖 0 覆盖 1 插旗 2 差错旗 static int[][] DATA_TOP = new int[MAP_W+2][MAP_H+2];
//载入图片 static Image lei = Toolkit.getDefaultToolkit().getImage("imgs/lei.png");
static Image top = Toolkit.getDefaultToolkit().getImage("imgs/top.gif"); static
Image flag = Toolkit.getDefaultToolkit().getImage("imgs/flag.gif"); static
Image noflag = Toolkit.getDefaultToolkit().getImage("imgs/noflag.png"); static
Image face = Toolkit.getDefaultToolkit().getImage("imgs/face.png"); static
Image over = Toolkit.getDefaultToolkit().getImage("imgs/over.png"); static
Image win = Toolkit.getDefaultToolkit().getImage("imgs/win.png"); static
Image[] images = new Image[9]; static { for (int i = 1; i <=8 ; i++) {
images[i] = Toolkit.getDefaultToolkit().getImage("imgs/num/"+i+".png"); } }
static void drawWord(Graphics g,String str,int x,int y,int size,Color color){
g.setColor(color); g.setFont(new Font("仿宋",Font.BOLD,size));
g.drawString(str,x,y); } }
难度选择类
package com.sxt; import java.awt.*; /** * 难度选择类 */ public class GameSelect {
//判断是否点击到难度 boolean hard(){ if(GameUtil.MOUSE_X>100&&GameUtil.MOUSE_X<400){
if(GameUtil.MOUSE_Y>50&&GameUtil.MOUSE_Y<150){ GameUtil.level=1;
GameUtil.state=0; return true; }
if(GameUtil.MOUSE_Y>200&&GameUtil.MOUSE_Y<300){ GameUtil.level=2;
GameUtil.state=0; return true; }
if(GameUtil.MOUSE_Y>350&&GameUtil.MOUSE_Y<450){ GameUtil.level=3;
GameUtil.state=0; return true; } } return false; } void paintSelf(Graphics g){
g.setColor(Color.black); g.drawRect(100,50,300,100);
GameUtil.drawWord(g,"简单",220,100,30,Color.black); g.drawRect(100,200,300,100);
GameUtil.drawWord(g,"普通",220,250,30,Color.black); g.drawRect(100,350,300,100);
GameUtil.drawWord(g,"困难",220,400,30,Color.black); } void hard(int level){
switch (level){ case 1: GameUtil.RAY_MAX = 10; GameUtil.MAP_W = 9;
GameUtil.MAP_H = 9; break; case 2: GameUtil.RAY_MAX = 40; GameUtil.MAP_W = 16;
GameUtil.MAP_H = 16; break; case 3: GameUtil.RAY_MAX = 99; GameUtil.MAP_W = 30;
GameUtil.MAP_H = 16; break; default: } } }
顶层地图类:
package com.sxt; import java.awt.*; /** * 顶层地图类 * 绘制顶层组件 * 判断逻辑 */ public
class MapTop { //格子位置 int temp_x; int temp_y; //重置游戏 void reGame(){ for (int i
= 1; i <=GameUtil.MAP_W ; i++) { for (int j = 1; j <=GameUtil.MAP_H ; j++) {
GameUtil.DATA_TOP[i][j]=0; } } } //判断逻辑 void logic(){ temp_x=0; temp_y=0;
if(GameUtil.MOUSE_X>GameUtil.OFFSET && GameUtil.MOUSE_Y>3*GameUtil.OFFSET){
temp_x = (GameUtil.MOUSE_X - GameUtil.OFFSET)/GameUtil.SQUARE_LENGTH+1; temp_y
= (GameUtil.MOUSE_Y - GameUtil.OFFSET * 3)/GameUtil.SQUARE_LENGTH+1; }
if(temp_x>=1 && temp_x<=GameUtil.MAP_W && temp_y>=1 && temp_y<=GameUtil.MAP_H){
if(GameUtil.LEFT){ //覆盖,则翻开 if(GameUtil.DATA_TOP[temp_x][temp_y]==0){
GameUtil.DATA_TOP[temp_x][temp_y]=-1; } spaceOpen(temp_x,temp_y);
GameUtil.LEFT=false; } if(GameUtil.RIGHT){ //覆盖则插旗
if(GameUtil.DATA_TOP[temp_x][temp_y]==0){ GameUtil.DATA_TOP[temp_x][temp_y]=1;
GameUtil.FLAG_NUM++; } //插旗则取消 else if(GameUtil.DATA_TOP[temp_x][temp_y]==1){
GameUtil.DATA_TOP[temp_x][temp_y]=0; GameUtil.FLAG_NUM--; } else
if(GameUtil.DATA_TOP[temp_x][temp_y]==-1){ numOpen(temp_x,temp_y); }
GameUtil.RIGHT=false; } } boom(); victory(); } //数字翻开 void numOpen(int x,int
y){ //记录旗数 int count=0; if(GameUtil.DATA_BOTTOM[x][y]>0){ for (int i = x-1; i
<=x+1 ; i++) { for (int j = y-1; j <=y+1 ; j++) {
if(GameUtil.DATA_TOP[i][j]==1){ count++; } } }
if(count==GameUtil.DATA_BOTTOM[x][y]){ for (int i = x-1; i <=x+1 ; i++) { for
(int j = y-1; j <=y+1 ; j++) { if(GameUtil.DATA_TOP[i][j]!=1){
GameUtil.DATA_TOP[i][j]=-1; } //必须在雷区当中
if(i>=1&&j>=1&&i<=GameUtil.MAP_W&&j<=GameUtil.MAP_H){ spaceOpen(i,j); } } } } }
} //失败判定 t 表示失败 f 未失败 boolean boom(){ if(GameUtil.FLAG_NUM==GameUtil.RAY_MAX){
for (int i = 1; i <=GameUtil.MAP_W ; i++) { for (int j = 1; j <=GameUtil.MAP_H
; j++) { if(GameUtil.DATA_TOP[i][j]==0){ GameUtil.DATA_TOP[i][j]=-1; } } } }
for (int i = 1; i <=GameUtil.MAP_W ; i++) { for (int j = 1; j <=GameUtil.MAP_H
; j++) { if(GameUtil.DATA_BOTTOM[i][j]==-1&&GameUtil.DATA_TOP[i][j]==-1){
GameUtil.state = 2; seeBoom(); return true; } } } return false; } //失败显示 void
seeBoom(){ for (int i = 1; i <=GameUtil.MAP_W ; i++) { for (int j = 1; j
<=GameUtil.MAP_H ; j++) { //底层是雷,顶层不是旗,显示
if(GameUtil.DATA_BOTTOM[i][j]==-1&&GameUtil.DATA_TOP[i][j]!=1){
GameUtil.DATA_TOP[i][j]=-1; } //底层不是雷,顶层是旗,显示差错旗
if(GameUtil.DATA_BOTTOM[i][j]!=-1&&GameUtil.DATA_TOP[i][j]==1){
GameUtil.DATA_TOP[i][j]=2; } } } } //胜利判断 t 表示胜利 f 未胜利 boolean victory(){
//统计未打开格子数 int count=0; for (int i = 1; i <=GameUtil.MAP_W ; i++) { for (int j
= 1; j <=GameUtil.MAP_H ; j++) { if(GameUtil.DATA_TOP[i][j]!=-1){ count++; } }
} if(count==GameUtil.RAY_MAX){ GameUtil.state=1; for (int i = 1; i
<=GameUtil.MAP_W ; i++) { for (int j = 1; j <=GameUtil.MAP_H ; j++) { //未翻开,变成旗
if(GameUtil.DATA_TOP[i][j]==0){ GameUtil.DATA_TOP[i][j]=1; } } } return true; }
return false; } //打开空格 void spaceOpen(int x,int y){
if(GameUtil.DATA_BOTTOM[x][y]==0){ for (int i = x-1; i <=x+1 ; i++) { for (int
j = y-1; j <=y+1 ; j++) { //覆盖,才递归 if(GameUtil.DATA_TOP[i][j]!=-1){
if(GameUtil.DATA_TOP[i][j]==1){GameUtil.FLAG_NUM--;}
GameUtil.DATA_TOP[i][j]=-1; //必须在雷区当中
if(i>=1&&j>=1&&i<=GameUtil.MAP_W&&j<=GameUtil.MAP_H){ spaceOpen(i,j); } } } } }
} //绘制方法 void paintSelf(Graphics g){ logic(); for (int i = 1; i <=
GameUtil.MAP_W ; i++) { for (int j = 1; j <= GameUtil.MAP_H; j++) { //覆盖 if
(GameUtil.DATA_TOP[i][j] == 0) { g.drawImage(GameUtil.top, GameUtil.OFFSET + (i
- 1) * GameUtil.SQUARE_LENGTH + 1, GameUtil.OFFSET * 3 + (j - 1) *
GameUtil.SQUARE_LENGTH + 1, GameUtil.SQUARE_LENGTH - 2, GameUtil.SQUARE_LENGTH
- 2, null); } //插旗 if (GameUtil.DATA_TOP[i][j] == 1) {
g.drawImage(GameUtil.flag, GameUtil.OFFSET + (i - 1) * GameUtil.SQUARE_LENGTH +
1, GameUtil.OFFSET * 3 + (j - 1) * GameUtil.SQUARE_LENGTH + 1,
GameUtil.SQUARE_LENGTH - 2, GameUtil.SQUARE_LENGTH - 2, null); } //差错旗 if
(GameUtil.DATA_TOP[i][j] == 2) { g.drawImage(GameUtil.noflag, GameUtil.OFFSET +
(i - 1) * GameUtil.SQUARE_LENGTH + 1, GameUtil.OFFSET * 3 + (j - 1) *
GameUtil.SQUARE_LENGTH + 1, GameUtil.SQUARE_LENGTH - 2, GameUtil.SQUARE_LENGTH
- 2, null); } } } } }
初始化地雷类
package com.sxt; /** * 初始化地雷 */ public class BottomRay { //存放坐标 static int[]
rays = new int[GameUtil.RAY_MAX*2]; //地雷坐标 int x,y; //是否放置 T 表示可以放置 F 不可放置
boolean isPlace = true; //生成雷 void newRay() { for (int i = 0; i <
GameUtil.RAY_MAX*2 ; i=i+2) { x= (int) (Math.random()*GameUtil.MAP_W +1);//1-12
y= (int) (Math.random()*GameUtil.MAP_H +1);//1-12 //判断坐标是否存在 for (int j = 0; j
< i ; j=j+2) { if(x==rays[j] && y==rays[j+1]){ i=i-2; isPlace = false; break; }
} //将坐标放入数组 if(isPlace){ rays[i]=x; rays[i+1]=y; } isPlace = true; } for (int i
= 0; i < GameUtil.RAY_MAX*2; i=i+2) {
GameUtil.DATA_BOTTOM[rays[i]][rays[i+1]]=-1; } } }
道具图片如下:

 

  

 

 

 

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信