首先说一下扫雷规则。

1.数字是几就表示此数字位置邻接的八个方向有几个地雷

2.鼠标右键单击一次标记此位置为地雷(插上一个小旗),再单击一次标记为?

3.鼠标左键单击某位置  

如果这个位置上的数字为1-8 即显示

如果为数字为0(即空白) 自动延伸八个方向直到遇见数字(1-8)为止

如果为地雷,游戏失败

4.当地图上的所有数字都点击完毕  游戏胜利

首先是MineClient类,初始化地雷,有刷新线程,画图等等

 

package com.xynu.mine;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;





import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JSeparator;

public class MineClient extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
//屏幕宽度
private int screenWidth;
//屏幕高度
private int screenHeight;
//图片宽度
private int imgWidth = 20;
//图片高度
private int imgHeight = 20;
//地图的行数
private int rowNum = 0;
//地图的列数
private int colNum = 0;
//地雷的总数
private int mineNum=99;
//计时器
private int timer=0;
//游戏时间
private int time=0;
//未扫雷的个数
private int restMine;
//不是雷的个数
private int notMine;
private MyPanel myPanel;
//当前游戏状态
private String gameState = "start";
//第一次点击
private boolean firstClick = true;
private JMenuBar menuBar;
private JMenu menu;
private JMenuItem lowLevel;
private JMenuItem midLevel;
private JMenuItem heightLevel;
private JMenuItem restart;
private Toolkit tk=Toolkit.getDefaultToolkit();
private Image icon=tk.getImage("Image/icon.jpg");
//地图集合
private ArrayList<Bomb> bombList = new ArrayList<Bomb>();


public MineClient(int screenWidth,int screenHeight,int mineNum) {
this.screenHeight=screenHeight;
this.screenWidth=screenWidth;
this.mineNum=mineNum;
//初始化菜单栏
initMenu();
setTitle("扫雷");
setIconImage(icon);
setSize(screenWidth , screenHeight);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
initList();
myPanel = new MyPanel();
myPanel.setBackground(Color.BLACK);
add(myPanel);
//鼠标事件
myPanel.addMouseListener(new MyMouseListener(this));
new updateThread().start();
}
/*
* 初始化菜单栏
*/
private void initMenu() {
menu=new JMenu("参数设置");
menuBar=new JMenuBar();
lowLevel=new JMenuItem("初级(10个雷)");
midLevel=new JMenuItem("中级(44个雷)");
heightLevel=new JMenuItem("高级(99个雷)");
restart=new JMenuItem("重新开始");
lowLevel.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
dispose();
new MineClient(225,305,10);
}
});
midLevel.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
dispose();
new MineClient(380,460,44);
}
});
heightLevel.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
dispose();
new MineClient(660,460,99);
}
});
restart.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
dispose();
new MineClient(screenWidth,screenHeight,mineNum);
}
});
menu.add(restart);
menu.add(new JSeparator());
menu.add(lowLevel);
menu.add(midLevel);
menu.add(heightLevel);
menuBar.add(menu);
setJMenuBar(menuBar);
}

public boolean isFirstClick() {
return firstClick;
}
public void setFirstClick(boolean firstClick) {
this.firstClick = firstClick;
}
public int getImgWidth() {
return imgWidth;
}

public void setImgWidth(int imgWidth) {
this.imgWidth = imgWidth;
}

public int getImgHeight() {
return imgHeight;
}

public void setImgHeight(int imgHeight) {
this.imgHeight = imgHeight;
}

public MyPanel getMyPanel() {
return myPanel;
}

public void setMyPanel(MyPanel myPanel) {
this.myPanel = myPanel;
}
public String getGameState() {
return gameState;
}

public void setGameState(String gameState) {
this.gameState = gameState;
}

public ArrayList<Bomb> getBombList() {
return bombList;
}

public int getRowNum() {
return rowNum;
}

public void setRowNum(int rowNum) {
this.rowNum = rowNum;
}

public int getColNum() {
return colNum;
}

public void setColNum(int colNum) {
this.colNum = colNum;
}

public int getMineNum() {
return mineNum;
}

//创建地图
private void initList() {
for (int i = imgWidth; i < this.getWidth() - 2 * imgWidth; i += imgWidth) {
for (int j = imgWidth; j < this.getHeight() - 6 * imgWidth; j += imgHeight) {
rowNum = rowNum > i / imgWidth ? rowNum : i / imgWidth;
colNum = colNum > j / imgWidth ? colNum : j / imgWidth;
Bomb bomb = new Bomb(i, j, 13, this);
bombList.add(bomb);
}
}
}

