Java课程设计——扫雷(winmine)
因为是我的课程设计,要是有冲突就不好了,转载注明出处!!!
程序很简单,毕竟我是搞acm的,我就只介绍一下闪光点。
中心空白搜索的时候,我用的DFS;
有一点是要注意的,就是JFrame不支持重画,还好机智我用的是JPanel,利用这个画板重画游戏区。
API文档之后补上。
package com.TreeDream.MyGame; public class Block { String name; int number; boolean boo = false; public void setName(String name) { this.name = name; } public void setNumber(int n) { number = n; } public int getNumber() { return number; } public String getName() { return name; } public void setIsMine(boolean boo) { this.boo = boo; } public boolean isMine() { return boo; } }
package com.TreeDream.MyGame; import java.awt.CardLayout; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; public class BlockView extends JPanel { JLabel blockName; //标签 JButton blockCover; //按钮 CardLayout card; public BlockView() { card = new CardLayout(); setLayout(card); blockName = new JLabel(); blockCover = new JButton(); add("cover",blockCover); add("name",blockName); } public void setName(String name) { blockName.setText(name); } public String getName() { return blockName.getText(); } public void seeBlockName() { card.show(this, "name"); } public void seeBlockCover() { card.show(this, "cover"); validate(); } public JButton getBlockCover() { return blockCover; } public JLabel getBlockName () { return blockName; } }
package com.TreeDream.MyGame; import java.util.LinkedList; public class LayMines { public void layMinesForBlock(Block[][] block,int mineCount){ int row=block.length; int colum=block[0].length; LinkedList<Block> list=new LinkedList<Block>();//创建空链表 for(int i=0;i<row;i++){ for(int j=0;j<colum;j++){ list.add(block[i][j]); } } while(mineCount>0){ int size=list.size(); int randomIndex=(int)(Math.random()*size); Block b=(Block)list.get(randomIndex); b.setName("*"); b.setIsMine(true); list.remove(randomIndex); mineCount--; } for(int i=0;i<row;i++){//非雷 for(int j=0;j<colum;j++){ if(block[i][j].isMine()==false){ int mineNumber=0;//周围雷的设置 for(int k=Math.max(i-1,0);k<=Math.min(i+1,row-1);k++){ for(int t=Math.max(j-1,0);t<=Math.min(j+1,colum-1);t++){ if(block[k][t].isMine()==true){ mineNumber++; } } } if(mineNumber==0){ block[i][j].setName(""); block[i][j].setNumber(mineNumber); } else{ block[i][j].setName(""+mineNumber); block[i][j].setNumber(mineNumber); } } } } } }
1 package com.TreeDream.MyGame; 2 3 import java.applet.Applet; 4 import java.applet.AudioClip; 5 import java.awt.BorderLayout; 6 import sun.audio.*; 7 import java.io.*; 8 import java.net.MalformedURLException; 9 import java.awt.Color; 10 import java.awt.GridLayout; 11 import java.awt.Label; 12 import java.awt.MenuBar; 13 import java.awt.Panel; 14 import java.awt.event.ActionEvent; 15 import java.awt.event.ActionListener; 16 import java.awt.event.MouseEvent; 17 import java.awt.event.MouseListener; 18 import java.security.cert.TrustAnchor; 19 20 import javax.sound.midi.MidiChannel; 21 import javax.sound.sampled.AudioInputStream; 22 import javax.swing.BorderFactory; 23 import javax.swing.BoundedRangeModel; 24 import javax.swing.Icon; 25 import javax.swing.ImageIcon; 26 import javax.swing.JButton; 27 import javax.swing.JFrame; 28 import javax.swing.JLabel; 29 import javax.swing.JMenu; 30 import javax.swing.JMenuBar; 31 import javax.swing.JMenuItem; 32 import javax.swing.JOptionPane; 33 import javax.swing.JPanel; 34 import javax.swing.JTable; 35 import javax.swing.JTextField; 36 import javax.swing.RowFilter; 37 import javax.swing.border.Border; 38 39 /** 40 * 游戏布局 41 * @author YinJian 42 * 43 */ 44 45 46 public class MineMainFrame extends JFrame implements ActionListener,MouseListener { 47 48 /** 49 * 菜单条 50 */ 51 JMenuBar menuBar = new JMenuBar(); 52 /** 53 * 菜单 54 */ 55 JMenu about = new JMenu("关于"); 56 /** 57 * 子菜单 58 */ 59 JMenuItem exItem,aboutItem; 60 61 /** 62 * 行数输入文本框 63 */ 64 JTextField inputRow = new JTextField(5); 65 66 /** 67 * 列数输入文本框 68 */ 69 JTextField inputColum = new JTextField(5); 70 71 /** 72 * 雷数输入文本 73 */ 74 JTextField inputMineCount = new JTextField(5); 75 76 /** 77 * 游戏对象 78 */ 79 MineMainFrame mainFrame = this; 80 81 /** 82 * 开始按钮 83 */ 84 JButton start; 85 86 /** 87 * 方块的二维数组 88 */ 89 Block block[][]; 90 /** 91 * 方块的视图数组 92 */ 93 BlockView blockView[][]; 94 95 /** 96 * 深搜标记 97 */ 98 boolean vis[][]; 99 100 /** 101 * 雷是否被插旗 102 */ 103 boolean isFlag[][]; 104 105 /** 106 * 当前插旗的数目 107 */ 108 int flagNum; 109 110 /** 111 * 游戏行数 112 */ 113 int row; 114 115 /** 116 * 游戏列数 117 */ 118 int colum; 119 120 /** 121 * 游戏雷数 122 */ 123 int mineCount; 124 125 /** 126 * 游戏中心区 127 */ 128 JPanel pCenter; 129 130 /** 131 * 游戏输入区 132 */ 133 JPanel pNorth; 134 135 /** 136 * 游戏雷的布局对象 137 */ 138 LayMines lay; 139 140 141 Icon icon1 = new ImageIcon("img/1.jpg"); 142 Icon icon2 = new ImageIcon("img/2.jpg"); 143 Icon icon3 = new ImageIcon("img/3.jpg"); 144 Icon icon4 = new ImageIcon("img/4.jpg"); 145 Icon icon5 = new ImageIcon("img/5.jpg"); 146 Icon icon6 = new ImageIcon("img/6.jpg"); 147 Icon icon7 = new ImageIcon("img/7.jpg"); 148 Icon icon8 = new ImageIcon("img/8.jpg"); 149 Icon icon9 = new ImageIcon("img/9.jpg"); 150 Icon iconflag = new ImageIcon("img/红旗.jpg"); 151 Icon iconmine = new ImageIcon("img/雷.jpg"); 152 153 /** 154 * 音乐 155 */ 156 AudioClip music; 157 158 /** 159 * 游戏初始化,构造函数 160 * @param title 游戏标题 161 */ 162 public MineMainFrame(String title) { 163 setTitle(title); 164 165 //插入音乐 166 File file = new File("musics/Lone Ranger.wav"); 167 168 try { 169 music = Applet.newAudioClip(file.toURI().toURL()); 170 music.play(); 171 } catch (MalformedURLException e) { 172 e.printStackTrace(); 173 } 174 175 //菜单制作 176 exItem = new JMenuItem("退出"); 177 aboutItem = new JMenuItem("介绍"); 178 179 aboutItem.addActionListener(new AboutListen()); 180 exItem.addActionListener(new exitActionListen()); 181 182 about.add(aboutItem); 183 about.add(exItem); 184 185 menuBar.add(about); 186 187 setJMenuBar(menuBar); 188 189 190 //画游戏区域 191 start = new JButton("开始"); 192 pCenter = new JPanel(); 193 pNorth = new JPanel(); 194 pNorth.setBackground(Color.red); 195 196 start.addActionListener(this); 197 inputColum.addActionListener(this); 198 inputMineCount.addActionListener(this); 199 inputRow.addActionListener(this); 200 201 pNorth.add(new JLabel("row")); 202 pNorth.add(inputRow); 203 pNorth.add(new JLabel("col")); 204 pNorth.add(inputColum); 205 pNorth.add(new JLabel("count")); 206 pNorth.add(inputMineCount); 207 pNorth.add(start); 208 add(pNorth, BorderLayout.NORTH); 209 setBounds(300, 100, 550, 550); 210 setVisible(true); 211 validate(); 212 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 213 } 214 215 /** 216 * 监听文本框,开始按钮,和游戏区的动作 217 */ 218 public void actionPerformed(ActionEvent e) { 219 String str = e.getActionCommand(); 220 if (e.getSource() == inputRow) { 221 row = Integer.parseInt(str); 222 System.out.println(row); 223 } 224 if (e.getSource() == inputColum) { 225 colum = Integer.parseInt(str); 226 System.out.println(colum); 227 } 228 if (e.getSource() == inputMineCount) { 229 mineCount = Integer.parseInt(str); 230 System.out.println(mineCount); 231 } 232 233 else { 234 JButton source = (JButton) e.getSource(); 235 if (source != start) { 236 int m = -1, n = -1; 237 for (int i = 0; i < row; i++) { 238 for (int j = 0; j < colum; j++) { 239 if (source == blockView[i][j].getBlockCover()) { 240 m = i; 241 n = j; 242 break; 243 } 244 } 245 } 246 if (block[m][n].isMine()) { 247 for (int i = 0; i < row; i++) { 248 for (int j = 0; j < colum; j++) { 249 blockView[i][j].getBlockCover().removeActionListener(this); 250 if (block[i][j].isMine()) { 251 blockView[i][j].seeBlockName(); 252 } 253 } 254 } 255 JOptionPane.showMessageDialog(this, "小朋友你挂了哦!快看看你踩到哪个雷了啊"); 256 257 } else { 258 if (block[m][n].getNumber() > 0) { 259 vis[m][n] = true; 260 blockView[m][n].seeBlockName(); 261 } else if (block[m][n].getNumber() == 0) { 262 dfs(m, n); 263 } 264 } 265 } 266 if (source == start) { 267 remove(this.pCenter); 268 pCenter = new JPanel(); 269 flagNum = 0; 270 System.out.println("hello"); 271 block = new Block[row][colum]; 272 vis = new boolean[row][colum]; 273 isFlag = new boolean[row][colum]; 274 275 for (int i = 0; i < row; i++) { 276 for (int j = 0; j < colum; j++) { 277 block[i][j] = new Block(); 278 vis[i][j] = false; 279 280 } 281 } 282 283 lay = new LayMines(); 284 lay.layMinesForBlock(block, mineCount); 285 286 blockView = new BlockView[row][colum]; 287 288 pCenter.setLayout(new GridLayout(row, colum)); 289 290 for (int i = 0; i < row; i++) { 291 for (int j = 0; j < colum; j++) { 292 blockView[i][j] = new BlockView(); 293 // blockView[i][j].setName(block[i][j].getName()); 294 // 给blockView视图添加上图片 295 if (block[i][j].getNumber() > 0) { 296 297 if (block[i][j].getNumber() == 1) 298 blockView[i][j].getBlockName().setIcon(icon1); 299 if (block[i][j].getNumber() == 2) 300 blockView[i][j].getBlockName().setIcon(icon2); 301 if (block[i][j].getNumber() == 3) 302 blockView[i][j].getBlockName().setIcon(icon3); 303 if (block[i][j].getNumber() == 4) 304 blockView[i][j].getBlockName().setIcon(icon4); 305 if (block[i][j].getNumber() == 5) 306 blockView[i][j].getBlockName().setIcon(icon5); 307 if (block[i][j].getNumber() == 6) 308 blockView[i][j].getBlockName().setIcon(icon6); 309 if (block[i][j].getNumber() == 7) 310 blockView[i][j].getBlockName().setIcon(icon7); 311 if (block[i][j].getNumber() == 8) 312 blockView[i][j].getBlockName().setIcon(icon8); 313 if (block[i][j].getNumber() == 9) 314 blockView[i][j].getBlockName().setIcon(icon9); 315 } 316 317 if (block[i][j].isMine()) { 318 blockView[i][j].getBlockName().setIcon(iconmine); 319 isFlag[i][j] = false; 320 } 321 322 pCenter.add(blockView[i][j]); 323 blockView[i][j].getBlockCover().addActionListener(this); 324 blockView[i][j].getBlockCover().addMouseListener(this); 325 } 326 } 327 328 add(pCenter, BorderLayout.CENTER); 329 setVisible(true); 330 validate(); 331 } 332 } 333 334 } 335 336 /** 337 * dfs的方向 338 */ 339 int dr[] = { -1, -1, -1, 0, 0, 1, 1, 1 }; 340 /** 341 * dfs的方向 342 */ 343 int dc[] = { -1, 0, 1, -1, 1, -1, 0, 1 }; 344 345 /** 346 * 深度优先搜索 347 * @param x 行坐标 348 * @param y 列坐标 349 */ 350 public void dfs(int x, int y) { 351 352 vis[x][y] = true; 353 blockView[x][y].seeBlockName(); 354 355 for (int i = 0; i < 8; i++) { 356 int dx = x + dr[i]; 357 int dy = y + dc[i]; 358 359 if (dx >= 0 && dx < row && dy >= 0 && dy < colum && !block[dx][dy].isMine() && !vis[dx][dy]) { 360 if (block[dx][dy].getNumber() == 0) { 361 dfs(dx, dy); 362 } else { 363 vis[dx][dy] = true; 364 blockView[dx][dy].seeBlockName(); 365 } 366 } 367 } 368 369 } 370 371 /** 372 * 判断是否胜利 373 */ 374 void win() { 375 int flag = 0; 376 for (int i = 0; i < row; i++) { 377 for (int j = 0; j < colum; j++) { 378 if (block[i][j].isMine()==true&&isFlag[i][j] == true) 379 flag ++; 380 } 381 } 382 if (flag == mineCount) { 383 for (int i = 0; i < row; i++) { 384 for (int j = 0; j < colum; j++) { 385 blockView[i][j].getBlockCover().removeActionListener(this); 386 blockView[i][j].getBlockCover().removeMouseListener(this); 387 } 388 } 389 JOptionPane.showMessageDialog(this, "小朋友,恭喜你胜利了啊"); 390 391 } 392 393 if (flagNum>mineCount) { 394 for (int i = 0; i < row; i++) { 395 for (int j = 0; j < colum; j++) { 396 blockView[i][j].getBlockCover().removeActionListener(this); 397 blockView[i][j].getBlockCover().removeMouseListener(this); 398 } 399 } 400 JOptionPane.showMessageDialog(this, "小朋友,你违规了,你的小红旗数目太多了!"); 401 } 402 403 } 404 405 /** 406 * 鼠标右击插上红旗 407 */ 408 @Override 409 public void mouseClicked(MouseEvent e) { // 鼠标单击 410 JButton button = (JButton) e.getSource(); 411 412 if (e.getButton() == MouseEvent.BUTTON3) { // 右击鼠标插上红旗在JButton上,不能是JLabel上,不然就给出答案了; 413 button.setIcon(iconflag); 414 flagNum ++; 415 // isFlag[][] 416 int m=-1, n=-1; 417 for (int i = 0; i < row; i++) { 418 for (int j = 0; j < colum; j++) { 419 if (button == blockView[i][j].getBlockCover()) { 420 m = i; 421 n = j; 422 break; 423 } 424 } 425 } 426 isFlag[m][n] = true; 427 button.removeMouseListener(this); 428 win(); 429 } 430 431 } 432 433 @Override 434 public void mouseEntered(MouseEvent e) { // 鼠标进入 435 436 } 437 438 @Override 439 public void mouseExited(MouseEvent e) { // 鼠标离开组件 440 441 } 442 443 @Override 444 public void mousePressed(MouseEvent e) { // 鼠标按下 445 446 } 447 448 @Override 449 public void mouseReleased(MouseEvent e) { // 鼠标释放 450 451 } 452 453 /** 454 * 菜单退出的动作事件 455 * @author YinJian 456 * 457 */ 458 public class exitActionListen implements ActionListener { 459 @Override 460 public void actionPerformed(ActionEvent e) { 461 System.exit(0); 462 } 463 } 464 465 /** 466 * 菜单关于的动作时间 467 * @author YinJian 468 * 469 */ 470 public class AboutListen implements ActionListener { 471 @Override 472 public void actionPerformed(ActionEvent e) { 473 JOptionPane.showMessageDialog(mainFrame, "尹建制作", "关于扫雷", JOptionPane.PLAIN_MESSAGE); 474 } 475 } 476 477 }
1 package com.TreeDream.MyGame; 2 3 /** 4 * 游戏创建 5 * @author YinJian 6 * 7 */ 8 9 public class Main { 10 11 /** 12 * 主函数创建游戏 13 * @param args 14 */ 15 public static void main(String[] args) { 16 new MineMainFrame("winmine"); 17 } 18 19 }