乞丐版JAVA扫雷
事先声明:本人是一位刚接触Java不久的菜鸟,所以代码写的略显臃肿,敬请谅解!这个扫雷是我在暑假时做的,灵感来源于csdn上某位大神的博客,不过我个人实在不喜欢他的代码实现,于是我自己写了一个实现上不同的扫雷。
这是那位大牛那篇扫雷的博客链接:http://blog.csdn.net/su20145104009/article/details/52152514,有兴趣的可以去浏览下。
程序:主界面上和Windows经典的那款扫雷很像,正上方有一个笑脸按钮,用于游戏重启,下面是雷区,用一个继承于JButton组件的类型实现。笑脸按钮两侧,一侧用JLabel显示剩余雷数,一侧用JLabel显示使用的时间。菜单栏上有难度设置,也是仿制windows经典扫雷的难度设置,即9*9,16*16,30*16三种级别。之所以叫乞丐版主要是左右同时敲击鼠标不能敲开周围的块而且没有排名并且记录的那个功能。
P.S.:用的好端端的edge浏览器TMD崩了,我真他们是CTM,我本来写的一大堆程序解释瞬间消失,算了我还是直接讲最主要算法吧。(这一下弄得我实在是没有热情再写那么详细了,我明明已经快写完了。第一次草稿保存的是如上内容,晚上修改的后面的所有全没了。网页崩了而我的系统屁事儿没有依旧飞快运转。。。。我可是在熬夜写这个啊)
主要难点在于如何判断点击后如何判断九宫格的位置,要引入两个值,edgeU和edgeD(不偏不倚这两个值我还真的给他们起名为edge,看着就来气),在雷区内总有些位置很尴尬它们周围并没有形成完全的九宫格,不过没有关系。因为在整个区域内只用两条竖边很特殊,它们的前一个或者后一个不一定在它们的左边或者右边,这个时候利用上面那两个值就很管用了,具体怎么用的我不想讲了,请自己去看代码吧(热情实在是被浇灭了。。。)在判断完九宫格内雷数后,你还要展开周围没有雷的地方(被展开的周围如有空位置也要一起展开),具体实现也请看代码。
1 import javax.swing.ImageIcon; 2 import javax.swing.JButton; 3 import javax.swing.JFrame; 4 import javax.swing.JLabel; 5 import javax.swing.JMenu; 6 import javax.swing.JMenuBar; 7 import javax.swing.JMenuItem; 8 import javax.swing.JPanel; 9 import java.awt.Font; 10 import java.awt.GridLayout; 11 import java.awt.event.ActionEvent; 12 import java.awt.event.ActionListener; 13 import java.util.ArrayList; 14 import java.awt.event.MouseEvent; 15 import java.awt.event.MouseListener; 16 import java.util.Random; 17 18 public class Main extends JFrame implements MouseListener{ 19 private int screenwide; 20 private int screenhigh; 21 private int colNum; 22 private int rowNum; 23 private int mineNum; 24 private int restNum; 25 private int min = 0;//分钟 26 private int sec = 0;//秒钟 27 private JLabel label1;//显示时间用 28 private JLabel label2;//显示剩余雷数 29 private JButton button;//笑脸按钮,用于重新开始 30 private String gameState = "run";//游戏运行状态 31 private boolean isfirst = true;//判断是否是第一次按下 32 //难度选择菜单 33 private JMenuBar menuBar; 34 private JMenu menu; 35 private JMenuItem low; 36 private JMenuItem mid; 37 private JMenuItem high; 38 //核心模块 39 private ArrayList<Bub>list = new ArrayList<Bub>(0); 40 public boolean isFirst() { 41 return isfirst; 42 } 43 public void initMenu() { 44 menuBar = new JMenuBar(); 45 menu = new JMenu("难度设置"); 46 low = new JMenuItem("初级(10)"); 47 mid = new JMenuItem("中级(40)"); 48 high = new JMenuItem("高级(99)"); 49 low.addActionListener(new ActionListener() { 50 public void actionPerformed(ActionEvent e) { 51 dispose(); 52 new Main(10); 53 } 54 }); 55 mid.addActionListener(new ActionListener() { 56 public void actionPerformed(ActionEvent e) { 57 dispose(); 58 new Main(40); 59 } 60 }); 61 high.addActionListener(new ActionListener() { 62 public void actionPerformed(ActionEvent e) { 63 dispose(); 64 new Main(99); 65 } 66 }); 67 menu.add(low); 68 menu.add(mid); 69 menu.add(high); 70 menuBar.add(menu); 71 setJMenuBar(menuBar); 72 } 73 class stopwatch extends Thread{ 74 public void run() { 75 while(gameState.equals("run")) { 76 try { 77 Thread.sleep(1000); 78 }catch(InterruptedException e) { 79 e.printStackTrace(); 80 } 81 sec++; 82 if(sec==60) { 83 sec=0; 84 min++; 85 } 86 if(min==0&&sec<10)label1.setText("00:0"+new Integer(sec).toString()); 87 if(min==0&&sec>=10)label1.setText("00:"+new Integer(sec).toString()); 88 if(min>0&&sec<10)label1.setText(new Integer(min).toString()+":0"+new Integer(sec).toString()); 89 if(min>0&&sec>=10)label1.setText(new Integer(min).toString()+":"+new Integer(sec).toString()); 90 } 91 } 92 } 93 public Main(int num) { 94 super("扫雷"); 95 mineNum = num; 96 restNum = mineNum; 97 if(mineNum == 10) { 98 screenwide = 200; 99 screenhigh = 290; 100 colNum = 9; 101 rowNum = 9; 102 } 103 if(mineNum == 40) { 104 screenwide = 340; 105 screenhigh = 430; 106 colNum = 16; 107 rowNum = 16; 108 } 109 if(mineNum == 99) { 110 screenwide = 620; 111 screenhigh = 430; 112 colNum = 30; 113 rowNum = 16; 114 } 115 initMenu(); 116 setSize(screenwide,screenhigh); 117 setLayout(null); 118 setLocationRelativeTo(null); 119 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 120 121 button = new JButton(new ImageIcon("D:\\学习文档\\smile1.jpg")); 122 button.setBounds(screenwide/2-20, 5, 20, 20); 123 button.addActionListener(new ActionListener() { 124 public void actionPerformed(ActionEvent e) { 125 dispose(); 126 new Main(mineNum); 127 } 128 }); 129 add(button); 130 label1 = new JLabel("剩余时间"); 131 label1.setBounds(10,5,60,20); 132 add(label1); 133 134 label2 = new JLabel("剩余:"+restNum); 135 label2.setBounds(screenwide-70,5,60,20); 136 add(label2); 137 JPanel p = new JPanel(); 138 p.setLayout(new GridLayout(rowNum,colNum,0,0)); 139 for(int i = 0;i<rowNum*colNum;++i) { 140 Bub bub = new Bub(); 141 bub.showImg(13); 142 bub.addMouseListener(this); 143 list.add(bub); 144 p.add(bub); 145 } 146 p.setBounds(0,40,colNum*20,rowNum*20); 147 add(p); 148 this.setVisible(true); 149 } 150 public static void main(String[]args) { 151 new Main(10); 152 } 153 class Result extends JFrame { 154 /** 155 * 156 */ 157 private static final long serialVersionUID = 7899366376251467187L; 158 159 public Result(String con) { 160 super("游戏结果"); 161 setSize(250,150); 162 setLocationRelativeTo(null); 163 JButton button = new JButton("确定"); 164 setLayout(null); 165 JLabel label3 = new JLabel(); 166 button.addActionListener(new ActionListener() { 167 public void actionPerformed(ActionEvent e) { 168 dispose(); 169 } 170 }); 171 label3.setFont(new Font("微软雅黑",Font.BOLD,15)); 172 if(con.equals("win")) label3.setText("用时"+min+"分"+sec+"秒"); 173 if(con.equals("lose"))label3.setText("继续努力!"); 174 label3.setBounds(70, 5, 100, 40); 175 add(label3); 176 button.setBounds(80, 50, 70, 40); 177 add(button); 178 setVisible(true); 179 } 180 } 181 @Override 182 public void mouseClicked(MouseEvent arg0) { 183 // TODO 自动生成的方法存根 184 185 } 186 187 @Override 188 public void mouseEntered(MouseEvent arg0) { 189 // TODO 自动生成的方法存根 190 191 } 192 193 @Override 194 public void mouseExited(MouseEvent arg0) { 195 // TODO 自动生成的方法存根 196 197 } 198 199 @Override 200 public void mousePressed(MouseEvent arg0) { 201 // TODO 自动生成的方法存根 202 203 } 204 public boolean judge(int index) { 205 if(index>=0&&index<list.size()) { 206 if(list.get(index).getreal()==1)return true; 207 } 208 return false; 209 } 210 public boolean judgeLimit(int index) { 211 if(index>=0&&index<list.size()) return true; 212 return false; 213 } 214 public void show(int index) { 215 Bub tmp1 = list.get(index);//当前点击位置的在链表中的索引 216 int cnt = 0; //四周雷数的记录值 217 boolean edgeU = (index%colNum!= 0); //判断是否在右边界 218 boolean edgeD = ((index+1)%colNum!= 0); //判断是否在左边界 219 if(judge(index-colNum))tmp1.setface(++cnt); 220 if(judge(index+colNum))tmp1.setface(++cnt); 221 if(judge(index-1)&&edgeU)tmp1.setface(++cnt); 222 if(judge(index+1)&&edgeD)tmp1.setface(++cnt); 223 if(judge(index-colNum+1)&&edgeD)tmp1.setface(++cnt); 224 if(judge(index+colNum+1)&&edgeD)tmp1.setface(++cnt); 225 if(judge(index-colNum-1)&&edgeU)tmp1.setface(++cnt); 226 if(judge(index+colNum-1)&&edgeU)tmp1.setface(++cnt); 227 if(cnt==0) { 228 tmp1.setface(0); 229 tmp1.showImg(0); 230 if(!judge(index-colNum)&&judgeLimit(index-colNum)&&!list.get(index-colNum).getOpen())show(index-colNum);//为了避免这里的递归陷入了死循环,要对相邻的按钮进行判断,如果已经处于翻开状态,就不用在进一步操作 231 if(!judge(index+colNum)&&judgeLimit(index+colNum)&&!list.get(index+colNum).getOpen())show(index+colNum); 232 if(!judge(index-1)&&edgeU&&judgeLimit(index-1)&&!list.get(index-1).getOpen())show(index-1); 233 if(!judge(index+1)&&edgeD&&judgeLimit(index+1)&&!list.get(index+1).getOpen())show(index+1); 234 if(!judge(index-colNum+1)&&edgeD&&judgeLimit(index-colNum+1)&&!list.get(index-colNum+1).getOpen())show(index-colNum+1); 235 if(!judge(index+colNum+1)&&edgeD&&judgeLimit(index+colNum+1)&&!list.get(index+colNum+1).getOpen())show(index+colNum+1); 236 if(!judge(index-colNum-1)&&edgeU&&judgeLimit(index-colNum-1)&&!list.get(index-colNum-1).getOpen())show(index-colNum-1); 237 if(!judge(index+colNum-1)&&edgeU&&judgeLimit(index+colNum-1)&&!list.get(index+colNum-1).getOpen())show(index+colNum-1); 238 } 239 else tmp1.showImg(cnt); 240 } 241 @Override 242 public void mouseReleased(MouseEvent e) { 243 Bub tmp = (Bub)e.getSource(); 244 int index = list.indexOf(tmp); 245 if(this.gameState.equals("over"))return; 246 else { 247 if(e.getButton()==MouseEvent.BUTTON1) { 248 if(tmp.getface()!=11&&tmp.getface()!=12) { 249 if(isfirst) { 250 tmp.setreal(1); 251 Random r = new Random(); 252 int len = list.size(); 253 for(int i = 1;i<=mineNum;++i) { 254 while(true) { 255 int des = r.nextInt(len); 256 if(list.get(des).getreal()!=1) { 257 list.get(des).setreal(1); 258 list.get(des).showImg(13); 259 break; 260 } 261 } 262 } 263 tmp.setreal(0); 264 isfirst = false; 265 show(index); 266 new stopwatch().start(); 267 } 268 else if(tmp.getreal()!=1){ 269 show(index); 270 } 271 else if(tmp.getreal()==1) { 272 for(Bub bub:list) { 273 if(bub.getreal()==1)bub.showImg(9); 274 if(bub.getreal()==0&&bub.getface()==11) { 275 bub.setface(10);bub.showImg(10); 276 } 277 } 278 gameState = "over"; 279 button.setIcon(new ImageIcon("D:\\学习文档\\smile3.jpg")); 280 new Result("lose"); 281 282 } 283 } 284 } 285 if(e.getButton()==MouseEvent.BUTTON3) { 286 if(tmp.getface()==13) { 287 tmp.setface(11); 288 tmp.showImg(11); 289 restNum--; 290 } 291 else if(tmp.getface()==11) { 292 tmp.setface(12); 293 tmp.showImg(12); 294 restNum++; 295 } 296 else if(tmp.getface()==12) { 297 tmp.setface(13); 298 tmp.showImg(13); 299 } 300 } 301 if(restNum==0) { 302 int total = 0; 303 for(Bub bub1:list) { 304 if(bub1.getface()==11&&bub1.getreal()==1)total++; 305 } 306 if(total==mineNum) { 307 gameState = "over"; 308 button.setIcon(new ImageIcon("D:\\学习文档\\smile2.jpg")); 309 new Result("win"); 310 } 311 } 312 label2.setText("剩余:"+restNum); 313 } 314 } 315 }
1 import javax.swing.ImageIcon; 2 import javax.swing.JButton; 3 4 public class Bub extends JButton{ 5 6 private int face=13; //表面上的图形显示 7 private int real=0; //有无雷,有雷为1,无雷为0 8 private boolean isOpen = false;//表明当前按钮的状态,true表示已经翻开,false表示还未翻开 9 private ImageIcon[]img = new ImageIcon[14]; 10 public Bub() { 11 super(); 12 img[0] = new ImageIcon("D:\\学习文档\\0mine.jpg"); 13 img[1] = new ImageIcon("D:\\学习文档\\1mine.jpg"); 14 img[2] = new ImageIcon("D:\\学习文档\\2mine.jpg"); 15 img[3] = new ImageIcon("D:\\学习文档\\3mine.jpg"); 16 img[4] = new ImageIcon("D:\\学习文档\\4mine.jpg"); 17 img[5] = new ImageIcon("D:\\学习文档\\5mine.jpg"); 18 img[6] = new ImageIcon("D:\\学习文档\\6mine.jpg"); 19 img[7] = new ImageIcon("D:\\学习文档\\7mine.jpg"); 20 img[8] = new ImageIcon("D:\\学习文档\\8mine.jpg"); 21 img[9] = new ImageIcon("D:\\学习文档\\mine.jpg"); 22 img[10] = new ImageIcon("D:\\学习文档\\mineerr.jpg"); 23 img[11] = new ImageIcon("D:\\学习文档\\flag.jpg"); 24 img[12] = new ImageIcon("D:\\学习文档\\flag2.jpg"); 25 img[13] = new ImageIcon("D:\\学习文档\\bg.jpg"); 26 } 27 public int getface() { 28 return face; 29 } 30 public int getreal() { 31 return real; 32 } 33 public void setface(int c) { 34 face = c; 35 } 36 public void setreal(int c) { 37 real = c; 38 } 39 public void setOpen(boolean swit) { 40 isOpen = swit; 41 } 42 public boolean getOpen() { 43 return isOpen; 44 } 45 public void showImg(int c) { 46 this.setIcon(img[c]); 47 if(c!=13)isOpen = true; 48 } 49 }
水品有限,代码写得很臃肿,仅限个人娱乐