public static void main(String[] args) {
new MineClient(225,305,10);

}


//自定义panel
public class MyPanel extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;

public void paint(Graphics g) {
super.paintComponent(g);
restMine=mineNum;
notMine=0;
//画地雷 数字
for (Bomb bomb : bombList) {
bomb.draw(g);
if(bomb.getWhat()==11)
restMine--;
if(bomb.getWhat()>=0&&bomb.getWhat()<=8)
notMine++;
}
//游戏失败
if (gameState.equals("lose")) {
for (Bomb bomb : bombList) {
if (bomb.getHide() == 9) {
bomb.setWhat(bomb.getHide());
}
}
Font font = new Font("微软雅黑", Font.BOLD, 20);
g.setFont(font);
g.setColor(new Color(255, 0, 255));
g.drawString("GAME OVER!!", this.getWidth() / 2 - 80,
this.getHeight() / 2);
}
//画当前游戏进行时间 和未扫的地雷数目
drawTimeAndMineNum(g);

//取得游戏胜利
if(!gameState.equals("lose")&¬Mine+mineNum==colNum*rowNum)
{
gameState="win";
Toolkit tk=Toolkit.getDefaultToolkit();
Image img=tk.getImage("Image/win.jpg");
g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
Font font1 = new Font("华文行楷", Font.BOLD, 40);
g.setFont(font1);
g.setColor(new Color(248 ,29 ,56));
g.drawString("YOU WIN!!!", this.getWidth()/2-100, 30);
}
}

