TETRIS 项目开发笔记

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

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

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

法夺走我们的激情。

  好好复习了!

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

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

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个格子

  }

}
 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 }
定义格子
  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 }
七中方块
  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 }
面板操作

 

posted on 2015-05-01 11:01  manue1  阅读(1373)  评论(0编辑  收藏  举报

导航