猿学-扫雷java版
首先说一下扫雷规则。
1.数字是几就表示此数字位置邻接的八个方向有几个地雷
2.鼠标右键单击一次标记此位置为地雷(插上一个小旗),再单击一次标记为?
3.鼠标左键单击某位置
如果这个位置上的数字为1-8 即显示
如果为数字为0(即空白) 自动延伸八个方向直到遇见数字(1-8)为止
如果为地雷,游戏失败
4.当地图上的所有数字都点击完毕 游戏胜利
首先是MineClient类,初始化地雷,有刷新线程,画图等等
packagecom.xynu.mine;
importjava.awt.Color;
importjava.awt.Font;
importjava.awt.Graphics;
importjava.awt.Image;
importjava.awt.Toolkit;
importjava.awt.event.ActionEvent;
importjava.awt.event.ActionListener;
importjava.util.ArrayList;
importjavax.swing.JFrame;
importjavax.swing.JMenu;
importjavax.swing.JMenuBar;
importjavax.swing.JMenuItem;
importjavax.swing.JPanel;
importjavax.swing.JSeparator;
publicclassMineClient extendsJFrame {
/**
*
*/
privatestaticfinallongserialVersionUID = 1L;
//屏幕宽度
privateintscreenWidth;
//屏幕高度
privateintscreenHeight;
//图片宽度
privateintimgWidth = 20;
//图片高度
privateintimgHeight = 20;
//地图的行数
privateintrowNum = 0;
//地图的列数
privateintcolNum = 0;
//地雷的总数
privateintmineNum=99;
//计时器
privateinttimer=0;
//游戏时间
privateinttime=0;
//未扫雷的个数
privateintrestMine;
//不是雷的个数
privateintnotMine;
privateMyPanel myPanel;
//当前游戏状态
privateString gameState = "start";
//第一次点击
privatebooleanfirstClick = true;
privateJMenuBar menuBar;
privateJMenu menu;
privateJMenuItem lowLevel;
privateJMenuItem midLevel;
privateJMenuItem heightLevel;
privateJMenuItem restart;
privateToolkit tk=Toolkit.getDefaultToolkit();
privateImage icon=tk.getImage("Image/icon.jpg");
//地图集合
privateArrayList bombList = newArrayList();
publicMineClient(intscreenWidth,intscreenHeight,intmineNum) {
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 = newMyPanel();
myPanel.setBackground(Color.BLACK);
add(myPanel);
//鼠标事件
myPanel.addMouseListener(newMyMouseListener(this));
newupdateThread().start();
}
/*
* 初始化菜单栏
*/
privatevoidinitMenu() {
menu=newJMenu("参数设置");
menuBar=newJMenuBar();
lowLevel=newJMenuItem("初级(10个雷)");
midLevel=newJMenuItem("中级(44个雷)");
heightLevel=newJMenuItem("高级(99个雷)");
restart=newJMenuItem("重新开始");
lowLevel.addActionListener(newActionListener() {
publicvoidactionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
dispose();
newMineClient(225,305,10);
}
});
midLevel.addActionListener(newActionListener() {
publicvoidactionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
dispose();
newMineClient(380,460,44);
}
});
heightLevel.addActionListener(newActionListener() {
publicvoidactionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
dispose();
newMineClient(660,460,99);
}
});
restart.addActionListener(newActionListener() {
publicvoidactionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
dispose();
newMineClient(screenWidth,screenHeight,mineNum);
}
});
menu.add(restart);
menu.add(newJSeparator());
menu.add(lowLevel);
menu.add(midLevel);
menu.add(heightLevel);
menuBar.add(menu);
setJMenuBar(menuBar);
}
publicbooleanisFirstClick() {
returnfirstClick;
}
publicvoidsetFirstClick(booleanfirstClick) {
this.firstClick = firstClick;
}
publicintgetImgWidth() {
returnimgWidth;
}
publicvoidsetImgWidth(intimgWidth) {
this.imgWidth = imgWidth;
}
publicintgetImgHeight() {
returnimgHeight;
}
publicvoidsetImgHeight(intimgHeight) {
this.imgHeight = imgHeight;
}
publicMyPanel getMyPanel() {
returnmyPanel;
}
publicvoidsetMyPanel(MyPanel myPanel) {
this.myPanel = myPanel;
}
publicString getGameState() {
returngameState;
}
publicvoidsetGameState(String gameState) {
this.gameState = gameState;
}
publicArrayList getBombList() {
returnbombList;
}
publicintgetRowNum() {
returnrowNum;
}
publicvoidsetRowNum(introwNum) {
this.rowNum = rowNum;
}
publicintgetColNum() {
returncolNum;
}
publicvoidsetColNum(intcolNum) {
this.colNum = colNum;
}
publicintgetMineNum() {
returnmineNum;
}
//创建地图
privatevoidinitList() {
for(inti = imgWidth; i < this.getWidth() - 2* imgWidth; i += imgWidth) {
for(intj = imgWidth; j < this.getHeight() - 6* imgWidth; j += imgHeight) {
rowNum = rowNum > i / imgWidth ? rowNum : i / imgWidth;
colNum = colNum > j / imgWidth ? colNum : j / imgWidth;
Bomb bomb = newBomb(i, j, 13, this);
bombList.add(bomb);
}
}
}
publicstaticvoidmain(String[] args) {
newMineClient(225,305,10);
}
//自定义panel
publicclassMyPanel extendsJPanel {
/**
*
*/
privatestaticfinallongserialVersionUID = 1L;
publicvoidpaint(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 = newFont("微软雅黑", Font.BOLD, 20);
g.setFont(font);
g.setColor(newColor(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 = newFont("华文行楷", Font.BOLD, 40);
g.setFont(font1);
g.setColor(newColor(248,29,56));
g.drawString("YOU WIN!!!", this.getWidth()/2-100, 30);
}
}
privatevoiddrawTimeAndMineNum(Graphics g) {
Font font = newFont("微软雅黑", 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刷新一次
publicclassupdateThread extendsThread {
publicvoidrun() {
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表示当前地雷(不一定是地雷)真实的内容
解释两个方法
1
2
3
publicRectangle getRec() {
returnnewRectangle(x, y, w, h);
}
返回当前地雷的矩形,具体作用我会在MyMouseListener类里面说
1draw(Graphics g)
draw方法 主要实在panel里面画图
packagecom.xynu.mine;
importjava.awt.Graphics;
importjava.awt.Image;
importjava.awt.Rectangle;
importjava.awt.Toolkit;
publicclassBomb {
privateintx;
privateinty;
privateintwhat;
privateinthide = 0;
privateintw = 19;
privateinth = 19;
privateMineClient mc;
privateToolkit tk = Toolkit.getDefaultToolkit();
privateImage bomb = tk.getImage("Image/bomb.jpg");
privateImage bomb0 = tk.getImage("Image/bomb0.jpg");
privateImage zeroBomb = tk.getImage("Image/0.jpg");
privateImage oneBomb = tk.getImage("Image/1.jpg");
privateImage twoBomb = tk.getImage("Image/2.jpg");
privateImage threeBomb = tk.getImage("Image/3.jpg");
privateImage fourBomb = tk.getImage("Image/4.jpg");
privateImage fiveBomb = tk.getImage("Image/5.jpg");
privateImage sixBomb = tk.getImage("Image/6.jpg");
privateImage severnBomb = tk.getImage("Image/7.jpg");
privateImage eightBomb = tk.getImage("Image/8.jpg");
privateImage flag = tk.getImage("Image/flag.jpg");
privateImage flag2 = tk.getImage("Image/flag2.jpg");
privateImage bg = tk.getImage("Image/s.jpg");
publicBomb() {
super();
// TODO Auto-generated constructor stub
}
publicBomb(intx, inty, intwhat, MineClient mc) {
super();
this.x = x;
this.y = y;
this.what = what;
this.mc = mc;
}
publicintgetX() {
returnx;
}
publicvoidsetX(intx) {
this.x = x;
}
publicintgetY() {
returny;
}
publicvoidsetY(inty) {
this.y = y;
}
publicintgetWhat() {
returnwhat;
}
publicvoidsetWhat(intwhat) {
this.what = what;
}
publicintgetHide() {
returnhide;
}
publicvoidsetHide(inthide) {
this.hide = hide;
}
//画地雷 数字
publicvoiddraw(Graphics g) {
switch(what) {
case0:
g.drawImage(zeroBomb, x, y, w, h, mc);
break;
case1:
g.drawImage(oneBomb, x, y, w, h, mc);
break;
case2:
g.drawImage(twoBomb, x, y, w, h, mc);
break;
case3:
g.drawImage(threeBomb, x, y, w, h, mc);
break;
case4:
g.drawImage(fourBomb, x, y, w, h, mc);
break;
case5:
g.drawImage(fiveBomb, x, y, w, h, mc);
break;
case6:
g.drawImage(sixBomb, x, y, w, h, mc);
break;
case7:
g.drawImage(severnBomb, x, y, w, h, mc);
break;
case8:
g.drawImage(eightBomb, x, y, w, h, mc);
break;
case9:
g.drawImage(bomb, x, y, w, h, mc);
break;
case10:
g.drawImage(bomb0, x, y, w, h, mc);
break;
case11:
g.drawImage(flag, x, y, w, h, mc);
break;
case12:
g.drawImage(flag2, x, y, w, h, mc);
break;
case13:
g.drawImage(bg, x, y, w, h, mc);
break;
}
}
publicRectangle getRec() {
returnnewRectangle(x, y, w, h);
}
}
MyMouseListener类(自定义的鼠标事件)
最难的都在这里面了
1.开始玩游戏的时候要保证第一下点击的不是地雷
2.点击到数字0(空白)时自动延伸
解决:
在解决问题之前 我们要首先知道鼠标点击的是哪个地雷
packagecom.xynu.mine;
importjava.awt.Rectangle;
importjava.awt.event.MouseAdapter;
importjava.awt.event.MouseEvent;
importjava.util.ArrayList;
importjava.util.Random;
publicclassMyMouseListener extendsMouseAdapter {
privateMineClient mc;
privateintcolNum;
privateintrowNum;
privatebooleanisFirstClick;
privateArrayList bombList = newArrayList();
boolean[] vis ;
publicMyMouseListener() {
super();
// TODO Auto-generated constructor stub
}
publicMyMouseListener(MineClient mc) {
super();
this.mc = mc;
colNum = mc.getColNum();
rowNum = mc.getRowNum();
vis = newboolean[colNum * rowNum];
bombList = mc.getBombList();
this.isFirstClick=mc.isFirstClick();
}
/*
* 鼠标松下事件
* 如果松下的是鼠标左键 那么显示当前位置的地雷
* 如果松下的鼠标右键 那么标记当前位置
* @see java.awt.event.MouseAdapter#mouseReleased(java.awt.event.MouseEvent)
*/
publicvoidmouseReleased(MouseEvent e) {
if(mc.getGameState().equals("lose")) {
return;
}
intx = e.getX();
inty = e.getY();
Rectangle rec = newRectangle(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);
}
elseif(bomb.getWhat()==11){
bomb.setWhat(12);
}
elseif(bomb.getWhat()==12){
bomb.setWhat(13);
}
}
}
}
}
}
//自动扩大区域直到遇见数字
privatevoidincreasePoint(intindex) {
if(vis[index])
return;
vis[index] = true;
booleanedgeU = 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);
}
}
//判断边界
privatebooleanjudgeLimit(inti) {
if(i >= 0&& i < bombList.size())
returntrue;
returnfalse;
}
//显示某位置
publicvoidsetVis(Bomb bomb, intindex) {
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
publicvoidmousePressed(MouseEvent e) {
if(mc.getGameState().equals("lose")) {
return;
}
if(e.getButton() == MouseEvent.BUTTON1) {
if(isFirstClick) {
isFirstClick = false;
mc.setFirstClick(false);
initBomb(e);
checkBomb();
}
}
}
privatevoidcheckBomb() {
for(Bomb bomb : bombList) {
intx = bombList.indexOf(bomb);
//edgeU edgeD边界状态值
booleanedgeU = 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);
}
}
}
//判断某位置是否是地雷
privatebooleanjudge(intx) {
if(x >= 0&& x < bombList.size()) {
if(bombList.get(x).getHide() == 9)
returntrue;
}
returnfalse;
}
/*
* 初始化地雷
*/
privatevoidinitBomb(MouseEvent e) {
intx = e.getX();
inty = e.getY();
Rectangle rec = newRectangle(x, y, 1, 1);
Bomb bombTemp=newBomb();
intwhat=0;
//为了避免第一下点击的不是地雷 首先让它设置为地雷,初始化地雷完成后 在恢复原样
for(Bomb bomb : bombList) {
if(rec.intersects(bomb.getRec())){
what=bomb.getHide();
bombTemp=bomb;
bomb.setHide(9);
break;
}
}
//使用随机数 初始化地图
Random r = newRandom();
for(inti = 0; i < mc.getMineNum(); i++) {
while(true) {
intindex = r.nextInt(bombList.size());
if(bombList.get(index).getHide() != 9) {
bombList.get(index).setHide(9);
break;
}
}
}
bombTemp.setHide(what);
}
}
还是自己的扫雷玩着有意思 哈哈
如果有问题 可以留言哦~一起解决