private void drawTimeAndMineNum(Graphics g) {
Font font = new Font("微软雅黑", Font.BOLD, 15);
g.setFont(font);
g.setColor(Color.orange);
g.drawString("已用时:"+time+" 秒", 0, this.getHeight()-20);
g.drawString("未扫雷:"+restMine+" 个", this.getWidth()-100, this.getHeight()-20);

}
}
//屏幕每隔100ms刷新一次
public class updateThread extends Thread {
public void run() {

while (true) {
repaint();
if(!firstClick){
timer+=100;
if(timer==1000){
timer=0;
time++;
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

然后是Bomb封装类。

 

解释两个变量。、

what表示当前地雷(不一定是地雷)所画的内容

hide表示当前地雷(不一定是地雷)真实的内容

解释两个方法

 

public Rectangle getRec() {
return new Rectangle(x, y, w, h);
}

返回当前地雷的矩形,具体作用我会在MyMouseListener类里面说

 

 

draw(Graphics g)

draw方法 主要实在panel里面画图

 

package com.xynu.mine;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;

public class Bomb {
private int x;
private int y;
private int what;
private int hide = 0;
private int w = 19;
private int h = 19;
private MineClient mc;
private Toolkit tk = Toolkit.getDefaultToolkit();
private Image bomb = tk.getImage("Image/bomb.jpg");
private Image bomb0 = tk.getImage("Image/bomb0.jpg");
private Image zeroBomb = tk.getImage("Image/0.jpg");
private Image oneBomb = tk.getImage("Image/1.jpg");
private Image twoBomb = tk.getImage("Image/2.jpg");
private Image threeBomb = tk.getImage("Image/3.jpg");
private Image fourBomb = tk.getImage("Image/4.jpg");
private Image fiveBomb = tk.getImage("Image/5.jpg");
private Image sixBomb = tk.getImage("Image/6.jpg");
private Image severnBomb = tk.getImage("Image/7.jpg");
private Image eightBomb = tk.getImage("Image/8.jpg");
private Image flag = tk.getImage("Image/flag.jpg");
private Image flag2 = tk.getImage("Image/flag2.jpg");
private Image bg = tk.getImage("Image/s.jpg");

public Bomb() {
super();
// TODO Auto-generated constructor stub
}

public Bomb(int x, int y, int what, MineClient mc) {
super();
this.x = x;
this.y = y;
this.what = what;
this.mc = mc;
}

public int getX() {
return x;
}

public void setX(int x) {
this.x = x;
}

public int getY() {
return y;
}

public void setY(int y) {
this.y = y;
}

public int getWhat() {
return what;
}

public void setWhat(int what) {
this.what = what;
}

public int getHide() {
return hide;
}

public void setHide(int hide) {
this.hide = hide;
}
//画地雷 数字
public void draw(Graphics g) {
switch (what) {
case 0:
g.drawImage(zeroBomb, x, y, w, h, mc);
break;
case 1:
g.drawImage(oneBomb, x, y, w, h, mc);
break;
case 2:
g.drawImage(twoBomb, x, y, w, h, mc);
break;
case 3:
g.drawImage(threeBomb, x, y, w, h, mc);
break;
case 4:
g.drawImage(fourBomb, x, y, w, h, mc);
break;
case 5:
g.drawImage(fiveBomb, x, y, w, h, mc);
break;
case 6:
g.drawImage(sixBomb, x, y, w, h, mc);
break;
case 7:
g.drawImage(severnBomb, x, y, w, h, mc);
break;
case 8:
g.drawImage(eightBomb, x, y, w, h, mc);
break;
case 9:
g.drawImage(bomb, x, y, w, h, mc);
break;
case 10:
g.drawImage(bomb0, x, y, w, h, mc);
break;
case 11:
g.drawImage(flag, x, y, w, h, mc);
break;
case 12:
g.drawImage(flag2, x, y, w, h, mc);
break;
case 13:
g.drawImage(bg, x, y, w, h, mc);
break;
}
}

public Rectangle getRec() {
return new Rectangle(x, y, w, h);
}
}

MyMouseListener类(自定义的鼠标事件)

 

最难的都在这里面了

1.开始玩游戏的时候要保证第一下点击的不是地雷

2.点击到数字0(空白)时自动延伸

解决:

在解决问题之前  我们要首先知道鼠标点击的是哪个地雷

 

<span style="white-space:pre">    </span>int x = e.getX();
int y = e.getY();
Rectangle rec = new Rectangle(x, y, 1, 1);
for (Bomb bomb : bombList) {
if(rec.intersects(bomb.getRec())){
//表示鼠标矩形和地雷矩形相交
}
}

解释一下,我们可以通过getx() ,gety()方法获得当前鼠标的坐标 然后把鼠标的宽和高认为1  new一个矩形对象

 

然后通过API提供的intersects方法判断两个矩形是否相交,也就是鼠标点击的地雷位置

1.为了保证第一次点击时点击不到地雷,我们在mousePressed(MouseEvent e)方法中初始化地图,把当前鼠标

点击的位置设置为地雷,当随机初始完地雷后再把当前位置恢复默认

2.这个应该是最难的了吧。当然 如果你学过算法中的搜索  那么久太简单了

DFS和BFS都行。从当前位置出发,向它的八个方向进行深搜  直到遇到数字结束当前递归

感觉这两个比较难  其它的有疑问可以留言  一起解决~~

package com.xynu.mine;

import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Random;

public class MyMouseListener extends MouseAdapter {
private MineClient mc;
private int colNum;
private int rowNum;
private boolean isFirstClick;
private ArrayList<Bomb> bombList = new ArrayList<Bomb>();
boolean[] vis ;
public MyMouseListener() {
super();
// TODO Auto-generated constructor stub
}

public MyMouseListener(MineClient mc) {
super();
this.mc = mc;
colNum = mc.getColNum();
rowNum = mc.getRowNum();
vis = new boolean[colNum * rowNum];
bombList = mc.getBombList();
this.isFirstClick=mc.isFirstClick();
}
/*
* 鼠标松下事件
* 如果松下的是鼠标左键 那么显示当前位置的地雷
* 如果松下的鼠标右键 那么标记当前位置
* @see java.awt.event.MouseAdapter#mouseReleased(java.awt.event.MouseEvent)
*/
public void mouseReleased(MouseEvent e) {
if (mc.getGameState().equals("lose")) {
return;
}
int x = e.getX();
int y = e.getY();
Rectangle rec = new Rectangle(x, y, 1, 1);
if (e.getButton() == MouseEvent.BUTTON1) {
for (Bomb bomb : bombList) {
if (rec.intersects(bomb.getRec())) {
if (bomb.getHide() == 9) {
mc.setGameState("lose");
} else {
if (bomb.getHide() == 0) {
increasePoint(bombList.indexOf(bomb));
}
bomb.setWhat(bomb.getHide());
}

}
}
}
if (e.getButton() == MouseEvent.BUTTON3) {
for (Bomb bomb : bombList) {
if (rec.intersects(bomb.getRec())) {
if(bomb.getWhat()!=bomb.getHide()){
if(bomb.getWhat()==13){
bomb.setWhat(11);
}
else if(bomb.getWhat()==11){
bomb.setWhat(12);
}
else if(bomb.getWhat()==12){
bomb.setWhat(13);
}
}
}
}
}

}

//自动扩大区域直到遇见数字
private void increasePoint(int index) {
if (vis[index])
return;
vis[index] = true;
boolean edgeU = false, edgeD = false;
if ((index + 1) % (colNum) != 0)
edgeU = true;
if (index % (colNum) != 0)
edgeD = true;
if (judgeLimit(index - 1) && edgeD) {
Bomb bomb = bombList.get(index - 1);
setVis(bomb, index - 1);
}

if (judgeLimit(index + 1) && edgeU) {
Bomb bomb = bombList.get(index + 1);
setVis(bomb, index + 1);
}

if (judgeLimit(index - colNum)) {
Bomb bomb = bombList.get(index - colNum);
setVis(bomb, index - colNum);
}

if (judgeLimit(index + colNum)) {
Bomb bomb = bombList.get(index + colNum);
setVis(bomb, index + colNum);
}

if (judgeLimit(index - colNum + 1) && edgeU) {
Bomb bomb = bombList.get(index - colNum + 1);
setVis(bomb, index - colNum + 1);
}

if (judgeLimit(index - colNum - 1) && edgeD) {
Bomb bomb = bombList.get(index - colNum - 1);
setVis(bomb, index - colNum - 1);
}

if (judgeLimit(index + colNum + 1) && edgeU) {
Bomb bomb = bombList.get(index + colNum + 1);
setVis(bomb, index + colNum + 1);
}

if (judgeLimit(index + colNum - 1) && edgeD) {
Bomb bomb = bombList.get(index + colNum - 1);
setVis(bomb, index + colNum - 1);
}

}
//判断边界
private boolean judgeLimit(int i) {
if (i >= 0 && i < bombList.size())
return true;
return false;
}
//显示某位置
public void setVis(Bomb bomb, int index) {
if (bomb.getWhat() == bomb.getHide() && bomb.getWhat() != 0)
return;
if (bomb.getHide() >= 0 && bomb.getHide() <= 8 && bomb.getHide() != 9) {
bomb.setWhat(bomb.getHide());
if (bomb.getWhat() == 0)
increasePoint(index);
} else {
increasePoint(index);
}
}
/*
* 按下鼠标左键的同时开始初始化地图
* @see java.awt.event.MouseAdapter#mousePressed(java.awt.event.MouseEvent)
*/
@Override
public void mousePressed(MouseEvent e) {
if (mc.getGameState().equals("lose")) {
return;
}
if (e.getButton() == MouseEvent.BUTTON1) {
if (isFirstClick) {
isFirstClick = false;
mc.setFirstClick(false);
initBomb(e);
checkBomb();
}
}
}

private void checkBomb() {

for (Bomb bomb : bombList) {
int x = bombList.indexOf(bomb);
//edgeU edgeD边界状态值
boolean edgeU = false, edgeD = false;
if ((x + 1) % (colNum) != 0)
edgeU = true;
if (x % (colNum) != 0)
edgeD = true;
if (bomb.getHide() != 9) {
if (judge(x - 1) && edgeD)
bomb.setHide(bomb.getHide() + 1);
if (judge(x + 1) && edgeU)
bomb.setHide(bomb.getHide() + 1);
if (judge(x - colNum))
bomb.setHide(bomb.getHide() + 1);
if (judge(x + colNum))
bomb.setHide(bomb.getHide() + 1);
if (judge(x - colNum + 1) && edgeU)
bomb.setHide(bomb.getHide() + 1);
if (judge(x - colNum - 1) && edgeD)
bomb.setHide(bomb.getHide() + 1);
if (judge(x + colNum + 1) && edgeU)
bomb.setHide(bomb.getHide() + 1);
if (judge(x + colNum - 1) && edgeD)
bomb.setHide(bomb.getHide() + 1);
}
}
}
//判断某位置是否是地雷
private boolean judge(int x) {
if (x >= 0 && x < bombList.size()) {
if (bombList.get(x).getHide() == 9)
return true;
}
return false;
}
/*
* 初始化地雷
*/
private void initBomb(MouseEvent e) {
int x = e.getX();
int y = e.getY();
Rectangle rec = new Rectangle(x, y, 1, 1);
Bomb bombTemp=new Bomb();
int what=0;
//为了避免第一下点击的不是地雷 首先让它设置为地雷,初始化地雷完成后 在恢复原样
for (Bomb bomb : bombList) {
if(rec.intersects(bomb.getRec())){
what=bomb.getHide();
bombTemp=bomb;
bomb.setHide(9);
break;
}
}
//使用随机数 初始化地图
Random r = new Random();
for (int i = 0; i < mc.getMineNum(); i++) {
while (true) {
int index = r.nextInt(bombList.size());
if (bombList.get(index).getHide() != 9) {
bombList.get(index).setHide(9);
break;
}
}
}
bombTemp.setHide(what);
}
}

还是自己的扫雷玩着有意思  哈哈

 

如果有问题  可以留言哦~一起解决

扫雷(java版)_ico

扫雷(java版)_扫雷java版_02

所有代码+图片