
一个简单的扫雷小游戏,在12*12的方格盘上,首先可以设定雷的个数,然后点击开始程序就会随机布雷,开始游戏后如果点到雷就会显示游戏结束,如果没有,会出现数字表示周围一圈雷的个数,以此推理当扫出所有雷将显示游戏胜利。
游戏项目规划:
1 import java.awt.*;
2 import java.awt.event.*;
3 import javax.swing.*;
4 public class Frame
5 extends JFrame {
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 public Frame() {
20 try {
21 setDefaultCloseOperation(EXIT_ON_CLOSE);//关闭操作并结束进程
22 jbInit();//一般用于对程序进行初始化
23 }
24 catch (Exception exception) {//异常处理
25 exception.printStackTrace();
26 }
27 }
28
29 private void jbInit() throws Exception {
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] = new Bomb(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 void start_actionPerformed(ActionEvent e) {
75 int num=Integer.Text().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 void startBomb() {
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 < BombNum; ) {
116 int x = (int) (Math.random() * (int) (Math.sqrt(BlockNum) - 1));
117 int y = (int) (Math.random() * (int) (Math.sqrt(BlockNum) - 1));
118
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 void CountRoundBomb() {
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 void isWin() {
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 void isNull(Bomb ClickedButton) {
174 int i, 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 void turn(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 void actionPerformed(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 void mouseClicked(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 void main(String[] args) {
275 Frame frame = new Frame();
276 frame.setVisible(true);
277 }
278 }
279
280 class Frame1_start_actionAdapter
281 implements ActionListener {
282 private Frame adaptee;
283 Frame1_start_actionAdapter(Frame adaptee) {
284 this.adaptee = adaptee;
285 }
286
287 public void actionPerformed(ActionEvent e) {
288 adaptee.start_actionPerformed(e);
289 }
290 }
291
292
293 class Bomb
294 extends JButton {
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, int y) {
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 class Bomb_actionAdapter
314 implements ActionListener {
315 private Frame adaptee;
316 Bomb_actionAdapter(Frame adaptee) {
317 this.adaptee = adaptee;
318 }
319
320 public void actionPerformed(ActionEvent e) {
321 adaptee.actionPerformed(e);
322 }
323 }
324
325 class Bomb_mouseAdapter
326 extends MouseAdapter {
327 private Frame adaptee;
328 Bomb_mouseAdapter(Frame adaptee) {
329 this.adaptee = adaptee;
330 }
331
332 public void mouseClicked(MouseEvent e) {
333 useClicked(e);
334 }
335 }
初始界面:
设置雷数为10,开始游戏,会显示数字:
踩到雷,游戏结束:
两种标记:
扫完雷,游戏胜利:
张子扬 30分
方浩南 27分
唐振远 23分
曾子誉 20分
团队贡献
张子扬:小组组长,负责给组员分配任务,掌握代码进度。对代码的架构进行划分,并协助方浩南完成部分代码。并完成图形界面和雷数的布控。
方浩南:负责编写部分前期代码,完成对周围雷数的计算、剩余雷数的计算和翻开的操作。
唐振远:负责编写后期代码,完成左右键的点击操作,并完成代码的检查,更正。
曾子誉:查阅相关资料,协助唐振远同学完成相关代码。并对代码进行后期完善,改善用户体验。
通过团队项目,我们认识到了合作的重要性,紧密的合作能够提高我们的能力。代码测试过程中出现很多错误,但经过互相的合作和探讨,加以改进,便可以成功运行。 小组各组员的课程总结已发到个人博客。
转载于:.html
本文发布于:2024-01-31 10:34:22,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170666846527895.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
| 留言与评论(共有 0 条评论) |