这是java课最后做的课程设计,由于java是初学的,所以做的时候有参考一些技术大牛的博客,在此表示感谢。
发在这里跟大家交流学习一下。
如需要完整工程文件、说明文档以及可运行jar文件,下载地址:点击打开链接
russianblocksgame.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
|
package russiablocksgame; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.border; import javax.swing.border.etchedborder; /** * 游戏主类,继承自jframe类,负责游戏的全局控制。 内含: 1.一个gamecanvas画布类的实例对象, * 2.一个保存当前活动块(russiablock)实例的对象; 3.一个保存当前控制面板(controlpanel)实例的对象; */ public class russiablocksgame extends jframe { private static final long serialversionuid = -7332245439279674749l; /** * 每填满一行计多少分 */ public final static int per_line_score = 100 ; /** * 积多少分以后能升级 */ public final static int per_level_score = per_line_score * 20 ; /** * 最大级数是10级 */ public final static int max_level = 10 ; /** * 默认级数是2 */ public final static int default_level = 2 ; private gamecanvas canvas; private ersblock block; private boolean playing = false ; private controlpanel ctrlpanel; //初始化菜单栏 private jmenubar bar = new jmenubar(); private jmenu mgame = new jmenu( " 游戏" ), mcontrol = new jmenu( " 控制" ), minfo = new jmenu( "帮助" ); private jmenuitem minewgame = new jmenuitem( "新游戏" ), misetblockcolor = new jmenuitem( "设置方块颜色..." ), misetbackcolor = new jmenuitem( "设置背景颜色..." ), miturnharder = new jmenuitem( "升高游戏难度" ), miturneasier = new jmenuitem( "降低游戏难度" ), miexit = new jmenuitem( "退出" ), miplay = new jmenuitem( "开始" ), mipause = new jmenuitem( "暂停" ), miresume = new jmenuitem( "恢复" ), mistop = new jmenuitem( "终止游戏" ), mirule = new jmenuitem( "游戏规则" ), miauthor = new jmenuitem( "关于本游戏" ); /** * 建立并设置窗口菜单 */ private void creatmenu() { bar.add(mgame); bar.add(mcontrol); bar.add(minfo); mgame.add(minewgame); mgame.addseparator(); //在菜单中加水平分割线 mgame.add(misetblockcolor); mgame.add(misetbackcolor); mgame.addseparator(); //在菜单中加水平分割线 mgame.add(miturnharder); mgame.add(miturneasier); mgame.addseparator(); //在菜单中加水平分割线 mgame.add(miexit); mcontrol.add(miplay); miplay.setenabled( true ); mcontrol.add(mipause); mipause.setenabled( false ); mcontrol.add(miresume); miresume.setenabled( false ); mcontrol.add(mistop); mistop.setenabled( false ); minfo.add(mirule); minfo.add(miauthor); setjmenubar(bar); minewgame.addactionlistener( new actionlistener() { @override public void actionperformed(actionevent e) { stopgame(); reset(); setlevel(default_level); } }); //设置方块颜色 misetblockcolor.addactionlistener( new actionlistener() { @override public void actionperformed(actionevent e) { color newfrontcolor = jcolorchooser.showdialog(russiablocksgame. this , "设置方块颜色" , canvas.getblockcolor()); if (newfrontcolor != null ) { canvas.setblockcolor(newfrontcolor); } } }); //设置背景颜色 misetbackcolor.addactionlistener( new actionlistener() { @override public void actionperformed(actionevent e) { color newbackcolor = jcolorchooser.showdialog(russiablocksgame. this , "设置背景颜色" , canvas.getbackgroundcolor()); if (newbackcolor != null ) { canvas.setbackgroundcolor(newbackcolor); } } }); //定义菜单栏"关于"的功能,弹出确认框。 miauthor.addactionlistener( new actionlistener() { @override public void actionperformed(actionevent e) { joptionpane.showmessagedialog( null , "软件工程(4)班\n3115005372\n杨宇杰\n©一切解释权归杨宇杰所有" , "关于俄罗斯方块 - 2016" , 1 ); } }); //游戏规则说明 mirule.addactionlistener( new actionlistener() { @override public void actionperformed(actionevent e) { joptionpane.showmessagedialog( null , "由小方块组成的不同形状的板块陆续从屏幕上方落下来,\n玩家通过调整板块的位置和方向,使它们在屏幕底部拼\n出完整的一条或几条。这些完整的横条会随即消失,给新\n落下来的板块腾出空间,与此同时,玩家得到分数奖励。\n没有被消除掉的方块不断堆积起来,一旦堆到屏幕顶端,\n玩家便告输,游戏结束。" , "游戏规则" , 1 ); } }); //增加难度 miturnharder.addactionlistener( new actionlistener() { @override public void actionperformed(actionevent e) { int curlevel = getlevel(); if (!playing && curlevel < max_level) { setlevel(curlevel + 1 ); } } }); //减少难度 miturneasier.addactionlistener( new actionlistener() { @override public void actionperformed(actionevent e) { int curlevel = getlevel(); if (!playing && curlevel > 1 ) { setlevel(curlevel - 1 ); } } }); //退出按钮动作响应 miexit.addactionlistener( new actionlistener() { @override public void actionperformed(actionevent e) { system.exit( 0 ); } }); } /** * 主游戏类的构造方法 * * @param title string ,窗口标题 */ public russiablocksgame(string title) { super (title); //设置标题 setsize( 500 , 600 ); //设置窗口大小 setlocationrelativeto( null ); //设置窗口居中 creatmenu(); container container = getcontentpane(); //创建菜单栏 container.setlayout( new borderlayout( 6 , 0 )); //设置窗口的布局管理器 canvas = new gamecanvas( 20 , 15 ); //新建游戏画布 ctrlpanel = new controlpanel( this ); //新建控制面板 container.add(canvas, borderlayout.center); //左边加上画布 container.add(ctrlpanel, borderlayout.east); //右边加上控制面板 //注册窗口事件。当点击关闭按钮时,结束游戏,系统退出。 addwindowlistener( new windowadapter() { @override public void windowclosing(windowevent we) { stopgame(); system.exit( 0 ); } }); //根据窗口大小,自动调节方格的尺寸 addcomponentlistener( new componentadapter() { @override public void componentresized(componentevent ce) { canvas.adjust(); } }); setvisible( true ); canvas.adjust(); } /** * 让游戏复位 */ public void reset() { //画布复位,控制面板复位 ctrlpanel.setplaybuttonenable( true ); ctrlpanel.setpausebuttonenable( false ); ctrlpanel.setpausebuttonlabel( true ); ctrlpanel.setstopbuttonenable( false ); ctrlpanel.setturnleveldownbuttonenable( true ); ctrlpanel.setturnlevelupbuttonenable( true ); miplay.setenabled( true ); mipause.setenabled( false ); miresume.setenabled( false ); mistop.setenabled( false ); ctrlpanel.reset(); canvas.reset(); } /** * 判断游戏是否还在进行 * * @return boolean,true -还在运行,false-已经停止 */ public boolean isplaying() { return playing; } /** * 得到当前活动的块 * * @return ersblock,当前活动块的引用 */ public ersblock getcurblock() { return block; } /** * 得到当前画布 * * @return gamecanvas,当前画布的引用 */ public gamecanvas getcanvas() { return canvas; } /** * 开始游戏 */ public void playgame() { play(); ctrlpanel.setplaybuttonenable( false ); ctrlpanel.setpausebuttonenable( true ); ctrlpanel.setpausebuttonlabel( true ); ctrlpanel.setstopbuttonenable( true ); ctrlpanel.setturnleveldownbuttonenable( false ); ctrlpanel.setturnlevelupbuttonenable( false ); mistop.setenabled( true ); miturnharder.setenabled( false ); miturneasier.setenabled( false ); ctrlpanel.requestfocus(); //设置焦点在控制面板上 } /** * 游戏暂停 */ public void pausegame() { if (block != null ) { block.pausemove(); } ctrlpanel.setplaybuttonenable( false ); ctrlpanel.setpausebuttonlabel( false ); ctrlpanel.setstopbuttonenable( true ); miplay.setenabled( false ); mipause.setenabled( false ); miresume.setenabled( true ); mistop.setenabled( true ); } /** * 让暂停中的游戏继续 */ public void resumegame() { if (block != null ) { block.resumemove(); } ctrlpanel.setplaybuttonenable( false ); ctrlpanel.setpausebuttonenable( true ); ctrlpanel.setpausebuttonlabel( true ); mipause.setenabled( true ); miresume.setenabled( false ); ctrlpanel.requestfocus(); } /** * 用户停止游戏 */ public void stopgame() { playing = false ; if (block != null ) { block.stopmove(); } ctrlpanel.setplaybuttonenable( true ); ctrlpanel.setpausebuttonenable( false ); ctrlpanel.setpausebuttonlabel( true ); ctrlpanel.setstopbuttonenable( false ); ctrlpanel.setturnleveldownbuttonenable( true ); ctrlpanel.setturnlevelupbuttonenable( true ); miplay.setenabled( true ); mipause.setenabled( false ); miresume.setenabled( false ); mistop.setenabled( false ); miturnharder.setenabled( true ); miturneasier.setenabled( true ); reset(); //重置画布和控制面板 } /** * 得到游戏者设置的难度 * * @return int ,游戏难度1-max_level */ public int getlevel() { return ctrlpanel.getlevel(); } /** * 用户设置游戏难度 * * @param level int ,游戏难度1-max_level */ public void setlevel( int level) { if (level < 11 && level > 0 ) { ctrlpanel.setlevel(level); } } /** * 得到游戏积分 * * @return int,积分 */ public int getscore() { if (canvas != null ) { return canvas.getscore(); } return 0 ; } /** * 得到自上次升级以来的游戏积分,升级以后,此积分清零 * * @return int,积分 */ public int getscoreforlevelupdate() { if (canvas != null ) { return canvas.getscoreforlevelupdate(); } return 0 ; } /** * 当积分累积到一定数值时,升一次级 * * @return boolean,true-update succeed,false-update fail */ public boolean levelupdate() { int curlevel = getlevel(); if (curlevel < max_level) { setlevel(curlevel + 1 ); canvas.resetscoreforlevelupdate(); return true ; } return false ; } /** * 游戏开始 */ private void play() { reset(); playing = true ; thread thread = new thread( new game()); //启动游戏线程 thread.start(); } /** * 报告游戏结束了 */ private void reportgameover() { new gameoverdialog( this , "俄罗斯方块" , "游戏结束,您的得分为" + canvas.getscore()); } /** * 一轮游戏过程,实现了runnable接口 一轮游戏是一个大循环,在这个循环中,每隔100毫秒, 检查游戏中的当前块是否已经到底了,如果没有, * 就继续等待。如果到底了,就看有没有全填满的行, 如果有就删除它,并为游戏者加分,同时随机产生一个新的当前块并让它自动落下。 * 当新产生一个块时,先检查画布最顶上的一行是否已经被占了,如果是,可以判断game over 了。 */ private class game implements runnable { @override public void run() { int col = ( int ) (math.random() * (canvas.getcols() - 3 )); //随机生成方块出现的位置 int style = ersblock.styles[ ( int ) (math.random() * 7 )][( int ) (math.random() * 4 )]; //随机生成一种形状的方块 while (playing) { if (block != null ) { //第一次循环时,block为空 if (block.isalive()) { try { thread.currentthread(); thread.sleep( 500 ); } catch (interruptedexception ie) { ie.printstacktrace(); } continue ; } } checkfullline(); //检查是否有全填满的行 if (isgameover()) { reportgameover(); miplay.setenabled( true ); mipause.setenabled( false ); miresume.setenabled( false ); mistop.setenabled( false ); ctrlpanel.setplaybuttonenable( true ); ctrlpanel.setpausebuttonlabel( false ); ctrlpanel.setstopbuttonenable( false ); return ; } block = new ersblock(style, - 1 , col, getlevel(), canvas); block.start(); col = ( int ) (math.random() * (canvas.getcols() - 3 )); style = ersblock.styles[ ( int ) (math.random() * 7 )][( int ) (math.random() * 4 )]; ctrlpanel.settipstyle(style); } } //检查画布中是否有全填满的行,如果有就删之 public void checkfullline() { for ( int i = 0 ; i < canvas.getrows(); i++) { int row = - 1 ; boolean fulllinecolorbox = true ; for ( int j = 0 ; j < canvas.getcols(); j++) { if (!canvas.getbox(i, j).iscolorbox()) { fulllinecolorbox = false ; break ; } } if (fulllinecolorbox) { row = i--; canvas.removeline(row); } } } //根据最顶行是否被占,判断游戏是否已经结束了 //@return boolean ,true-游戏结束了,false-游戏未结束 private boolean isgameover() { for ( int i = 0 ; i < canvas.getcols(); i++) { ersbox box = canvas.getbox( 0 , i); if (box.iscolorbox()) { return true ; } } return false ; } } /** * 定义gameover对话框。 */ @suppresswarnings ( "serial" ) private class gameoverdialog extends jdialog implements actionlistener { private jbutton againbutton, exitbutton; private border border = new etchedborder(etchedborder.raised, color.white, new color( 148 , 145 , 140 )); public gameoverdialog(jframe parent, string title, string message) { super (parent, title, true ); if (parent != null ) { setsize( 240 , 120 ); this .setlocationrelativeto(parent); jpanel messagepanel = new jpanel(); messagepanel.add( new jlabel(message)); messagepanel.setborder(border); container container = this .getcontentpane(); container.setlayout( new gridlayout( 2 , 0 , 0 , 10 )); container.add(messagepanel); jpanel choosepanel = new jpanel(); choosepanel.setlayout( new gridlayout( 0 , 2 , 4 , 0 )); container.add(choosepanel); againbutton = new jbutton( "再玩一局" ); exitbutton = new jbutton( "退出游戏" ); choosepanel.add( new jpanel().add(againbutton)); choosepanel.add( new jpanel().add(exitbutton)); choosepanel.setborder(border); } againbutton.addactionlistener( this ); exitbutton.addactionlistener( this ); this .setvisible( true ); } @override public void actionperformed(actionevent e) { if (e.getsource() == againbutton) { this .setvisible( false ); reset(); } else if (e.getsource() == exitbutton) { stopgame(); system.exit( 0 ); } } } } |
gamecanvas.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
|
package russiablocksgame; import java.awt.color; import java.awt.graphics; import javax.swing.jpanel; import javax.swing.border.etchedborder; /** * 画布类,内有<行数>*<列数> 个方格类实例。 继承自jpanel类。 ersblock线程类动态改变画布类的方格颜色,画布类通过 * 检查方格颜色来体现ersblock块的移动情况。 */ public class gamecanvas extends jpanel { private static final long serialversionuid = 6732901391026089276l; private color backcolor = color.darkgray, frontcolor = color.white; private int rows, cols, score = 0 , scoreforlevelupdate = 0 ; private ersbox[][] boxes; private int boxwidth, boxheight; /** * 画布类的构造函数 * * @param rows int,画布的行数 * @param cols int,画布的列数 行数和列数决定着画布拥有方格的数目 */ public gamecanvas( int rows, int cols) { this .rows = rows; this .cols = cols; boxes = new ersbox[rows][cols]; for ( int i = 0 ; i < boxes.length; i++) { for ( int j = 0 ; j < boxes[i].length; j++) { boxes[i][j] = new ersbox( false ); } } setborder( new etchedborder(etchedborder.raised, color.white, new color( 148 , 145 , 140 ))); } /** * 画布类的构造函数 * * @param rows * @param cols * @param backcolor * @param frontcolor */ public gamecanvas( int rows, int cols, color backcolor, color frontcolor) { this (rows, cols); this .backcolor = backcolor; this .frontcolor = frontcolor; } /** * 设置游戏背景色彩 * * @param backcolor color,背景色彩 */ public void setbackgroundcolor(color backcolor) { this .backcolor = backcolor; } /** * 取得游戏背景色彩 * * @return color ,背景色彩 */ public color getbackgroundcolor() { return backcolor; } /** * 设置游戏方块颜色 * * @param frontcolor color,方块颜色 */ public void setblockcolor(color frontcolor) { this .frontcolor = frontcolor; } /** * 取得游戏方块色彩 * * @return color,方块颜色 */ public color getblockcolor() { return frontcolor; } /** * 取得画布中方格的行数 * * @return */ public int getrows() { return rows; } /** * 取得画布中方格的列数 * * @return int,方格的列数 */ public int getcols() { return cols; } /** * 取得游戏成绩 * * @return int, 分数 */ public int getscore() { return score; } /** * 取得自上一次升级后的积分 * * @return int ,上一次升级后的积分 */ public int getscoreforlevelupdate() { return scoreforlevelupdate; } /** * 升级后,将上一次升级以来的积分清零 */ public void resetscoreforlevelupdate() { scoreforlevelupdate -= russiablocksgame.per_level_score; } /** * 得到某一行某一列的方格引用 * * @return row int ,要引用的方格所在的行 * @param col int, 要引用的方格所在的行 * @return ersbox,在row行col列的方格的引用 */ public ersbox getbox( int row, int col) { if (row < 0 || row > boxes.length - 1 || col < 0 || col > boxes[ 0 ].length - 1 ) { return null ; } return (boxes[row][col]); } /** * 覆盖jcomponent类的函数,画组件。 * * @param g 图形设备环境 */ @override public void paintcomponent(graphics g) { super .paintcomponent(g); g.setcolor(frontcolor); for ( int i = 0 ; i < boxes.length; i++) { for ( int j = 0 ; j < boxes[i].length; j++) { g.setcolor(boxes[i][j].iscolorbox() ? frontcolor : backcolor); g.fill3drect(j * boxwidth, i * boxheight, boxwidth, boxheight, true ); } } } /** * 根据窗口大小,自动调节方格的尺寸 */ public void adjust() { boxwidth = getsize().width / cols; boxheight = getsize().height / rows; } /** * 当一行被游戏者叠满后,将此行清除,并为游戏者加分 * * @param row int,要清除的行,是由ersboxesgame类计算的 */ public synchronized void removeline( int row) { for ( int i = row; i > 0 ; i--) { for ( int j = 0 ; j < cols; j++) { boxes[i][j] = (ersbox) boxes[i - 1 ][j].clone(); //将上一行的方块颜色克隆下来, } //即消去一行方块 } score += russiablocksgame.per_level_score; scoreforlevelupdate += russiablocksgame.per_level_score; repaint(); } /** * 重置画布,置积分为零 */ public void reset() { score = 0 ; scoreforlevelupdate = 0 ; for ( int i = 0 ; i < boxes.length; i++) { for ( int j = 0 ; j < boxes[i].length; j++) { boxes[i][j].setcolor( false ); } } repaint(); } } |
controlpanel.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
|
package russiablocksgame; import java.awt.borderlayout; import java.awt.color; import java.awt.graphics; import java.awt.gridlayout; import java.awt.event.actionevent; import java.awt.event.actionlistener; import java.awt.event.componentadapter; import java.awt.event.componentevent; import java.awt.event.keyadapter; import java.awt.event.keyevent; import java.text.dateformat; import java.text.simpledateformat; import java.util.date; import javax.swing.jbutton; import javax.swing.jlabel; import javax.swing.jpanel; import javax.swing.jtextfield; import javax.swing.timer; import javax.swing.border.border; import javax.swing.border.etchedborder; /** * 控制面板类,继承自jpanel。 上边安放预显窗口,等级,得分,控制按钮 主要用来控制游戏进程。 */ class controlpanel extends jpanel { private static final long serialversionuid = 3900659640646175724l; private jtextfield tflevel = new jtextfield( "" + russiablocksgame.default_level), tfscore = new jtextfield( " 0" ), tftime = new jtextfield( " " ); private jbutton btplay = new jbutton( " 开始" ), btpause = new jbutton( " 暂停" ), btstop = new jbutton( "终止游戏" ), btturnlevelup = new jbutton( " 增加难度" ), btturnleveldown = new jbutton( " 降低难度" ); private jpanel pltip = new jpanel( new borderlayout()); private tippanel pltipblock = new tippanel(); private jpanel plinfo = new jpanel( new gridlayout( 4 , 1 )); private jpanel plbutton = new jpanel( new gridlayout( 6 , 1 )); private timer timer; private border border = new etchedborder(etchedborder.raised, color.white, new color( 148 , 145 , 140 )); /** * 控制面板类的构造函数 * * @param game ersblocksgame,ersblocksgame 类的一个实例引用 方便直接控制ersblocksgame类的行为。 */ public controlpanel( final russiablocksgame game) { setlayout( new gridlayout( 3 , 1 , 0 , 2 )); pltip.add( new jlabel( " 下一个方块" ), borderlayout.north); //添加组件 pltip.add(pltipblock); pltip.setborder(border); plinfo.add( new jlabel( " 难度系数" )); plinfo.add(tflevel); plinfo.add( new jlabel( " 得分" )); plinfo.add(tfscore); plinfo.setborder(border); plbutton.add(btplay); btplay.setenabled( true ); plbutton.add(btpause); btpause.setenabled( false ); plbutton.add(btstop); btstop.setenabled( false ); plbutton.add(btturnlevelup); plbutton.add(btturnleveldown); plbutton.add(tftime); plbutton.setborder(border); tflevel.seteditable( false ); tfscore.seteditable( false ); tftime.seteditable( false ); add(pltip); add(plinfo); add(plbutton); addkeylistener( new keyadapter() { @override public void keypressed(keyevent ke) { if (!game.isplaying()) { return ; } ersblock block = game.getcurblock(); switch (ke.getkeycode()) { case keyevent.vk_down: block.movedown(); break ; case keyevent.vk_left: block.moveleft(); break ; case keyevent.vk_right: block.moveright(); break ; case keyevent.vk_up: block.turnnext(); break ; default : break ; } } }); btplay.addactionlistener( new actionlistener() { //开始游戏 @override public void actionperformed(actionevent ae) { game.playgame(); } }); btpause.addactionlistener( new actionlistener() { //暂停游戏 @override public void actionperformed(actionevent ae) { if (btpause.gettext().equals( " 暂停" )) { game.pausegame(); } else { game.resumegame(); } } }); btstop.addactionlistener( new actionlistener() { //停止游戏 @override public void actionperformed(actionevent ae) { game.stopgame(); } }); btturnlevelup.addactionlistener( new actionlistener() { //升高难度 @override public void actionperformed(actionevent ae) { try { int level = integer.parseint(tflevel.gettext()); if (level < russiablocksgame.max_level) { tflevel.settext( "" + (level + 1 )); } } catch (numberformatexception e) { } requestfocus(); } }); btturnleveldown.addactionlistener( new actionlistener() { //降低游戏难度 @override public void actionperformed(actionevent ae) { try { int level = integer.parseint(tflevel.gettext()); if (level > 1 ) { tflevel.settext( "" + (level - 1 )); } } catch (numberformatexception e) { } requestfocus(); } }); addcomponentlistener( new componentadapter() { @override public void componentresized(componentevent ce) { pltipblock.adjust(); } }); timer = new timer( 1000 , new actionlistener() { @override public void actionperformed(actionevent ae) { dateformat format = new simpledateformat( "时间:hh:mm:ss" ); //系统获得时间 date date = new date(); tftime.settext(format.format(date)); tfscore.settext( "" + game.getscore()); int scoreforlevelupdate = //判断当前分数是否能升级 game.getscoreforlevelupdate(); if (scoreforlevelupdate >= russiablocksgame.per_level_score && scoreforlevelupdate > 0 ) { game.levelupdate(); } } }); timer.start(); } /** * 设置预显窗口的样式 * * @param style int,对应ersblock类的styles中的28个值 */ public void settipstyle( int style) { pltipblock.setstyle(style); } /** * 取得用户设置的游戏等级。 * * @return int ,难度等级,1-ersblocksgame.max_level */ public int getlevel() { int level = 0 ; try { level = integer.parseint(tflevel.gettext()); } catch (numberformatexception e) { } return level; } /** * 让用户修改游戏难度等级。 * * @param level 修改后的游戏难度等级 */ public void setlevel( int level) { if (level > 0 && level < 11 ) { tflevel.settext( "" + level); } } /** * 设置“开始”按钮的状态。 */ public void setplaybuttonenable( boolean enable) { btplay.setenabled(enable); } public void setpausebuttonenable( boolean enable) { btpause.setenabled(enable); } public void setpausebuttonlabel( boolean pause) { btpause.settext(pause ? " 暂停" : " 继续" ); } public void setstopbuttonenable( boolean enable) { btstop.setenabled(enable); } public void setturnlevelupbuttonenable( boolean enable) { btturnlevelup.setenabled(enable); } public void setturnleveldownbuttonenable( boolean enable) { btturnleveldown.setenabled(enable); } /** * 重置控制面板 */ public void reset() { tfscore.settext( " 0" ); pltipblock.setstyle( 0 ); } /** * 重新计算tippanel里的boxes[][]里的小框的大小 */ public void adjust() { pltipblock.adjust(); } /** * 预显窗口的实现细节类 */ public class tippanel extends jpanel { //tippanel用来显示下一个将要出现方块的形状 private static final long serialversionuid = 5160553671436997616l; private color backcolor = color.darkgray, frontcolor = color.white; private ersbox[][] boxes = new ersbox[ersblock.boxes_rows][ersblock.boxes_cols]; private int style, boxwidth, boxheight; private boolean istiled = false ; /** * 预显示窗口类构造函数 */ public tippanel() { for ( int i = 0 ; i < boxes.length; i++) { for ( int j = 0 ; j < boxes[i].length; j++) { boxes[i][j] = new ersbox( false ); } } } /** * 设置预显示窗口的方块样式 * * @param style int,对应ersblock类的styles中的28个值 */ public void setstyle( int style) { this .style = style; repaint(); } /** * 覆盖jcomponent类的函数,画组件。 * * @param g 图形设备环境 */ @override public void paintcomponent(graphics g) { super .paintcomponent(g); if (!istiled) { adjust(); } int key = 0x8000 ; for ( int i = 0 ; i < boxes.length; i++) { for ( int j = 0 ; j < boxes[i].length; j++) { color color = ((key & style) != 0 ? frontcolor : backcolor); g.setcolor(color); g.fill3drect(j * boxwidth, i * boxheight, boxwidth, boxheight, true ); key >>= 1 ; } } } /** * g根据窗口的大小,自动调整方格的尺寸 */ public void adjust() { boxwidth = getsize().width / ersblock.boxes_cols; boxheight = getsize().height / ersblock.boxes_rows; istiled = true ; } } } |
ersbox.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
package russiablocksgame; import java.awt.dimension; /** * 方格类,是组成块的基本元素,用自己的颜色来表示块的外观 */ public class ersbox implements cloneable { private boolean iscolor; private dimension size = new dimension(); /** * 方格类的构造函数, * * @param iscolor 是不是用前景色来为此方格着色 true前景色,false 用背景色 */ public ersbox( boolean iscolor) { this .iscolor = iscolor; } /** * 此方格是不是用前景色表现 * * @return boolean ,true用前景色表现,false 用背景色表现 */ public boolean iscolorbox() { return iscolor; } /** * 设置方格的颜色, * * @param iscolor boolean ,true用前景色表现,false 用背景色表现 */ public void setcolor( boolean iscolor) { this .iscolor = iscolor; } /** * 得到此方格的尺寸 * * @return dimension ,方格的尺寸 */ public dimension getsize() { return size; } /** * 设置方格的尺寸, * * @param size dimension ,方格的尺寸 */ public void setsize(dimension size) { this .size = size; } /** * 覆盖object的object clone(),实现克隆 * * @return object,克隆的结果 */ @override public object clone() { object cloned = null ; try { cloned = super .clone(); } catch (exception ex) { ex.printstacktrace(); } return cloned; } } |
ersblock.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
|
package russiablocksgame; /** * 块类,继承自线程类(thread) 由4 × 4个方块(ersbox)构成一个方块, 控制块的移动·下落·变形等 */ class ersblock extends thread { /** * 一个块占的行数是4行 */ public final static int boxes_rows = 4 ; /** * 一个块占的列数是4列 */ public final static int boxes_cols = 4 ; /** * 让升级变化平滑的因子,避免最后几级之间的速度相差近一倍 */ public final static int level_flatness_gene = 3 ; /** * 相近的两级之间,块每下落一行的时间差别为多少(毫秒) */ public final static int between_levels_degress_time = 50 ; /** * 方块的样式数目为7 */ public final static int block_kind_number = 7 ; /** * 每一个样式的方块的反转状态种类为4 */ public final static int block_status_number = 4 ; /** * 分别对应7种模型的28种状态 */ public final static int [][] styles = { //共28种状态 { 0x0f00 , 0x4444 , 0x0f00 , 0x4444 }, //长条型的四种状态 { 0x04e0 , 0x0464 , 0x00e4 , 0x04c4 }, //t型的四种状态 { 0x4620 , 0x6c00 , 0x4620 , 0x6c00 }, //反z型的四种状态 { 0x2640 , 0xc600 , 0x2640 , 0xc600 }, //z型的四种状态 { 0x6220 , 0x1700 , 0x2230 , 0x0740 }, //7型的四种状态 { 0x6440 , 0x0e20 , 0x44c0 , 0x8e00 }, //反7型的四种状态 { 0x0660 , 0x0660 , 0x0660 , 0x0660 }, //方块的四种状态 }; private gamecanvas canvas; private ersbox[][] boxes = new ersbox[boxes_rows][boxes_cols]; private int style, y, x, level; private boolean pausing = false , moving = true ; /** * 构造函数,产生一个特定的块 * * @param style 块的样式,对应styles的28个值中的一个 * @param y 起始位置,左上角在canvas中的坐标行 * @param x 起始位置,左上角在canvas中的坐标列 * @param level 游戏等级,控制块的下落速度 * @param canvas 画板 */ public ersblock( int style, int y, int x, int level, gamecanvas canvas) { this .style = style; this .y = y; this .x = x; this .level = level; this .canvas = canvas; int key = 0x8000 ; for ( int i = 0 ; i < boxes.length; i++) { for ( int j = 0 ; j < boxes[i].length; j++) { boolean iscolor = ((style & key) != 0 ); boxes[i][j] = new ersbox(iscolor); key >>= 1 ; } } display(); } /** * 线程类的run()函数覆盖,下落块,直到块不能再下落 */ @override public void run() { while (moving) { try { sleep(between_levels_degress_time * (russiablocksgame.max_level - level + level_flatness_gene)); } catch (interruptedexception ie) { ie.printstacktrace(); } //后边的moving是表示在等待的100毫秒间,moving没有被改变 if (!pausing) { moving = (moveto(y + 1 , x) && moving); } } } /** * 块向左移动一格 */ public void moveleft() { moveto(y, x - 1 ); } /** * 块向右移动一格 */ public void moveright() { moveto(y, x + 1 ); } /** * 块向下移动一格 */ public void movedown() { moveto(y + 1 , x); } /** * 块变型 */ public void turnnext() { for ( int i = 0 ; i < block_kind_number; i++) { for ( int j = 0 ; j < block_status_number; j++) { if (styles[i][j] == style) { int newstyle = styles[i][(j + 1 ) % block_status_number]; turnto(newstyle); return ; } } } } public void startmove() { pausing = false ; moving = true ; } /** * 暂停块的下落,对应游戏暂停 */ public void pausemove() { pausing = true ; // moving = false; } /** * 继续块的下落,对应游戏继续 */ public void resumemove() { pausing = false ; moving = true ; } /** * 停止块的下落,对应游戏停止 */ public void stopmove() { pausing = false ; moving = false ; } /** * 将当前块从画布的对应位置移除,要等到下次重画画布时才能反映出来 */ private void erase() { for ( int i = 0 ; i < boxes.length; i++) { for ( int j = 0 ; j < boxes[i].length; j++) { if (boxes[i][j].iscolorbox()) { ersbox box = canvas.getbox(i + y, j + x); if (box == null ) { continue ; } box.setcolor( false ); } } } } /** * 让当前块放置在画布的对因位置上,要等到下次重画画布时才能看见 */ private void display() { for ( int i = 0 ; i < boxes.length; i++) { for ( int j = 0 ; j < boxes[i].length; j++) { if (boxes[i][j].iscolorbox()) { ersbox box = canvas.getbox(i + y, j + x); if (box == null ) { continue ; } box.setcolor( true ); } } } } /** * 当前块能否移动到newrow/newcol 所指定的位置 * * @param newrow int,目的地所在行 * @param newcol int,目的地所在列 * @return boolean,true-能移动,false-不能移动 */ public boolean ismoveable( int newrow, int newcol) { erase(); for ( int i = 0 ; i < boxes.length; i++) { for ( int j = 0 ; j < boxes[i].length; j++) { if (boxes[i][j].iscolorbox()) { ersbox box = canvas.getbox(i + newrow, j + newcol); if (box == null || (box.iscolorbox())) { display(); return false ; } } } } display(); return true ; } /** * 将当前块移动到newrow/newcol 所指定的位置 * * @param newrow int,目的地所在行 * @param newcol int,目的地所在列 * @return boolean,true-移动成功,false-移动失败 */ private synchronized boolean moveto( int newrow, int newcol) { if (!ismoveable(newrow, newcol) || !moving) { return false ; } erase(); y = newrow; x = newcol; display(); canvas.repaint(); return true ; } /** * 当前块能否变成newstyle所指定的块样式,主要是考虑 边界以及被其他块挡住,不能移动的情况 * * @param newsytle int,希望改变的块样式,对应styles的28个值中的一个 * @return boolean,true-能改变,false-不能改变 */ private boolean isturnable( int newstyle) { int key = 0x8000 ; erase(); for ( int i = 0 ; i < boxes.length; i++) { for ( int j = 0 ; j < boxes[i].length; j++) { if ((newstyle & key) != 0 ) { ersbox box = canvas.getbox(i + y, j + x); if (box == null || (box.iscolorbox())) { display(); return false ; } } key >>= 1 ; } } display(); return true ; } /** * 将当前块变成newstyle所指定的块样式 * * @param newstyle int,希望改变的块样式,对应styles的28个值中的一个 * @return true-改变成功,false-改变失败 */ private boolean turnto( int newstyle) { if (!isturnable(newstyle) || !moving) { return false ; } erase(); int key = 0x8000 ; for ( int i = 0 ; i < boxes.length; i++) { for ( int j = 0 ; j < boxes[i].length; j++) { boolean iscolor = ((newstyle & key) != 0 ); boxes[i][j].setcolor(iscolor); key >>= 1 ; } } style = newstyle; display(); canvas.repaint(); return true ; } } |
main.java
1
2
3
4
5
6
7
8
9
10
11
12
13
|
package russiablocksgame; /** * 程序入口函数 * * @param args string[],附带的命令行参数 */ public class main { public static void main(string[] args) { new russiablocksgame( "俄罗斯方块:杨宇杰" ); } } |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/OnlyLove_KD/article/details/53813612