TETRIS 项目开发笔记

时间:2022-10-08 08:51:52

  java学习一个月了,没有什么进展,期间又是复习Linux,又是看Android,瞻前顾后,感觉自己真的是贪得无厌,

学习的东西广而不精,所以写出的文章也就只能泛泛而谈。五一小长假,哪里都没有去,也不想去,刚刚无聊刷新了下

朋友圈,朋友们不是在玩,就是在吃,突然一下子感觉自己老了许多。岁月真是把杀猪刀,夺走了我们的青春,但却无

法夺走我们的激情。

  好好复习了!

  在老师引领下,算是把人生中的第一个Java项目敲完了,感觉对于学习OOP的朋友,应该有所帮助,先做个笔记吧

等后期有时间再添些自己的Feature。

TETRIS 项目开发笔记

package com.manue1.tetris;

import javax.swing.JFrame;

/**
* 游戏窗口
*
@author Manue1
*
@version 1.0
*
*/
public class GameFrame extends JFrame{

private static final long serialVersionUID = 1L;
private Tetris tetris;
public GameFrame(){

tetris
=new Tetris();
add(tetris);
setSize(
530,580);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(
null);
}
public static void main(String[] args){
GameFrame frame
=new GameFrame();
frame.setVisible(
true);
frame.tetris.action();
//创建4个格子

}

}
TETRIS 项目开发笔记TETRIS 项目开发笔记
 1 package com.manue1.tetris;
2
3 import java.awt.image.BufferedImage;
4
5 /**
6 * 定义格子
7 * @author Manue1
8 */
9 public class Cell extends Object{
10 private int row; int col;
11 private BufferedImage image;
12
13 public Cell(int row, int col, BufferedImage image) {
14 super();
15 this.row = row;
16 this.col = col;
17 this.image = image;
18 }
19
20 public int getRow() {
21 return row;
22 }
23
24 public void setRow(int row) {
25 this.row = row;
26 }
27
28 public int getCol() {
29 return col;
30 }
31
32 public void setCol(int col) {
33 this.col = col;
34 }
35
36 public BufferedImage getImage() {
37 return image;
38 }
39
40 public void setImage(BufferedImage image) {
41 this.image = image;
42 }
43
44 @Override
45 public String toString() {
46 return "Cell [col=" + col + ", image=" + image + ", row=" + row + "]";
47 }
48
49
50 public void moveLeft(){
51 col--;
52 }
53 public void moveRight(){
54 col++;
55 }
56 public void moveDrop(){
57 row++;
58 }
59
60
61 }
定义格子
TETRIS 项目开发笔记TETRIS 项目开发笔记
  1 package com.manue1.tetris;
