1 import java.awt.*;2 import java.awt.event.*;3 import javax.swing.*;4 public classFrame5 extendsJFrame {6 JTextField text;7 JLabel nowBomb, setBomb;8 int BombNum, BlockNum; //当前雷数,当前方块数
9 int rightBomb, restBomb, restBlock; //找到的地雷数,剩余雷数,剩余方块数
10
11 JButton start = new JButton(" 开始 ");//初始化一个开始的按钮
12 JPanel MenuPanel = new JPanel();//新建一个区域,作为菜单
13 JPanel bombPanel = new JPanel();//新建一个区域,作为雷区
14 Bomb[][] bombButton;//2维数组,防地雷
15
16 JPanel c;17 BorderLayout borderLayout1 = new BorderLayout();//布局管理器边界布局
18 GridLayout gridLayout1 = new GridLayout();//布局一个网格布局
19 publicFrame() {20 try{21 setDefaultCloseOperation(EXIT_ON_CLOSE);//关闭操作并结束进程
22 jbInit();//一般用于对程序进行初始化
23 }24 catch (Exception exception) {//异常处理
25 exception.printStackTrace();26 }27 }28
29 private void jbInit() throwsException {30 c = (JPanel) getContentPane();//设定一个空间
31 setTitle("扫雷");//标题为扫雷
32 c.setBackground(Color.WHITE);//背景颜色为白色
33 MenuPanel.setBackground(Color.GRAY);//菜单颜色为灰色
34 c.setLayout(borderLayout1);35 setSize(new Dimension(700, 700));//界面大小700*700
36 setResizable(false);37
38 BlockNum = 144;//设定方块数144个
39 BombNum = 10;//设定初始地雷数10个
40 text = new JTextField("10 ", 3);//设定一个字符框长度为3
41 nowBomb = new JLabel("当前雷数" + ":" +BombNum);42 setBomb = new JLabel("设置地雷数");//标明解释
43 start.addActionListener(new Frame1_start_actionAdapter(this));44
45 MenuPanel.add(setBomb);46 MenuPanel.add(text);47 MenuPanel.add(start);48 MenuPanel.add(nowBomb);//添加菜单元素
49 c.add(MenuPanel, java.awt.BorderLayout.SOUTH);//给界面下方的界面设定布局
50
51 bombPanel.setLayout(gridLayout1);52 gridLayout1.setColumns( (int) Math.sqrt(BlockNum));//纵列设定
53 gridLayout1.setRows( (int) Math.sqrt(BlockNum));//横排设定
54 bombButton = new Bomb[ (int) Math.sqrt(BlockNum)][ (int) Math.sqrt(BlockNum)];55 for (int i = 0; i < (int) Math.sqrt(BlockNum); i++) {56 for (int j = 0; j < (int) Math.sqrt(BlockNum); j++) {//嵌套for循环表示所有的格子
57 bombButton[i][j] = newBomb(i, j);58
59 bombButton[i][j].setFont(new Font("", Font.PLAIN, 14));//设计字体显示效果
60
61 bombButton[i][j].setForeground(Color.white);//背景颜色为白色
62 bombButton[i][j].addMouseListener(new Bomb_mouseAdapter(this));63 bombButton[i][j].addActionListener(new Bomb_actionAdapter(this));64 bombPanel.add(bombButton[i][j]);65 }66 }67 c.add(bombPanel, java.awt.BorderLayout.CENTER);//给界面中间的界面设定布局
68
69 startBomb();70 }71
72 /*开始按钮*/
73
74 public voidstart_actionPerformed(ActionEvent e) {75 int num=Integer.parseInt(text.getText().trim());//调用Integer.parseInt()把一个String转换成一个Double基本类型的值并赋值给了num
76 if (num >= 5 && num < 50) {77 BombNum = num;//如果当前雷数在5-50之间
78 startBomb();//可以开始布雷。
79 }80 else if (num < 5) {//如果当前雷数在5以下
81 JOptionPane.showMessageDialog(null, "您设置的地雷数太少了,请重设!", "错误",82 JOptionPane.ERROR_MESSAGE);//消息提示框显示错误。
83 num=10;84 BombNum = num;//自动将雷数改为10.
85 }86 else{87 JOptionPane.showMessageDialog(null, "您设置的地雷数太多了,请重设!", "错误",88 JOptionPane.ERROR_MESSAGE);//同上,消息提示框提醒输入有误。
89 num=10;90 BombNum =num;91 }92 }93 /*开始,布雷*/
94
95
96 public voidstartBomb() {97 nowBomb.setText("当前雷数" + ":" + BombNum);//利用setText设置现在的雷数。
98 for (int i = 0; i < (int) Math.sqrt(BlockNum); i++) {//由按钮组成的二维数组,i表示行,j表示列,构成了一个方形网格
99 for (int j = 0; j < (int) Math.sqrt(BlockNum); j++) {//循环条件判断isRight的值,如果为false循环否则退出
100 bombButton[i][j].isBomb = false;//当前按钮是否为雷
101 bombButton[i][j].isClicked = false;//是否已被点击
102 bombButton[i][j].isRight = false;//是否被(标注)正确
103 bombButton[i][j].BombFlag = 0;//是否被标注为雷
104 bombButton[i][j].BombRoundCount = 9;//周围
105 bombButton[i][j].setEnabled(true);106 bombButton[i][j].setText("");107 bombButton[i][j].setFont(new Font("", Font.PLAIN, 14));//设置字体大小
108 bombButton[i][j].setForeground(Color.BLUE);//设置颜色为蓝色
109 rightBomb = 0;//正确标出的雷数为0
110 restBomb =BombNum;111 restBlock = BlockNum -BombNum;112 }113 }114
115 for (int i = 0; i
119 if (bombButton[x][y].isBomb != true) {120 bombButton[x][y].isBomb = true;121 i++;122 }123 }124 CountRoundBomb();125 }126
127 /*计算方块周围雷数*/
128
129 public voidCountRoundBomb() {130 for (int i = 0; i < (int) Math.sqrt(BlockNum); i++) {//开方 障碍数
131 for (int j = 0; j < (int) Math.sqrt(BlockNum); j++) {132 int count = 0;//当需要检测的单元格本身无雷的情况下,统计周围的地雷个数
133
134 if (bombButton[i][j].isBomb != true) {//如果不是雷
135 for (int x = i - 1; x < i + 2; x++) {//从左边到右,一个三个
136 for (int y = j - 1; y < j + 2; y++) {137 if ( (x >= 0) && (y >= 0)138 && (x < ( (int) Math.sqrt(BlockNum)))139 && (y < ( (int) Math.sqrt(BlockNum)))) {//因前面x=i-1,所以排除超出边界的情况
140 if (bombButton[x][y].isBomb == true) {//如果是雷
141 count++;//加一
142 }143 }144 }145 }146 bombButton[i][j].BombRoundCount = count;//设置该Bomb环绕数的值
147 }148 }149 }150 }151
152 /*是否挖完了所有的雷*/
153
154 public voidisWin() {155 restBlock = BlockNum -BombNum;156 for (int i = 0; i < (int) Math.sqrt(BlockNum); i++) {157 for (int j = 0; j < (int) Math.sqrt(BlockNum); j++) {158 if (bombButton[i][j].isClicked == true) {159 restBlock--;160 }161 }162 }163
164 if (rightBomb == BombNum || restBlock == 0) {165 JOptionPane.showMessageDialog(this, "您挖完了所有的雷,您胜利了!", "胜利",166 JOptionPane.INFORMATION_MESSAGE);167 startBomb();168 }169 }170
171 /**当选中的位置为空,则翻开周围的地图**/
172
173 public voidisNull(Bomb ClickedButton) {174 inti, j;175 i = ClickedButton.num_x; //点击的方块,周围地图
176 j =ClickedButton.num_y;177
178 for (int x = i - 1; x < i + 2; x++) { //从左边到右边,一至三个
179 for (int y = j - 1; y < j + 2; y++) {180 if ( ( (x != i) || (y != j)) && (x >= 0) && (y >= 0)181 && (x < ( (int) Math.sqrt(BlockNum))) //因为设定x=i-1,所以排除超出边界的情况
182 && (y < ( (int) Math.sqrt(BlockNum)))) {183 if (bombButton[x][y].isBomb == false //如果方块中不是雷
184 && bombButton[x][y].isClicked == false //如果方块未被点击
185 && bombButton[x][y].isRight == false) { //如果方块未被标记
186 turn(bombButton[x][y]);187 } //当前位置为空,周围地图被翻开
188 }189 }190 }191 }192
193 /*翻开*/
194
195 public voidturn(Bomb ClickedButton) {196 ClickedButton.setEnabled(false);197 ClickedButton.isClicked = true; //点击方块为空,不是地雷
198 if (ClickedButton.BombRoundCount > 0) { //如果方块地雷环绕数>0
199 ClickedButton.setText(ClickedButton.BombRoundCount + ""); //标记数目
200 }201 else{202 isNull(ClickedButton); //否则,代替Null
203 }204 }205
206
207 /*左键点击*/
208 public voidactionPerformed(ActionEvent e) {209 if ( ( (Bomb) e.getSource()).isClicked == false //如果方块未被点击
210 && ( (Bomb) e.getSource()).isRight == false) { //如果方块标未被记
211 if ( ( (Bomb) e.getSource()).isBomb == false) { //如果方块不是地雷
212 turn( ( (Bomb) e.getSource()));213 isWin(); //当挖完雷,胜利
214 }215
216 else{217 for (int i = 0; i < (int) Math.sqrt(BlockNum); i++) {218 for (int j = 0; j < (int) Math.sqrt(BlockNum); j++) {219 if (bombButton[i][j].isBomb == true) { //如果踩到雷
220 bombButton[i][j].setText("b"); //地雷方块上显示“b”
221 }222 }223 }224 ( (Bomb) e.getSource()).setForeground(Color.RED); //显示红色
225 ( (Bomb) e.getSource()).setFont(new Font("", Font.BOLD, 20));226 ( (Bomb) e.getSource()).setText("X"); //显示符号“X”
227 JOptionPane.showMessageDialog(this, "你踩到地雷了,按确定重来", "踩到地雷", 2);228 startBomb();229 }230 }231 }232
233
234 /*右键点击*/
235 public voidmouseClicked(MouseEvent e) {236 Bomb bombSource =(Bomb) e.getSource();237 boolean right =SwingUtilities.isRightMouseButton(e);238
239 if ( (right == true) && (bombSource.isClicked == false)) {240 bombSource.BombFlag = (bombSource.BombFlag + 1) % 3; //计算右键标记数及对应得出符号
241 if (bombSource.BombFlag == 1) { //如果计算得1,标记显示F
242 if (restBomb > 0) {243 bombSource.setForeground(Color.RED); //标记显示红色
244 bombSource.setText("F"); //标记符号“F”
245 bombSource.isRight = true; //如果方块被标记
246 restBomb--; //那么当前地雷数减1
247 }248 else{249 bombSource.BombFlag = 0;250 }251 }252 else if (bombSource.BombFlag == 2) { //如果计算得2,标记显示Q
253 restBomb++; //在F减1的基础上地雷数加1
254 bombSource.setText("Q"); //标记符号“Q”
255 bombSource.isRight = false; //方块未被标记地雷
256 }257 else{258 bombSource.setText("");259 }260
261 if (bombSource.isBomb == true) { //如果方块是雷
262 if (bombSource.BombFlag == 1) { //如果所在方块计算得1,即标记F
263 rightBomb++;264 }265 else if (bombSource.BombFlag == 2) { //如果所在方块计算得2,即标记Q
266 rightBomb--;267 }268 }269 nowBomb.setText("当前雷数" + ":" +restBomb);270 isWin();271 }272 }273
274 public static voidmain(String[] args) {275 Frame frame = newFrame();276 frame.setVisible(true);277 }278 }279
280 classFrame1_start_actionAdapter281 implementsActionListener {282 privateFrame adaptee;283 Frame1_start_actionAdapter(Frame adaptee) {284 this.adaptee =adaptee;285 }286
287 public voidactionPerformed(ActionEvent e) {288 adaptee.start_actionPerformed(e);289 }290 }291
292 293 classBomb294 extendsJButton {295 int num_x, num_y; //第几号方块
296 int BombRoundCount; //周围雷数
297 boolean isBomb; //是否为雷
298 boolean isClicked; //是否被点击
299 int BombFlag; //测试雷标记
300 boolean isRight; //是否点击右键
301
302 public Bomb(int x, inty) {303 num_x =x;304 num_y = y;//累的位置,获得是参数值,嵌套了两个for循环
305 BombFlag = 0;//是否已经插旗了
306 BombRoundCount = 9;//环绕数
307 isBomb = false;//是雷
308 isClicked = false;//被点击
309 isRight = false;//是真的
310 }311 }312
313 classBomb_actionAdapter314 implementsActionListener {315 privateFrame adaptee;316 Bomb_actionAdapter(Frame adaptee) {317 this.adaptee =adaptee;318 }319
320 public voidactionPerformed(ActionEvent e) {321 adaptee.actionPerformed(e);322 }323 }324
325 classBomb_mouseAdapter326 extendsMouseAdapter {327 privateFrame adaptee;328 Bomb_mouseAdapter(Frame adaptee) {329 this.adaptee =adaptee;330 }331
332 public voidmouseClicked(MouseEvent e) {333 adaptee.mouseClicked(e);334 }335 }