Project共有3个类:
UI类:主要负责绘制界面以及时间监听和鼠标监听,对于点击事件的搜索,失败与成功的判定等等。
Maze类:负责生成与管理内部的地图(int数组),随机生成迷宫。
Main类:程序入口。
运行效果:
程序代码:
UI.java
1 package MineSweeper; 2 3 import java.awt.event.*; 4 import javax.swing.*; 5 import javax.swing.Timer; 6 import javax.swing.border.EmptyBorder; 7 import javax.swing.table.*; 8 import java.awt.*; 9 import java.util.*; 10 import java.math.*; 11 12 public class UI extends JFrame{ 13 static Maze maze; 14 static Timer timer; 15 static int dir[][] = {{-1,0},{1,0},{0,-1},{0,1},{1,1},{1,-1},{-1,1},{-1,-1}}; 16 static JButton mmp[][] = new JButton[40][40]; 17 static Font enFont1 = new Font("Times New Roman",Font.BOLD,15); 18 static Font enFont2 = new Font("Times New Roman",Font.BOLD,20); 19 static Font enFont3 = new Font("Times New Roman",Font.BOLD,17); 20 static JPanel drawPanel,scorePanel; 21 static JLabel timeText,timeNum,leftText,leftNum; 22 static JButton select; 23 static int L,vis[][],isGameover; 24 public UI(int diff){ 25 if(diff == 1) L = 9; 26 else if(diff == 2) L = 16; 27 else L = 22; 28 isGameover = 0; 29 maze = new Maze(diff); 30 drawPanel = new JPanel(); 31 drawPanel.setLayout(null); 32 drawPanel.setBounds(5,10,25*L,25*L); 33 drawPanel.setBackground(Color.DARK_GRAY); 34 this.add(drawPanel); 35 for(int i = 1;i <= L;i ++){ 36 for(int j = 1;j <= L;j ++){ 37 final int ii = i,jj = j; 38 mmp[i][j] = new JButton(); 39 mmp[i][j].setBounds(j*25-25,i*25-25,25,25); 40 mmp[i][j].setFocusable(false); 41 mmp[i][j].setMargin(new Insets(0,0,0,0)); 42 mmp[i][j].setFont(enFont3); 43 mmp[i][j].addMouseListener(new MouseListener(){ 44 public void mouseClicked(MouseEvent e) { 45 if(timer == null){timer = new Timer(1000,new TimerListener());timer.start();} 46 if(isGameover == 1){return ;} 47 int Event = e.getButton(); // 通过该值可以判断按下的是哪个键 48 if(Event == MouseEvent.BUTTON1) {//left 49 if(mmp[ii][jj].isEnabled() == false) return ; 50 if(maze.mmp[ii][jj] == -1){GameOver(ii,jj);} 51 else if(maze.mmp[ii][jj] == 0){vis = new int[40][40];dfs(ii,jj);} 52 else {mmp[ii][jj].setEnabled(false);mmp[ii][jj].setText(String.valueOf(maze.mmp[ii][jj]));} 53 } 54 else if(Event == MouseEvent.BUTTON3) {//right 55 if(mmp[ii][jj].isEnabled() == false) return ; 56 if(mmp[ii][jj].getText().length() == 0){ 57 mmp[ii][jj].setText("X"); 58 } 59 else if(mmp[ii][jj].getText().charAt(0) == 'X'){ 60 mmp[ii][jj].setText("?"); 61 } 62 else if(mmp[ii][jj].getText().charAt(0) == '?'){ 63 mmp[ii][jj].setText(""); 64 } 65 } 66 if(isGameover == 0 && check() == 1){GameFinish();} 67 int cnt = 0; 68 for(int p = 1;p <= L;p ++){ 69 for(int q = 1;q <= L;q ++) { 70 if(mmp[p][q].getText().length() == 1 && mmp[p][q].getText().charAt(0) == 'X') { 71 cnt ++; 72 } 73 } 74 } 75 if(L == 9) leftNum.setText(String.valueOf(10-cnt)); 76 else if(L == 16) leftNum.setText(String.valueOf(40-cnt)); 77 else leftNum.setText(String.valueOf(100-cnt)); 78 } 79 public void mouseEntered(MouseEvent arg0) {} 80 public void mouseExited(MouseEvent arg0) {} 81 public void mousePressed(MouseEvent arg0) {} 82 public void mouseReleased(MouseEvent arg0) {} 83 }); 84 drawPanel.add(mmp[i][j]); 85 } 86 } 87 88 scorePanel = new JPanel(); 89 scorePanel.setLayout(null); 90 scorePanel.setBounds(25*L+10,10,150,225); 91 scorePanel.setBackground(Color.LIGHT_GRAY); 92 this.add(scorePanel); 93 timeText = new JLabel("Time :",JLabel.LEFT); 94 timeText.setFont(enFont2); 95 timeText.setBounds(20,5,110,25); 96 timeText.setOpaque(true); 97 timeText.setBackground(Color.white); 98 scorePanel.add(timeText); 99 timeNum = new JLabel("0",JLabel.RIGHT); 100 timeNum.setFont(enFont2); 101 timeNum.setBounds(20,35,110,25); 102 timeNum.setOpaque(true); 103 timeNum.setBackground(Color.white); 104 scorePanel.add(timeNum); 105 leftText = new JLabel("Mines :",JLabel.LEFT); 106 leftText.setFont(enFont2); 107 leftText.setBounds(20,70,110,25); 108 leftText.setOpaque(true); 109 leftText.setBackground(Color.white); 110 scorePanel.add(leftText); 111 leftNum = new JLabel("10",JLabel.RIGHT); 112 if(diff == 2){leftNum.setText("40");} 113 else if(diff == 3){leftNum.setText("100");} 114 leftNum.setFont(enFont2); 115 leftNum.setBounds(20,100,110,25); 116 leftNum.setOpaque(true); 117 leftNum.setBackground(Color.white); 118 scorePanel.add(leftNum); 119 120 select = new JButton("<html>Choose<br>Difficulty<html/>"); 121 select.setFont(enFont1); 122 select.setBounds(20,150,110,60); 123 select.setMargin(new Insets(0,0,0,0)); 124 select.setFocusable(false); 125 select.addActionListener(new ActionListener(){ 126 public void actionPerformed(ActionEvent e) { 127 Object[] possibleValues = { "9*9 && 10 Mines", "16*16 && 40 Mines", "22*22 && 100 Mines" }; 128 Object selectedValue = JOptionPane.showInputDialog(null, "Choose Difficulty", "Choose Difficulty", 129 JOptionPane.INFORMATION_MESSAGE, null, possibleValues, possibleValues[0]); 130 if(selectedValue == null){return ;} 131 if(selectedValue.toString().charAt(0) == '9'){dispose();new UI(1);} 132 else if(selectedValue.toString().charAt(0) == '1'){dispose();new UI(2);} 133 else{dispose();new UI(3);} 134 } 135 }); 136 scorePanel.add(select); 137 138 this.setTitle("MineSweeper"); 139 this.setLayout(null); 140 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 141 this.setSize(25*L+175,25*L+45); 142 Dimension winSize = Toolkit.getDefaultToolkit().getScreenSize(); 143 this.setLocation((winSize.width - this.getWidth()) / 2,(winSize.height - this.getHeight()) / 2); 144 this.setResizable(false); 145 this.setVisible(true); 146 } 147 148 static void dfs(int x,int y){ 149 vis[x][y] = 1; 150 mmp[x][y].setEnabled(false); 151 if(maze.mmp[x][y] >= 1){mmp[x][y].setText(String.valueOf(maze.mmp[x][y]));return ;} 152 mmp[x][y].setText(""); 153 for(int i = 0;i < 8;i ++){ 154 int xx = x + dir[i][0]; 155 int yy = y + dir[i][1]; 156 if(xx < 1 || xx > L || yy < 1 || yy > L){continue;} 157 if(vis[xx][yy] != 0){continue;} 158 if(maze.mmp[xx][yy] == -1){continue;} 159 if(i > 3){ 160 if(maze.mmp[xx][yy] == 0){continue;} 161 } 162 dfs(xx,yy); 163 } 164 } 165 166 static void GameFinish(){ 167 isGameover = 1; 168 timer.stop(); 169 String mess = "" 170 + "You have finish this game. Using time : " 171 + timeNum.getText() + " second(s). " 172 + "Thanks for your playing! "; 173 JOptionPane.showMessageDialog(null, mess, "Congratulations", JOptionPane.INFORMATION_MESSAGE); 174 } 175 176 static void GameOver(int x,int y){ 177 isGameover = 1; 178 timer.stop(); 179 for(int i = 1;i <= L;i ++){ 180 for(int j = 1;j <= L;j ++){ 181 if(mmp[i][j].isEnabled() == false){} 182 else if(maze.mmp[i][j] == -1 && mmp[i][j].getText().length() != 0 && mmp[i][j].getText().charAt(0) == 'X'){} 183 else if(maze.mmp[i][j] == -1){mmp[i][j].setText("X");} 184 else { 185 mmp[i][j].setText(""); 186 } 187 } 188 } 189 mmp[x][y].setBackground(Color.RED); 190 JOptionPane.showMessageDialog(null, "You triggered the mine !", "Gameover", JOptionPane.INFORMATION_MESSAGE); 191 } 192 193 static int check(){ 194 int cntX = 0,cnt = 0; 195 for(int i = 1;i <= L;i ++){ 196 for(int j = 1;j <= L;j ++){ 197 if(mmp[i][j].isEnabled() == false) continue; 198 if(mmp[i][j].getText().length() == 1 && mmp[i][j].getText().charAt(0) == '?'){return 0;} 199 if(mmp[i][j].getText().length() == 0){cnt ++;} 200 if(mmp[i][j].getText().length() == 1 && mmp[i][j].getText().charAt(0) == 'X' && maze.mmp[i][j] == -1){cntX ++;} 201 if(mmp[i][j].getText().length() == 1 && mmp[i][j].getText().charAt(0) == 'X' && maze.mmp[i][j] != -1){return 0;} 202 } 203 } 204 if(cntX == 10 && L == 9){return 1;} 205 if(cntX == 40 && L == 16){return 1;} 206 if(cntX == 100 && L == 22){return 1;} 207 if(cnt + cntX == 10 && L == 9){return 1;} 208 if(cnt + cntX == 40 && L == 16){return 1;} 209 if(cnt + cntX == 100 && L == 22){return 1;} 210 return 0; 211 } 212 213 class TimerListener implements ActionListener { 214 public void actionPerformed(ActionEvent e) { 215 timeNum.setText(String.valueOf(Integer.valueOf(timeNum.getText()) + 1)); 216 } 217 } 218 }
Maze.java
1 package MineSweeper; 2 3 import java.util.*; 4 import java.math.*; 5 6 public class Maze { 7 static int L; 8 static int mmp[][] = new int[40][40];//(0,1,...,8) = space , -1 = mine 9 static int dir[][] = {{-1,0},{1,0},{0,-1},{0,1},{1,1},{1,-1},{-1,1},{-1,-1}}; 10 public Maze(int diff){ 11 if(diff == 1) L = 9; 12 else if(diff == 2) L = 16; 13 else L = 22; 14 randomMaze(); 15 } 16 17 static void randomMaze(){ 18 for(int i = 1;i <= L;i ++){ 19 for(int j = 1;j <= L;j ++){ 20 mmp[i][j] = 0; 21 } 22 } 23 int cnt = 0; 24 if(L == 9) cnt = 10; 25 else if(L == 16) cnt = 40; 26 else cnt = 100; 27 for(int i = 0;i < cnt;i ++){ 28 int x = (int)(Math.random() * 1000) % L + 1; 29 int y = (int)(Math.random() * 1000) % L + 1; 30 while(mmp[x][y] == -1){ 31 x = (int)(Math.random() * 1000) % L + 1; 32 y = (int)(Math.random() * 1000) % L + 1; 33 } 34 mmp[x][y] = -1; 35 } 36 for(int i = 1;i <= L;i ++){ 37 for(int j = 1;j <= L;j ++){ 38 if(mmp[i][j] == -1){ 39 for(int k = 0;k < 8;k ++){ 40 int x = i + dir[k][0]; 41 int y = j + dir[k][1]; 42 if(mmp[x][y] != -1){mmp[x][y] ++;} 43 } 44 } 45 } 46 } 47 for(int i = 1;i <= L;i ++){ 48 for(int j = 1;j <= L;j ++){ 49 System.out.printf("%3d",mmp[i][j]); 50 }System.out.println(); 51 } 52 } 53 54 }
Main.java
1 package MineSweeper; 2 3 public class Main { 4 public static void main(String[] args) { 5 new UI(1); 6 } 7 8 }