2 import java.util.Arrays;
3 import java.util.Random;
4
5 /**
6 * 4格方块
7 * 只能被子类使用
8 * @author Manue1
9 */
10 public abstract class Tetromino {
11
12 protected Cell[] cells =new Cell[4];//{^,^,^,^}
13
14 /*旋转状态
15 *
16 */
17 protected State[] states;
18 /* 旋转状态的序号
19 *
20 */
21 protected int index =10000;
22 /*内部类
23 *
24 */
25 protected class State {
26 int row0, col0, row1, col1, row2, col2, row3, col3;
27 public State(int row0, int col0, int row1, int col1, int row2,
28 int col2, int row3, int col3) {
29 this.row0 = row0;
30 this.col0 = col0;
31 this.row1 = row1;
32 this.col1 = col1;
33 this.row2 = row2;
34 this.col2 = col2;
35 this.row3 = row3;
36 this.col3 = col3;
37 }
38 }
39 /** 向右转 */
40 public void rotateRight() {
41
42 index++;
43 State s = states[index % states.length];
44 Cell o = cells[0];
45 int row = o.getRow();
46 int col = o.getCol();
47 cells[1].setRow(row + s.row1);
48 cells[1].setCol(col + s.col1);
49 cells[2].setRow(row + s.row2);
50 cells[2].setCol(col + s.col2);
51 cells[3].setRow(row + s.row3);
52 cells[3].setCol(col + s.col3);
53 }
54
55 /** 向左转 */
56 public void rotateLeft() {
57 index--;
58 State s = states[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[1].setCol(col + s.col1);
64 cells[2].setRow(row + s.row2);
65 cells[2].setCol(col + s.col2);
66 cells[3].setRow(row + s.row3);
67 cells[3].setCol(col + s.col3);
68 }
69
70
71
72 //工厂方法,随机产生4格方块
73
74 public static Tetromino randomOne(){
75 Random random =new Random();
76 int type =random.nextInt(7);
77 switch(type){
78 case 0:
79 return new T();
80 case 1:
81 return new I();
82 case 2:
83 return new S();
84 case 3:
85 return new J();
86 case 4:
87 return new L();
88 case 5:
89 return new Z();
90 case 6:
91 return new O();
92 }
93
94 return null;
95
96 }
97
98
99 //方块下落 左右移动 一个格子
100 public void moveRight(){
101 for(int i=0;i<cells.length ;i++){
102 cells[i].moveRight();
103 }
104 }
105 public void moveLeft(){
106 for(int i=0;i<cells.length ;i++){
107 cells[i].moveLeft();
108 }
109 }
110 public void sofeDrop(){
111 for(int i=0;i<cells.length ;i++){
112 cells[i].moveDrop();
113 }
114 }
115 //显示方块中每个格子的行列信息
116 public String toString(){
117 return Arrays.toString(cells);
118 }
119
120 }
121
122 // 定义七类格子
123 class T extends Tetromino{
124 public T(){
125 cells[0]=new Cell(0,4,Tetris.T);
126 cells[1]=new Cell(0,3,Tetris.T);
127 cells[2]=new Cell(0,5,Tetris.T);
128 cells[3]=new Cell(1,4,Tetris.T);
129 states = new State[4];
130 states[0] = new State(0, 0, 0, -1, 0, 1, 1, 0);
131 states[1] = new State(0, 0, -1, 0, 1, 0, 0, -1);
132 states[2] = new State(0, 0, 0, 1, 0, -1, -1, 0);
133 states[3] = new State(0, 0, 1, 0, -1, 0, 0, 1);
134 }
135 }
136 class S extends Tetromino{
137 public S(){
138 cells[0]=new Cell(0,4,Tetris.S);
139 cells[1]=new Cell(0,5,Tetris.S);
140 cells[2]=new Cell(1,3,Tetris.S);
141 cells[3]=new Cell(1,4,Tetris.S);
142
143
144 states = new State[] { new State(0, 0, 0, -1, -1, 0, -1, 1),
145 new State(0, 0, -1, 0, 0, 1, 1, 1) };
146
147 }
148 }
149 class Z extends Tetromino{
150 public Z() {
151 cells[0] = new Cell(1, 4, Tetris.Z);
152 cells[1] = new Cell(0, 3, Tetris.Z);
153 cells[2] = new Cell(0, 4, Tetris.Z);
154 cells[3] = new Cell(1, 5, Tetris.Z);
155
156 states = new State[] { new State(0, 0, -1, -1, -1, 0, 0, 1),
157 new State(0, 0, -1, 1, 0, 1, 1, 0) };
158 }
159 }
160 class O extends Tetromino{
161 public O() {
162 cells[0] = new Cell(0, 4, Tetris.O);
163 cells[1] = new Cell(0, 5, Tetris.O);
164 cells[2] = new Cell(1, 4, Tetris.O);
165 cells[3] = new Cell(1, 5, Tetris.O);
166 states = new State[] { new State(0, 0, 0, 1, 1, 0, 1, 1),
167 new State(0, 0, 0, 1, 1, 0, 1, 1) };
168 }
169 }
170 class J extends Tetromino{
171 public J() {
172 cells[0] = new Cell(0, 4, Tetris.J);
173 cells[1] = new Cell(0, 3, Tetris.J);
174 cells[2] = new Cell(0, 5, Tetris.J);
175 cells[3] = new Cell(1, 5, Tetris.J);
176
177 states = new State[] { new State(0, 0, 0, -1, 0, 1, 1, 1),
178 new State(0, 0, -1, 0, 1, 0, 1, -1),
179 new State(0, 0, 0, 1, 0, -1, -1, -1),
180 new State(0, 0, 1, 0, -1, 0, -1, 1) };
181 }
182 }
183 class L extends Tetromino{
184 public L() {
185 cells[0] = new Cell(0, 4, Tetris.L);
186 cells[1] = new Cell(0, 3, Tetris.L);
187 cells[2] = new Cell(0, 5, Tetris.L);
188 cells[3] = new Cell(1, 3, Tetris.L);
189
190 states = new State[] { new State(0, 0, 0, 1, 0, -1, -1, 1),
191 new State(0, 0, 1, 0, -1, 0, 1, 1),
192 new State(0, 0, 0, -1, 0, 1, 1, -1),
193 new State(0, 0, -1, 0, 1, 0, -1, -1) };
194 }
195 }
196 class I extends Tetromino{
197 public I() {
198 cells[0] = new Cell(0, 4, Tetris.I);
199 cells[1] = new Cell(0, 3, Tetris.I);
200 cells[2] = new Cell(0, 5, Tetris.I);
201 cells[3] = new Cell(0, 6, Tetris.I);
202
203 states = new State[] { new State(0, 0, 0, -1, 0, 1, 0, 2),
204 new State(0, 0, -1, 0, 1, 0, 2, 0) };
205 }
206 }
七中方块
TETRIS 项目开发笔记TETRIS 项目开发笔记
  1 package com.manue1.tetris;
2 import java.awt.Color;
3 import java.awt.Font;
4 import java.awt.Graphics;
5 import java.awt.event.KeyAdapter;
6 import java.awt.event.KeyEvent;
7 import java.awt.image.BufferedImage;
8 import java.util.Arrays;
9 import java.util.Timer;
10 import java.util.TimerTask;
11
12 import javax.swing.JPanel;
13 import javax.imageio.ImageIO;
14
15 /**
16 * 俄罗斯方块面板
17 * @author Manue1
18 * @version 1.0
19 */
20 public class Tetris extends JPanel {
21
22
23 private static final long serialVersionUID = 1L;
24 /*
25 * 分数 墙 正在 下落的方块 下一个方块
26 */
27 public static final int FONT_COLOR=0x667799;
28 public static final int FONT_SIZE=30;
29 private int score;
30 private int lines; // 销毁的行数
31 private Cell[][] wall = new Cell[ROWS][COLS]; //
32 private Tetromino tetromino; // 正在下落的四格方块
33 private Tetromino nextOne;
34 public static final int ROWS = 20; // 行数
35 public static final int COLS = 10; // 列数
36
37 /*
38 * 背景图片
39 */
40 private static BufferedImage background;
41 private static BufferedImage overImage;
42 public static BufferedImage T;
43 public static BufferedImage S;
44 public static BufferedImage I;
45 public static BufferedImage L;
46 public static BufferedImage J;
47 public static BufferedImage O;
48 public static BufferedImage Z;
49
50 /*
51 * 静态代码块
52 */
53 static {
54 try { // 从Tetris类所在的包中读取图片文件到内存对象
55 background = ImageIO.read(Tetris.class.getResource("tetris.png"));
56 overImage = ImageIO.read(Tetris.class.getResource("game-over.png"));
57 T = ImageIO.read(Tetris.class.getResource("T.png"));
58 I = ImageIO.read(Tetris.class.getResource("I.png"));
59 S = ImageIO.read(Tetris.class.getResource("S.png"));
60 Z = ImageIO.read(Tetris.class.getResource("Z.png"));
61 J = ImageIO.read(Tetris.class.getResource("J.png"));
62 L = ImageIO.read(Tetris.class.getResource("L.png"));
63 O = ImageIO.read(Tetris.class.getResource("O.png"));
64
65 } catch (Exception e) {
66 e.printStackTrace();
67 }
68 }
69
70 // 在Tetris类中重写 绘制方法 绘制背景图片
71 public void paint(Graphics g) {
72 g.drawImage(background, 0, 0, null);
73 g.translate(15, 15); // 坐标系平移
74 paintWall(g); // 画墙
75 paintTetromino(g);
76 paintnextOne(g);
77 paintScore(g);//绘制分数
78 if (gameOver) {
79 g.drawImage(overImage, 0, 0, null);
80 }
81 }
82
83 /*
84 * 在Tetris添加启动方法action()
85 */
86 public void action() {
87 wall = new Cell[ROWS][COLS];
88 tetromino = Tetromino.randomOne();
89 nextOne = Tetromino.randomOne();
90
91 /* 处理键盘按下事件, 在按下按键时候执行下落方法
92 * 监听键盘事件 创建监听器对象, 注册监听器
93 */
94
95 this.addKeyListener(new KeyAdapter() {
96 public void keyPressed(KeyEvent e) {
97 int key = e.getKeyCode();// [c]
98
99 if (key == KeyEvent.VK_Q) {//Q表示退出
100 System.exit(0);// 结束Java进程
101 }
102 if (gameOver) {
103 if (key == KeyEvent.VK_S) {//S表示开始
104 startAction();
105 repaint();
106 }
107 return;
108 }
109 if (pause) {// pause = true
110 if (key == KeyEvent.VK_C) {//C表示继续
111 continueAction();
112 repaint();
113 }
114 return;
115 }
116
117
118
119
120 switch (key) {
121 case KeyEvent.VK_DOWN:
122 //tetromino.sofeDrop();
123 softDropAction();
124
125 break;
126 case KeyEvent.VK_RIGHT:
127 //tetromino.moveRight();
128 moveRightAction();
129 break;
130 case KeyEvent.VK_LEFT:
131 //tetromino.moveLeft();
132 moveLeftAction();
133 break;
134 case KeyEvent.VK_SPACE :
135
136 hardDropAction();
137 break;
138 case KeyEvent.VK_UP:
139 rotateRightAction();
140 break;
141 case KeyEvent.VK_P://按键盘上的P表示暂停
142 pauseAction();
143 break;
144 }
145 repaint();// 再画一次!
146 }
147 });
148
149 this.requestFocus(); //为面板请求焦点
150
151 this.setFocusable(true); //面板可以获得焦点
152 /*
153 * 计时器 自动下落
154 */
155 timer = new Timer();
156 timer.schedule(
157 new TimerTask(){
158 public void run(){
159 //tetromino.sofeDrop();
160 softDropAction();
161 repaint();
162 }
163 },1000,1000);
164
165
166 }
167
168 public static final int CELL_SIZE = 26;
169
170 /*
171 * 画墙
172 */
173
174 private void paintWall(Graphics g) {
175 for (int row = 0; row < wall.length; row++) {
176 Cell[] line = wall[row];
177 // line 代表墙上的每一行
178 for (int col = 0; col < line.length; col++) {
179 Cell cell = line[col];
180 // cell 代表墙上的每个格子
181 int x = col * CELL_SIZE;
182 int y = row * CELL_SIZE;
183 if (cell == null) {
184 g.drawRect(x, y, CELL_SIZE, CELL_SIZE);
185
186 } else {
187 g.drawImage(cell.getImage(), x - 1, y - 1, null);
188
189 }
190 // g.drawString(row+","+col, x,y+CELL_SIZE);
191 }
192 }
193 }
194
195 /*
196 * 正在下落 方块
197 */
198 public void paintTetromino(Graphics g) {
199 if (tetromino == null) {return;} // 如果是空 直接不执行了 输入数据的有效性检测
200 Cell[] cells = tetromino.cells;
201 for (int i = 0; i < cells.length; i++) {
202 Cell cell = cells[i];
203 int x = cell.getCol() * CELL_SIZE;
204 int y = cell.getRow() * CELL_SIZE;
205 g.drawImage(cell.getImage(), x, y, null);
206 }
207 }
208 /*
209 * 下一个下落的方块
210 */
211 public void paintnextOne(Graphics g) {
212 if (nextOne == null) {return;} // 如果是空 直接不执行了 输入数据的有效性检测
213 Cell[] cells = nextOne.cells;
214 for (int i = 0; i < cells.length; i++) {
215 Cell cell = cells[i];
216 int x = (cell.getCol()+10) * CELL_SIZE;
217 int y = (cell.getRow()+1) * CELL_SIZE;
218 g.drawImage(cell.getImage(), x, y, null);
219 }
220 }
221
222 /*在Tetris类中添加方法
223 * 检测正在下路方块是否出界
224 */
225 /** 检查当前正在下落的方块是否出界了 */
226 private boolean outOfBounds() {
227 Cell[] cells = tetromino.cells;
228 for (int i = 0; i < cells.length; i++) {
229 Cell cell = cells[i];
230 int col = cell.getCol();
231 if (col < 0 || col >= COLS) {
232 return true;
233 }
234 }
235 return false;
236 }
237 /** 检查正在下落的方块是否与墙上的砖块重叠 */
238 private boolean coincide() {
239 Cell[] cells = tetromino.cells;
240 for (int i = 0; i < cells.length; i++) {
241 Cell cell = cells[i];
242 int row = cell.getRow();
243 int col = cell.getCol();
244 // 如果墙的row,col位置上有格子,就重叠了!
245 if (row >= 0 && row < ROWS && col >= 0 && col <= COLS
246 && wall[row][col] != null) {
247 return true;// 重叠
248 }
249 }
250 return false;
251 }
252 /** 在Tetris 类上添加方法, 向右移动的流程控制 */
253 public void moveRightAction() {
254 // 尝试先向右移动, 如果发现超出了边界, 就
255 // 向左移动, 修正回来.
256 tetromino.moveRight();// coincide重叠
257 if (outOfBounds() || coincide()) {
258 tetromino.moveLeft();
259 }
260 }
261 public void moveLeftAction() {
262 tetromino.moveLeft();
263 if (outOfBounds() || coincide()) {
264 tetromino.moveRight();
265 }
266 }
267
268
269
270
271
272
273 /* 下落流程控制
274 *
275 */
276
277 public void softDropAction() {
278 if (canDrop()) {
279 tetromino.sofeDrop();
280 } else {
281 landIntoWall();
282 destoryLines();
283 checkGameOverAction();
284 tetromino = nextOne;
285 nextOne = Tetromino.randomOne();
286 }
287 }
288 public void hardDropAction(){
289 while(canDrop()){
290 tetromino.sofeDrop();
291 }
292 landIntoWall();
293 destoryLines();
294 checkGameOverAction();
295 tetromino = nextOne;
296 nextOne = Tetromino.randomOne();
297
298 }
299
300
301
302
303 private static int[] scoreTable={0,1,10,50,100};
304
305
306 /* 调用删除行方法。循环让上面所有的行落下来
307
308 */
309 private void destoryLines() {
310 int lines = 0;
311 for (int row = 0; row < wall.length; row++) {
312 if (fullCells(row)) {
313 deleteRow(row);
314 lines++;
315 }
316 }
317 this.score += scoreTable[lines];
318 this.lines += lines;
319 }
320
321
322 /*
323 * 删除行
324 */
325 private void deleteRow(int row) {
326 for (int i = row; i >= 1; i--) {
327 System.arraycopy(wall[i - 1], 0, wall[i], 0, COLS);
328 }
329 Arrays.fill(wall[0], null);
330 }
331
332
333 /* 判断行是否被填充
334 *
335 */
336 private boolean fullCells(int row){
337 Cell[] line =wall[row];
338 /*
339 for(Cell cell : line){
340 if(cell==null) return false;
341 }
342 */
343 for(int i=0;i<line.length;i++){
344 if(line[i]==null)return false;
345 }
346 return true;
347 }
348
349
350
351 /*下落到最低行停止
352 *
353 */
354 private void landIntoWall(){
355 Cell[] cells=tetromino.cells;
356 for(int i=0;i<cells.length;i++){
357 Cell cell = cells[i];
358 int row,col;
359 row=cell.getRow();
360 col=cell.getCol();
361 wall[row][col]=cell;
362 }
363 }
364
365
366 private boolean canDrop() {
367 Cell[] cells = tetromino.cells;
368 for (int i = 0; i < cells.length; i++) {
369 Cell cell = cells[i];
370 int row = cell.getRow();
371 if (row == ROWS - 1) {
372 return false;
373 }
374 }
375 for (Cell cell : cells) {// Java 5 以后可以使用
376 int row = cell.getRow() + 1;
377 int col = cell.getCol();
378 if (row >= 0 && row < ROWS && col >= 0 && col <= COLS
379 && wall[row][col] != null) {
380 return false;
381 }
382 }
383 return true;
384 }
385
386 /*绘制分数
387 *
388 */
389 private void paintScore(Graphics g) {
390 int x = 290;
391 int y = 160;
392 g.setColor(new Color(FONT_COLOR));
393 Font font = g.getFont();// 取得g当前字体
394 font = new Font(font.getName(), font.getStyle(), FONT_SIZE);
395 g.setFont(font);// 更改了g的字体
396 String str = "SCORE:" + score;
397 g.drawString(str, x, y);
398 y += 56;
399 str = "LINES:" + lines;
400 g.drawString(str, x, y);
401 y += 56;
402 str = "[P]Pause";
403 if (pause) {
404 str = "[C]Continue";
405 }
406 if (gameOver) {
407 str = "[S]Start!";
408 }
409 g.drawString(str, x, y);
410
411
412 }
413
414
415
416 /** 在Tetris类中添加 旋转流程控制方法 */
417 public void rotateRightAction() {
418 tetromino.rotateRight();
419 if (outOfBounds() || coincide()) {
420 tetromino.rotateLeft();
421 }
422 }
423
424
425
426 /*
427 * 流程处理
428 */
429 private Timer timer;
430 private boolean pause;//是否为暂停状态
431 private boolean gameOver;//是否为游戏结束状态
432 private long interval = 600;// 间隔时间
433
434
435 /** 在Tetris类中添加 开始流程控制 */
436 public void startAction() {
437 pause = false;
438 gameOver = false;
439 score = 0;
440 lines = 0;
441 clearWall();
442 tetromino = Tetromino.randomOne();
443 nextOne = Tetromino.randomOne();
444 timer = new Timer();
445 timer.schedule(new TimerTask() {
446 public void run() {
447 softDropAction();
448 repaint();
449 }
450 }, interval, interval);
451 }
452 /**
453 * 清除墙上的方块
454 */
455 private void clearWall() {
456 for (Cell[] line : wall) {
457 Arrays.fill(line, null);
458 }
459 }
460 /**
461 * 暂停
462 */
463 public void pauseAction() {
464 timer.cancel();
465 pause = true;
466 }
467 /**
468 * 继续
469 */
470 public void continueAction() {
471 timer = new Timer();
472 timer.schedule(new TimerTask() {
473 @Override
474 public void run() {
475 softDropAction();
476 repaint();
477 }
478 }, interval, interval);
479 pause = false;
480 }
481 /**
482 * 游戏结束
483 */
484 public void checkGameOverAction() {
485 if (wall[0][4] != null) {
486 timer.cancel();
487 gameOver = true;
488 }
489 }
490 }
面板操作