首先说一下扫雷规则。
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(); } } } } }
解释两个变量。、
what表示当前地雷(不一定是地雷)所画的内容
hide表示当前地雷(不一定是地雷)真实的内容
解释两个方法
public Rectangle getRec() { return new Rectangle(x, y, w, h); }返回当前地雷的矩形,具体作用我会在MyMouseListener类里面说
draw(Graphics g)
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())){ //表示鼠标矩形和地雷矩形相交 } }
然后通过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); } }还是自己的扫雷玩着有意思 哈哈
如果有问题 可以留言哦~一起解决
所有代码+图片
下载地址:
原文:http://blog.csdn.net/su20145104009/article/details/52152514