Java实现俄罗斯方块
代码分析
定义格子
1 package com.ftl.tetris;
2 /**
3 * 定义格子
4 */
5
6 import java.awt.image.BufferedImage;
7
8 public class Cell {
9
10 private int row;
11 private int col;
12 private BufferedImage image;
13
14 /**
15 * 构造方法,传递参数
16 * @param row 定义行
17 * @param col 定义列
18 * @param image
19 */
20 public Cell(int row, int col, BufferedImage image) {
21 super();
22 this.row = row;
23 this.col = col;
24 this.image = image;
25 }
26
27 /**
28 * drop函数,控制下降
29 * @return
30 */
31 public void drop(){
32 row++;
33 }
34
35 /**
36 * 右移
37 */
38 public void moveRight()
39 {
40 col++;
41 }
42
43 /**
44 * 左移
45 */
46 public void moveLeft(){
47 col--;
48 }
49
50 public int getRow() {
51 return row;
52 }
53 public void setRow(int row) {
54 this.row = row;
55 }
56 public int getCol() {
57 return col;
58 }
59 public void setCol(int col) {
60 this.col = col;
61 }
62 public BufferedImage getImage() {
63 return image;
64 }
65 public void setImage(BufferedImage image) {
66 this.image = image;
67 }
68
69 public String toString(){
70 return row + "," + col;
71 }
72
73
74 }
View Code
定义方块
1 package com.ftl.tetris;
2
3 import java.util.Arrays;
4 import java.util.Random;
5
6 import javax.swing.plaf.nimbus.State;
7
8 /**
9 * 4格方块,7种形态
10 */
11
12 public abstract class Tetromino {
13 protected Cell[] cells = new Cell[4]; //四个格子,静态方法
14 protected State[] states;
15
16 public State[] getStates() {
17 return states;
18 }
19
20 public void setStates(State[] states) {
21 this.states = states;
22 }
23
24
25 /*旋转状态序列号, states = index % states.length*/
26 protected int index = 10000;
27
28 /**
29 * 内部类
30 */
31
32 protected class State{
33
34 int row0,col0,row1,col2,row2,col1,row3,col3;
35
36 public State(int row0, int col0, int row1, int col2, int row2,
37 int col1, int row3, int col3) {
38 this.row0 = row0;
39 this.col0 = col0;
40 this.row1 = row1;
41 this.col2 = col2;
42 this.row2 = row2;
43 this.col1 = col1;
44 this.row3 = row3;
45 this.col3 = col3;
46 }
47 }
48
49 /**
50 * 向右旋转
51 */
52 public void roateRight(){
53 //取得变化的下个数据状态
54 //取得当前轴的row,col
55 //旋转后的数据= (row,col) + states[n]
56 this.index++;
57 State s = states[index % states.length];
58 System.out.println("index++" + this.index + "\tstates长度:" + states.length + "\t取余数 " + (index % states.length));
59 Cell o = cells[0];
60 int row = o.getRow();
61 int col = o.getCol();
62 cells[1].setRow(row + s.row1);
63 cells[2].setRow(row + s.row2);
64 cells[3].setRow(row + s.row3);
65 cells[1].setCol(col + s.col1);
66 cells[2].setCol(col + s.col2);
67 cells[3].setCol(col + s.col3);
68 }
69 /**
70 * 左旋转
71 */
72 public void roateLeft(){
73 //取得变化的下个数据状态
74 //取得当前轴的row,col
75 //旋转后的数据= (row,col) + states[n]
76 this.index--;
77 State s = states[index % states.length];
78 System.out.println("index--" + this.index + "\tstates长度:" + states.length + "\t取余数 " + (index % states.length));
79 Cell o = cells[0];
80 int row = o.getRow();
81 int col = o.getCol();
82 cells[1].setRow(row + s.row1);
83 cells[2].setRow(row + s.row2);
84 cells[3].setRow(row + s.row3);
85 cells[1].setCol(col + s.col1);
86 cells[2].setCol(col + s.col2);
87 cells[3].setCol(col + s.col3);
88 }
89
90
91 /**
92 * 工厂方法,产生四个随机方块
93 */
94 public static Tetromino getOne() {
95 Random random = new Random();
96 int type = random.nextInt(7);
97 switch (type) {
98 case 0:
99 return new T();
100 case 1:
101 return new I();
102 case 2:
103 return new S();
104 case 3:
105 return new J();
106 case 4:
107 return new L();
108 case 5:
109 return new Z();
110 case 6:
111 return new O();
112 }
113 return null;
114 }
115
116 /**
117 * 方块落下一个格子
118 */
119 public void softDorp() {
120 for (int i = 0; i < cells.length; i++) {
121 cells[i].drop();
122 }
123 }
124
125 /**
126 * 方块落左移一个格子
127 */
128 public void moveLeft() {
129 for (int i = 0; i < cells.length; i++) {
130 cells[i].moveLeft();
131 }
132 }
133
134 /**
135 * 方块落右移一个格子
136 */
137 public void moveRight() {
138 for (int i = 0; i < cells.length; i++) {
139 cells[i].moveRight();
140 }
141 }
142
143 public Cell[] getCells() {
144 return cells;
145 }
146
147 public void setCells(Cell[] cells) {
148 this.cells = cells;
149 }
150
151
152 /**
153 * 打印每个格子的行列信息
154 */
155 public String toString() {
156 return Arrays.toString(cells);
157 }
158
159 }
160
161 /**
162 * T格子
163 *
164 * @author Administrator
165 *
166 */
167 class T extends Tetromino{
168 public T() {
169 cells[0] = new Cell(0, 4, Tetris.T );
170 cells[1] = new Cell(0, 3, Tetris.T);
171 cells[2] = new Cell(0, 5, Tetris.T);
172 cells[3] = new Cell(1, 4, Tetris.T);
173 states = new State[4];
174 states[0] = new State(0,0,0,-1,0,1,1,0);
175 states[1] = new State(0,0,-1,0,1,0,0,-1);
176 states[2] = new State(0,0,0,1,0,-1,-1,0);
177 states[3] = new State(0,0,1,0,-1,0,0,1);
178 }
179 }
180
181 /**
182 * I格子
183 *
184 * @author Administrator
185 *
186 */
187 class I extends Tetromino {
188 public I() {
189 cells[0] = new Cell(0, 4, Tetris.I);
190 cells[1] = new Cell(0, 3, Tetris.I);
191 cells[2] = new Cell(0, 5, Tetris.I);
192 cells[3] = new Cell(0, 6, Tetris.I);
193 states = new State[]{
194 new State(0,0,0,-1,0,1,0,2),
195 new State(0,0,-1,0,1,0,2,0),
196 };
197 }
198 }
199
200 /**
201 * Z格子
202 *
203 * @author Administrator
204 *
205 */
206 class Z extends Tetromino {
207 public Z() {
208 cells[0] = new Cell(1, 4, Tetris.Z);
209 cells[1] = new Cell(0, 3, Tetris.Z);
210 cells[2] = new Cell(0, 4, Tetris.Z);
211 cells[3] = new Cell(1, 5, Tetris.Z);
212 states = new State[]{
213 new State(0,0,-1,-1,-1,0,0,1),
214 new State(0,0,-1,1,0,1,1,0),
215 };
216 }
217 }
218
219 /**
220 * L格子
221 *
222 * @author Administrator
223 *
224 */
225 class L extends Tetromino {
226 public L() {
227 cells[0] = new Cell(0, 4, Tetris.L);
228 cells[1] = new Cell(0, 3, Tetris.L);
229 cells[2] = new Cell(0, 5, Tetris.L);
230 cells[3] = new Cell(1, 3, Tetris.L);
231 states = new State[]{
232 new State(0,0,0,1,0,-1,-1,1),
233 new State(0,0,1,0,-1,0,1,1),
234 new State(0,0,0,-1,0,1,1,-1),
235 new State(0,0,-1,0,1,0,-1,-1),
236 };
237 }
238 }
239
240 /**
241 * S格子
242 *
243 * @author Administrator
244 *
245 */
246 class S extends Tetromino {
247 public S() {
248 cells[0] = new Cell(1, 4, Tetris.S);
249 cells[1] = new Cell(1, 3, Tetris.S);
250 cells[2] = new Cell(0, 4, Tetris.S);
251 cells[3] = new Cell(0, 5, Tetris.S);
252 states = new State[]{new State(0,0,0,-1,-1,0,-1,1),new State(0,0,-1,0,0,1,1,1)};
253 }
254 }
255
256 /**
257 * J格子
258 *
259 * @author Administrator
260 *
261 */
262 class J extends Tetromino {
263 public J() {
264 cells[0] = new Cell(0, 4, Tetris.J);
265 cells[1] = new Cell(0, 3, Tetris.J);
266 cells[2] = new Cell(0, 5, Tetris.J);
267 cells[3] = new Cell(1, 5, Tetris.J);
268 states = new State[]{
269 new State(0,0,0,-1,0,1,1,1),
270 new State(0,0,-1,0,1,0,1,-1),
271 new State(0,0,0,1,0,-1,-1,-1),
272 new State(0,0,1,0,-1,0,-1,1),
273 };
274 }
275 }
276
277 /**
278 * O格子
279 *
280 * @author Administrator
281 *
282 */
283 class O extends Tetromino {
284 public O() {
285 cells[0] = new Cell(0, 4, Tetris.O);
286 cells[1] = new Cell(0, 5, Tetris.O);
287 cells[2] = new Cell(1, 4, Tetris.O);
288 cells[3] = new Cell(1, 5, Tetris.O);
289 }
290 }
View Code
游戏主程序
1 package com.ftl.tetris;
2
3 import java.awt.Color;
4 import java.awt.Font;
5 import java.awt.Graphics;
6 import java.awt.event.KeyAdapter;
7 import java.awt.event.KeyEvent;
8 import java.awt.image.BufferedImage;
9 import java.io.IOException;
10 import java.util.Arrays;
11 import java.util.Timer;
12 import java.util.TimerTask;
13
14 import javax.imageio.ImageIO;
15 import javax.swing.JFrame;
16 import javax.swing.JPanel;
17
18 /**
19 * 俄罗斯方块
20 *
21 * @author FTL1012
22 *
23 */
24 public class Tetris extends JPanel {
25 private int score; // 分数
26 private int lines; // 行数
27 private Cell[][] walls; // 定义背景
28 private Tetromino tetromino; // 正在下降的格子
29 private Tetromino nextOne; // 下一个下降的格子
30
31 public static final int ROWS = 20; // 背景墙的行数
32 public static final int COLS = 10; // 背景墙的列数
33 private static final int CELL_SIZE = 26; //间距
34 private static final int FONT_COLOR= 0x667799; //字体颜色
35 private static final int FONT_SIZE = 30;
36
37 private Timer timer; //定时调度
38 private int speed;
39 private int level;
40 private int index;
41
42 //游戏运行状态
43 private int state;
44 private static final int RUNNING = 0;
45 private static final int PAUSE = 1;
46 private static final int GAME_OVER = 2;
47
48
49
50 /**
51 * 背景图片
52 *
53 * @param args
54 */
55 private static BufferedImage background;
56 public static BufferedImage T;
57 public static BufferedImage S;
58 public static BufferedImage I;
59 public static BufferedImage L;
60 public static BufferedImage J;
61 public static BufferedImage O;
62 public static BufferedImage Z;
63 public static BufferedImage gameOver;
64 public static BufferedImage pause;
65
66
67 /**
68 * 静态代码块加载图片
69 */
70 static {
71 try {
72 background = ImageIO.read(Tetris.class.getResource("tetris.png"));
73 gameOver = ImageIO.read(Tetris.class.getResource("gameover.png"));
74 pause = ImageIO.read(Tetris.class.getResource("pause.png"));
75 T = ImageIO.read(Tetris.class.getResource("T.png"));
76 I = ImageIO.read(Tetris.class.getResource("I.png"));
77 L = ImageIO.read(Tetris.class.getResource("L.png"));
78 O = ImageIO.read(Tetris.class.getResource("O.png"));
79 S = ImageIO.read(Tetris.class.getResource("S.png"));
80 J = ImageIO.read(Tetris.class.getResource("J.png"));
81 Z = ImageIO.read(Tetris.class.getResource("Z.png"));
82 } catch (IOException e) {
83 // TODO 自动生成的 catch 块
84 e.printStackTrace();
85 }
86 }
87
88
89
90 /**
91 * 画背景,画墙,画正在下落的方块,画下一个方块
92 */
93 @Override
94 public void paint(Graphics g) {
95 // TODO 自动生成的方法存根
96 g.drawImage(background, 0, 0, null);
97 g.translate(15, 15); // 坐标系平移15个像素
98
99 //打印背景
100 paintWall(g);
101 //打印下落的方块
102 paintTetromino(g);
103 //打印即将下落的方块
104 paintNextmino(g);
105 //绘制分数
106 paintScore(g);
107 //绘制游戏状态
108 paintState(g);
109 }
110
111 /**
112 * 绘制游戏状态
113 */
114 private void paintState(Graphics g) {
115 switch (state) {
116 case PAUSE:
117 g.drawImage(pause, -15, -15, null);
118 break;
119 case GAME_OVER:
120 g.drawImage(gameOver, -15, -15, null);
121 break;
122 }
123 }
124
125
126 /**
127 * 绘制分数
128 * @param g
129 */
130 private void paintScore(Graphics g) {
131 int x = 290;
132 int y = 160;
133 g.setColor(new Color(FONT_COLOR));
134 Font font = g.getFont();
135 font = new Font(font.getName(),font.getStyle(),FONT_SIZE);
136 g.setFont(font);
137 String str = null;
138 str = "SCORE:" + score;
139 g.drawString(str, x, y);
140 y += 56;
141 str = "LINES:" + lines;
142 g.drawString(str, x, y);
143 y += 56;
144 str = "LEVEL:" + level;
145 g.drawString(str, x, y);
146 }
147
148
149 /**
150 * 启动Action方法,初始化数组Walls,
151 * @param args
152 */
153 public void action()
154 {
155 walls = new Cell[ROWS][COLS];
156 walls[2][2] = new Cell(2,2,T); //将强的第二行第二列设置为T方块的一个格子(2,2)
157 tetromino = Tetromino.getOne(); //正在下落的方块
158 nextOne = Tetromino.getOne(); //下一个即将下落的方块
159
160 this.state = RUNNING;
161 //增加键盘监听控制
162 KeyAdapter l = new KeyAdapter() {
163
164 @Override
165 public void keyPressed(KeyEvent e) {
166 // TODO 自动生成的方法存根
167 // int key = e.getKeyCode();
168 // switch (key) {
169 // case KeyEvent.VK_DOWN:
170 // softDorpAction();
171 // break;
172 // case KeyEvent.VK_RIGHT:
173 // moveRightAction();
174 // break;
175 // case KeyEvent.VK_LEFT:
176 // moveLeftAction();
177 // break;
178 // case KeyEvent.VK_SPACE:
179 // hardDropAction();
180 // break;
181 // case KeyEvent.VK_UP:
182 // rotateRightAction();
183 // break;
184 // }
185 int key = e.getKeyCode();
186 switch (state) {
187 case GAME_OVER:
188 processGameOverKey(key);
189 break;
190 case PAUSE:
191 processPauseKey(key);
192 break;
193 case RUNNING:
194 processRunningKey(key);
195 break;
196 }
197 repaint();
198 }
199 };
200 //点击按钮的时候,按钮获得焦点,对应处理一些逻辑
201 this.requestFocus();
202 this.addKeyListener(l);
203
204 //定时方法
205 this.timer = new Timer();
206 this.timer.schedule(new TimerTask() {
207 public void run() {
208 speed = 40 - (lines / 2);
209 speed = speed < 1 ? 1 : speed;
210 level = 41 - speed;
211 if(state == RUNNING && index % speed == 0){
212 softDorpAction();
213 }
214 index++;
215 repaint();
216 }
217 }, 10, 13);
218 }
219
220 /**
221 * 运行按钮
222 * @param key
223 */
224 private void processRunningKey(int key) {
225 switch (key) {
226 case KeyEvent.VK_Q:
227 System.exit(0);
228 break;
229 case KeyEvent.VK_DOWN:
230 softDorpAction();
231 break;
232 case KeyEvent.VK_RIGHT:
233 moveRightAction();
234 break;
235 case KeyEvent.VK_LEFT:
236 moveLeftAction();
237 break;
238 case KeyEvent.VK_SPACE:
239 hardDropAction();
240 break;
241 case KeyEvent.VK_UP:
242 rotateRightAction();
243 break;
244 case KeyEvent.VK_P:
245 this.state = PAUSE;
246 break;
247 }
248
249 }
250
251 /**
252 * 停止按钮
253 * @param key
254 */
255 private void processPauseKey(int key) {
256 switch (key) {
257 case KeyEvent.VK_Q:
258 System.exit(0);
259 break;
260 case KeyEvent.VK_C:
261 index = 0;
262 this.state = RUNNING;
263 break;
264 }
265
266 }
267
268 /**
269 * 游戏结束,重新开始
270 * @param key
271 */
272 private void processGameOverKey(int key) {
273 switch (key) {
274 case KeyEvent.VK_Q:
275 System.exit(0); //退出游戏
276 break;
277 case KeyEvent.VK_S:
278 this.lines = 0;
279 this.score = 0;
280 this.walls = new Cell[ROWS][COLS];
281 this.tetromino = Tetromino.getOne();
282 this.nextOne = Tetromino.getOne();
283 this.state = RUNNING;
284 // this.index = 0;
285 break;
286 }
287 }
288
289
290 /**
291 * 绘制正在下落的方块
292 * @param args
293 */
294 public void paintTetromino(Graphics g)
295 {
296 if(tetromino == null)
297 {
298 return; //结束方法
299 }
300 //将每个格子的row 和 col转换为x,y,然后贴图
301 Cell[] cells = tetromino.cells;
302 for(int i = 0; i < cells.length; i++)
303 {
304 //cell 为每一个盒子
305 Cell cell = cells[i];
306 int x = cell.getCol() * CELL_SIZE;
307 int y = cell.getRow() * CELL_SIZE;
308 g.drawImage(cell.getImage(), x-1, y-1, null);
309 }
310 }
311
312 /**
313 * 画下一个即将下落的方块
314 */
315 public void paintNextmino(Graphics g)
316 {
317 if(nextOne == null)
318 {
319 return; //结束方法
320 }
321 //将每个格子的row 和 col转换为x,y,然后贴图
322 Cell[] cells = nextOne.cells;
323 for(int i = 0; i < cells.length; i++)
324 {
325 //cell 为每一个盒子
326 Cell cell = cells[i];
327 int x = (cell.getCol() + 10)* CELL_SIZE;
328 int y = (cell.getRow() + 1) * CELL_SIZE;
329 g.drawImage(cell.getImage(), x-1, y-1, null);
330 }
331 }
332
333
334 /**
335 * 画墙
336 *
337 * @param args
338 */
339 private void paintWall(Graphics g) {
340 // TODO 自动生成的方法存根
341 for (int row = 0; row < walls.length; row++) {
342 // line表示墙上的每一行
343 Cell[] line = walls[row];
344 for (int col = 0; col < line.length; col++) {
345 // cell表示墙上的每一个格子
346 Cell cell = line[col];
347 int x = col * CELL_SIZE;
348 int y = row * CELL_SIZE;
349 //如果cell为空,则表示没有格子
350 if(cell == null){
351 g.drawRect(x, y, CELL_SIZE, CELL_SIZE);
352 }
353 //如果不为空,表示有格子,显示各自,x-1,y-1为了不让重叠,为了美观
354 else
355 {
356 g.drawImage(cell.getImage(), x-1, y-1, null);
357 }
358 // g.drawString(row+"," + col,x,y+CELL_SIZE);
359 }
360
361 }
362 }
363
364 /**
365 * 判断是否出界
366 */
367 private boolean outOfBounds(){
368 Cell[] cells = tetromino.cells;
369 for(int i = 0; i < cells.length; i++)
370 {
371 Cell cell = cells[i];
372 int col = cell.getCol();
373 if(col < 0 || col >= COLS )
374 {
375 return true;
376 }
377 }
378 return false;
379 }
380
381 /**
382 * 判断是否重合
383 */
384 private boolean coinclude() {
385 Cell[] cells = tetromino.cells;
386 for (int i = 0; i < cells.length; i++) {
387 Cell cell = cells[i];
388 int row = cell.getRow();
389 int col = cell.getCol();
390 if (row >= 0 && row < ROWS && col >= 0 && col <= COLS
391 && walls[row][col] != null) {
392 return true; //重合
393 }
394 }
395 return false;
396 }
397
398 /**
399 * 判断右边是否出界
400 * @param args
401 */
402 public void moveRightAction(){
403 tetromino.moveRight();
404 if(this.outOfBounds() || this.coinclude())
405 {
406 tetromino.moveLeft();
407 }
408 }
409
410 /**
411 * 判断左边是否出界
412 * @param args
413 */
414 public void moveLeftAction(){
415 tetromino.moveLeft();
416 if(this.outOfBounds() || this.coinclude())
417 {
418 tetromino.moveRight();
419 }
420 }
421
422 /**
423 * 判断游戏是否结束:
424 *
425 */
426
427 private boolean isGameOver(){
428 //如果下一个放开没有出场位置,游戏结束
429 //就是: 下一个出场方块每个ge子都有对于的墙上如果有格子
430 Cell[] cells = nextOne.cells;
431 for(Cell cell:cells){
432 int row = cell.getRow();
433 int col = cell.getCol();
434 if(walls[row][col] != null){
435 return true;
436 }
437 }
438 return false;
439 }
440
441 /**
442 * 选择控制--右边
443 */
444 private void rotateRightAction() {
445 tetromino.roateRight();
446 if(this.outOfBounds() || this.coinclude()){
447 tetromino.roateLeft();
448 }
449
450 }
451
452
453 private static int[] scoreTable = {0,1,10,50,100};
454
455 /**
456 *销毁行
457 */
458 public void destoryLines()
459 {
460 int lines = 0;
461 //循环墙上的每一行,如果每一行都有格子,表示行满
462 for(int row = 0; row < walls.length; row++){
463 if(this.fullCells(row)){
464 deleteRow(row);
465 lines++;
466 }
467 }
468 this.score += scoreTable[lines];
469 this.lines += lines;
470 }
471
472 /**
473 * 删除某行
474 *
475 */
476 public void deleteRow(int row) {
477 for(int i = row; i >=1; i--)
478 {
479 System.arraycopy(walls[i-1], 0, walls[i], 0, COLS);
480 }
481 Arrays.fill(walls[0], null);
482 }
483
484
485 /**
486 * 判断行是否满了
487 */
488 public boolean fullCells(int row){
489 Cell[] line = walls[row];//获取每一个格子的行
490 for(Cell cell:line)
491 {
492 if(cell == null)
493 {
494 return false; //未满
495 }
496 }
497 return true;
498 }
499
500
501 /**
502 * 格子落地
503 */
504 public void landIntoWall(){
505 //获取正在下落的四个格子
506 Cell[] cells = tetromino.cells;
507 for(int i = 0; i< cells.length; i++)
508 {
509 Cell cell = cells[i];
510 int row = cell.getRow();
511 int col = cell.getCol();
512 //格子放在相应的位置
513 walls[row][col] = cell;
514 }
515 }
516
517
518 /**
519 * 判断是否可以继续下落
520 * @param args
521 */
522
523 private boolean canDrop(){
524 Cell[] cells = tetromino.cells;
525 //到达最后一行
526 for (int i = 0; i < cells.length; i++) {
527 Cell cell = cells[i];
528 int row = cell.getRow();
529 if( row == ROWS - 1)
530 {
531 return false; //不能下落
532 }
533 }
534 //下一行有格子
535 for(Cell cell:cells )
536 {
537 int row = cell.getRow() + 1;
538 int col = cell.getCol();
539 if( row >= 0 && row < ROWS && col >=0 && col <=COLS
540 && walls[row][col] != null)
541 {
542 return false;
543 }
544 }
545 return true;
546 }
547
548 /**
549 *下落流控制
550 */
551 public void softDorpAction() {
552 if(this.canDrop()){
553 tetromino.softDorp();
554 }else{
555 this.landIntoWall();
556 this.destoryLines();
557 this.tetromino = this.nextOne;
558 this.nextOne = Tetromino.getOne();
559 }
560 }
561
562 public void hardDropAction()
563 {
564 while(this.canDrop()){
565 this.softDorpAction();
566 }
567 landIntoWall();
568 destoryLines();
569 tetromino = nextOne;
570 nextOne = Tetromino.getOne();
571 }
572
573 public static void main(String[] args) {
574 JFrame jf = new JFrame();
575 Tetris tetris = new Tetris();
576 tetris.setBackground(new Color(0x0000ff));
577 jf.add(tetris);
578 jf.setSize(530, 580);
579 jf.setLocationRelativeTo(null);
580 jf.setTitle("Go Fighting——FTL");
581 jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
582 jf.setVisible(true);
583
584 tetris.action();
585 }
586
587 }
View Code
游戏截图
源码下载
附:程序略有小bug,感兴趣的朋友可以改改
作者:小a玖拾柒
-------------------------------------------
个性签名: 所有的事情到最後都是好的,如果不好,那說明事情還沒有到最後~
本文版权归作者【小a玖拾柒】,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利!