zoukankan      html  css  js  c++  java
  • Java项目--俄罗斯方块

    Java项目--俄罗斯方块

    百度盘链接

    链接:http://pan.baidu.com/s/1mhQ9SYc 密码:9ujo

    一、心得

    二、游戏实例

    游戏截图

    目录结构

    三、代码

    1、主界面 Tetris.java

      1 package com.hsj.tetris;
      2 
      3 import java.awt.Color;
      4 import java.awt.Font;
      5 import java.awt.Graphics;
      6 import java.awt.Image;
      7 import java.awt.event.KeyAdapter;
      8 import java.awt.event.KeyEvent;
      9 import java.util.Arrays;
     10 import java.util.Timer;
     11 import java.util.TimerTask;
     12 
     13 import javax.imageio.ImageIO;
     14 import javax.swing.JFrame;
     15 import javax.swing.JPanel;
     16 /**
     17  * 俄罗斯方块游戏面板 
     18  *
     19  */
     20 public class Tetris extends JPanel {
     21     /** 正在下落方块 */
     22     private Tetromino tetromino;
     23     /** 下一个下落方块 */
     24     private Tetromino nextOne;
     25     /** 行数 */
     26     public static final int ROWS = 20;
     27     /** 列数 */
     28     public static final int COLS = 10;
     29     /***/
     30     private Cell[][] wall = new Cell[ROWS][COLS]; 
     31     /** 消掉的行数 */
     32     private int lines;
     33     /** 分数 */
     34     private int score;
     35     
     36     public static final int CELL_SIZE = 26;
     37     
     38     private static Image background;//背景图片
     39     public static Image I;
     40     public static Image J;
     41     public static Image L;
     42     public static Image S;
     43     public static Image Z;
     44     public static Image O;
     45     public static Image T;
     46     static{//加载静态资源的,加载图片
     47         //建议将图片放到 Tetris.java 同包中!
     48         //从包中加载图片对象,使用Swing API实现
     49 //        Toolkit toolkit = Toolkit.getDefaultToolkit();
     50 //        background = toolkit.getImage(
     51 //                Tetris.class.getResource("tetris.png"));
     52 //        T = toolkit.getImage(Tetris.class.getResource("T.png"));
     53 //        S = toolkit.getImage(Tetris.class.getResource("S.png"));
     54 //        Z = toolkit.getImage(Tetris.class.getResource("Z.png"));
     55 //        L = toolkit.getImage(Tetris.class.getResource("L.png"));
     56 //        J = toolkit.getImage(Tetris.class.getResource("J.png"));
     57 //        I = toolkit.getImage(Tetris.class.getResource("I.png"));
     58 //        O = toolkit.getImage(Tetris.class.getResource("O.png"));
     59         //import javax.imageio.ImageIO;
     60         try{
     61             background = ImageIO.read(
     62                 Tetris.class.getResource("tetris.png"));
     63             T=ImageIO.read(Tetris.class.getResource("T.png"));
     64             I=ImageIO.read(Tetris.class.getResource("I.png"));
     65             S=ImageIO.read(Tetris.class.getResource("S.png"));
     66             Z=ImageIO.read(Tetris.class.getResource("Z.png"));
     67             L=ImageIO.read(Tetris.class.getResource("L.png"));
     68             J=ImageIO.read(Tetris.class.getResource("J.png"));
     69             O=ImageIO.read(Tetris.class.getResource("O.png"));
     70         }catch(Exception e){
     71             e.printStackTrace();
     72         }
     73     }
     74     
     75     public void action(){
     76         //tetromino = Tetromino.randomTetromino();
     77         //nextOne = Tetromino.randomTetromino();
     78         //wall[19][2] = new Cell(19,2,Tetris.T);
     79         startAction();
     80         repaint();
     81         KeyAdapter l = new KeyAdapter() {
     82             public void keyPressed(KeyEvent e) {
     83                 int key = e.getKeyCode();
     84                 if(key == KeyEvent.VK_Q){
     85                     System.exit(0);//退出当前的Java进程
     86                 }
     87                 if(gameOver){
     88                     if(key==KeyEvent.VK_S){
     89                         startAction();
     90                     }
     91                     return;
     92                 }
     93                 //如果暂停并且按键是[C]就继续动作
     94                 if(pause){//pause = false
     95                     if(key==KeyEvent.VK_C){    continueAction();    }
     96                     return;
     97                 }
     98                 //否则处理其它按键
     99                 switch(key){
    100                 case KeyEvent.VK_RIGHT: moveRightAction(); break;
    101                 case KeyEvent.VK_LEFT: moveLeftAction(); break;
    102                 case KeyEvent.VK_DOWN: softDropAction() ; break;
    103                 case KeyEvent.VK_UP: rotateRightAction() ; break;
    104                 case KeyEvent.VK_Z: rotateLeftAction() ; break;
    105                 case KeyEvent.VK_SPACE: hardDropAction() ; break;
    106                 case KeyEvent.VK_P: pauseAction() ; break;
    107                 }
    108                 repaint();
    109             }
    110         };
    111         this.requestFocus();
    112         this.addKeyListener(l);
    113     }
    114     
    115     public void paint(Graphics g){
    116         g.drawImage(background, 0, 0, null);//使用this 作为观察者
    117         g.translate(15, 15);//平移绘图坐标系
    118         paintTetromino(g);//绘制正在下落的方块
    119         paintWall(g);//画墙
    120         paintNextOne(g);
    121         paintScore(g);
    122     }
    123     public static final int FONT_COLOR = 0x667799;
    124     public static final int FONT_SIZE = 0x20;
    125     private void paintScore(Graphics g) {
    126         Font f = getFont();//获取当前的 面板默认字体
    127         Font font = new Font(
    128                 f.getName(), Font.BOLD, FONT_SIZE);
    129         int x = 290;
    130         int y = 162;
    131         g.setColor(new Color(FONT_COLOR));
    132         g.setFont(font);
    133         String str = "SCORE:"+this.score;
    134         g.drawString(str, x, y);
    135         y+=56;
    136         str = "LINES:"+this.lines;
    137         g.drawString(str, x, y);
    138         y+=56;
    139         str = "[P]Pause";
    140         if(pause){str = "[C]Continue";}
    141         if(gameOver){    str = "[S]Start!";}
    142         g.drawString(str, x, y);
    143     }
    144 
    145     private void paintNextOne(Graphics g) {
    146         Cell[] cells = nextOne.getCells();
    147         for(int i=0; i<cells.length; i++){
    148             Cell c = cells[i];
    149             int x = (c.getCol()+10) * CELL_SIZE-1;
    150             int y = (c.getRow()+1) * CELL_SIZE-1;
    151             g.drawImage(c.getImage(), x, y, null);
    152         }    
    153     }
    154 
    155     private void paintTetromino(Graphics g) {
    156         Cell[] cells = tetromino.getCells();
    157         for(int i=0; i<cells.length; i++){
    158             Cell c = cells[i];
    159             int x = c.getCol() * CELL_SIZE-1;
    160             int y = c.getRow() * CELL_SIZE-1;
    161             //g.setColor(new Color(c.getColor()));
    162             //g.fillRect(x, y, CELL_SIZE, CELL_SIZE);
    163             g.drawImage(c.getImage(), x, y, null);
    164         }        
    165     }
    166 
    167     //在 Tetris 类 中添加 方法 paintWall
    168     private void paintWall(Graphics g){
    169         for(int row=0; row<wall.length; row++){
    170             //迭代每一行, i = 0 1 2 ... 19
    171             Cell[] line = wall[row];
    172             //line.length = 10
    173             for(int col=0; col<line.length; col++){
    174                 Cell cell = line[col]; 
    175                 int x = col*CELL_SIZE; 
    176                 int y = row*CELL_SIZE;
    177                 if(cell==null){
    178                     //g.setColor(new Color(0));
    179                     //画方形 
    180                     //g.drawRect(x, y, CELL_SIZE, CELL_SIZE);
    181                 }else{
    182                     g.drawImage(cell.getImage(), x-1, y-1, null);
    183                 }
    184             }
    185         }
    186     }
    187     /**
    188      * 在 Tetris(俄罗斯方块) 类中增加方法
    189      * 这个方法的功能是:软下落的动作 控制流程
    190      * 完成功能:如果能够下落就下落,否则就着陆到墙上,
    191      *   而新的方块出现并开始落下。
    192      */
    193     public void softDropAction(){
    194         if(tetrominoCanDrop()){
    195             tetromino.softDrop();
    196         }else{
    197             tetrominoLandToWall();
    198             destroyLines();//破坏满的行
    199             checkGameOver();
    200             tetromino = nextOne;
    201             nextOne = Tetromino.randomTetromino();
    202         }
    203     }
    204     /** 销毁已经满的行,并且计分
    205      * 1)迭代每一行 
    206      * 2)如果(检查)某行满是格子了 就销毁这行 
    207      **/
    208     public void destroyLines(){
    209         int lines = 0;
    210         for(int row = 0; row<wall.length; row++){
    211             if(fullCells(row)){
    212                 deleteRow(row);
    213                 lines++;
    214             }
    215         }
    216         // lines = ?
    217         this.lines += lines;//0 1 2 3 4
    218         this.score += SCORE_TABLE[lines];
    219     }
    220     private static final int[] SCORE_TABLE={0,1,10,30,200};
    221     //                                      0 1  2  3  4
    222     
    223     public boolean fullCells(int row){
    224         Cell[] line = wall[row];
    225         for(int i=0; i<line.length; i++){
    226             if(line[i]==null){//如果有空格式就不是满行
    227                 return false;
    228             }
    229         }
    230         return true;
    231     }
    232     public void deleteRow(int row){
    233         for(int i=row; i>=1; i--){
    234             //复制 [i-1] -> [i] 
    235             System.arraycopy(wall[i-1], 0, wall[i], 0, COLS);
    236         }
    237         Arrays.fill(wall[0], null);
    238     }
    239     
    240     /** 检查当前的4格方块能否继续下落 */
    241     public boolean tetrominoCanDrop(){
    242         Cell[] cells = tetromino.getCells();
    243         for(int i = 0; i<cells.length; i++){
    244             Cell cell = cells[i];
    245             int row = cell.getRow(); int col = cell.getCol();
    246             if(row == ROWS-1){return false;}//到底就不能下降了
    247         }
    248         for(int i = 0; i<cells.length; i++){
    249             Cell cell = cells[i];
    250             int row = cell.getRow(); int col = cell.getCol();
    251             if(wall[row+1][col] != null){
    252                 return false;//下方墙上有方块就不能下降了
    253             }
    254         }
    255         return true;
    256     }
    257     /** 4格方块着陆到墙上 */
    258     public void tetrominoLandToWall(){
    259         Cell[] cells = tetromino.getCells();
    260         for(int i=0; i<cells.length; i++){
    261             Cell cell = cells[i];
    262             int row = cell.getRow();
    263             int col = cell.getCol();
    264             wall[row][col] = cell;
    265         }
    266     }
    267     
    268     public void moveRightAction(){
    269         tetromino.moveRight();
    270         if(outOfBound() || coincide()){
    271             tetromino.moveLeft();
    272         }
    273     }
    274     public void moveLeftAction(){
    275         tetromino.moveLeft();
    276         if(outOfBound() || coincide()){
    277             tetromino.moveRight();
    278         }
    279     }
    280     /** ... */
    281     private boolean outOfBound(){
    282         Cell[] cells = tetromino.getCells();
    283         for(int i=0; i<cells.length; i++){
    284             Cell cell = cells[i];
    285             int col = cell.getCol();
    286             if(col<0 || col>=COLS){
    287                 return true;//出界了
    288             }
    289         }
    290         return false;
    291     }
    292     private boolean coincide(){
    293         Cell[] cells = tetromino.getCells();
    294         //for each 循环、迭代,简化了"数组迭代书写"
    295         for(Cell cell: cells){//Java 5 以后提供增强版for循环
    296             int row = cell.getRow();
    297             int col = cell.getCol();
    298             if(row<0 || row>=ROWS || col<0 || col>=COLS || 
    299                     wall[row][col]!=null){
    300                 return true; //墙上有格子对象,发生重合
    301             }
    302         }
    303         return false;
    304     } 
    305     /** 向右旋转动作 */
    306     public void rotateRightAction(){
    307         //旋转之前
    308         //System.out.println(tetromino);
    309         tetromino.rotateRight();
    310         //System.out.println(tetromino);
    311         //旋转之后
    312         if(outOfBound() || coincide()){
    313             tetromino.rotateLeft();
    314         }
    315     }
    316     
    317     /** Tetris 类中添加的方法 */
    318     public void rotateLeftAction(){
    319         tetromino.rotateLeft();
    320         if(outOfBound() || coincide()){
    321             tetromino.rotateRight();
    322         }
    323     }
    324     public void hardDropAction(){
    325         while(tetrominoCanDrop()){
    326             tetromino.softDrop();
    327         }
    328         tetrominoLandToWall();
    329         destroyLines();
    330         checkGameOver();
    331         tetromino = nextOne;
    332         nextOne = Tetromino.randomTetromino();
    333     }
    334     
    335     private boolean pause;
    336     private boolean gameOver;
    337     private Timer timer;
    338     /** Tetris 类中添加的方法, 用于启动游戏 */
    339     public void startAction(){
    340         clearWall();
    341         tetromino = Tetromino.randomTetromino();
    342         nextOne = Tetromino.randomTetromino();
    343         lines = 0; score = 0;    pause=false; gameOver=false;
    344         timer = new Timer();
    345         timer.schedule(new TimerTask(){
    346             public void run() {
    347                 softDropAction();
    348                 repaint();
    349             }
    350         }, 700, 700);
    351     }
    352     
    353     private void clearWall(){
    354         //将墙的每一行的每个格子清理为null
    355         for(int row=0; row<ROWS; row++){
    356             Arrays.fill(wall[row], null);
    357         }
    358     }
    359     
    360     /** 在Tetris 类中添加方法  */
    361     public void pauseAction(){
    362         timer.cancel(); //停止定时器
    363         pause = true;
    364         repaint();
    365     }
    366     public void continueAction(){
    367         timer = new Timer();
    368         timer.schedule(new TimerTask() {
    369             public void run() {
    370                 softDropAction();
    371                 repaint();
    372             }
    373         }, 700, 700);
    374         pause = false;
    375         repaint();
    376     }
    377     /** 在 Tetris 类中添加 方法 */
    378     public void checkGameOver(){
    379         if(wall[0][4]==null){
    380             return;
    381         }
    382         gameOver = true;
    383         timer.cancel();
    384         repaint();
    385     }
    386     
    387     public static void main(String[] args) {
    388         JFrame frame = new JFrame();
    389         Tetris tetris = new Tetris();
    390         frame.add(tetris);
    391         frame.setSize(525, 550);
    392         frame.setUndecorated(false);//true去掉窗口框!
    393         frame.setTitle("俄罗斯方块");
    394         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    395         //Location 位置 RelativeTo相对于 
    396         frame.setLocationRelativeTo(null);//使当前窗口居中
    397         frame.setVisible(true);
    398         tetris.action();
    399     }
    400 }

    二、Cell.java

     1 package com.fry.tetris;
     2 
     3 import java.awt.Image;
     4 
     5 /**
     6  * 格子
     7  * 每一个小格子,就有所在的行 列 和图片 
     8  */
     9 public class Cell {
    10     private int row;
    11     private int col;
    12     //private int color;
    13     private Image image;//格子的贴图
    14     
    15     public Cell() {
    16     }
    17 
    18     public Cell(int row, int col, Image image) {
    19         super();
    20         this.row = row;
    21         this.col = col;
    22         this.image = image;
    23     }
    24 
    25     public int getRow() {
    26         return row;
    27     }
    28 
    29     public void setRow(int row) {
    30         this.row = row;
    31     }
    32 
    33     public int getCol() {
    34         return col;
    35     }
    36 
    37     public void setCol(int col) {
    38         this.col = col;
    39     }
    40     
    41     
    42     public Image getImage() {
    43         return image;
    44     }
    45 
    46     public void setImage(Image image) {
    47         this.image = image;
    48     }
    49 
    50     public void moveRight(){
    51         col++;
    52         //System.out.println("Cell moveRight()" + col); 
    53     }
    54     
    55     public void moveLeft(){
    56         col--;
    57     }
    58     
    59     public void moveDown(){
    60         row++;
    61     }
    62     
    63     @Override
    64     public String toString() {
    65         return "["+row+","+col+"]";
    66     }
    67 }

    三、功能实现 Tetromino.java

    package com.fry.tetris;
    
    import java.util.Arrays;
    import java.util.Random;
    
    /**
     * 4格方块 
     */
    public class Tetromino {
        protected Cell[] cells = new Cell[4];
        /** 保存旋转的相对于轴位置状态 */
        protected State[] states;
        
        /** 随机生成 4格方块, 使用简单工厂方法模式! 
         * randomTetromino 随机生成一个四格方块 
         * 这个方面的返回值是多态的!
         * */
        public static Tetromino randomTetromino(){
            Random r = new Random();
            int type = r.nextInt(7);
            switch(type){
            case 0: return new T();
            case 1: return new I();
            case 2: return new J();
            case 3: return new L();
            case 4: return new O();
            case 5: return new S();
            case 6: return new Z();
            }
            return null;
        }
        
        public Cell[] getCells() {
            return cells;
        }
    
        /** 下落 */
        public void softDrop(){
            for(int i=0; i<cells.length; i++){
                cells[i].moveDown();
            }
        }
        public void moveRight(){
            //System.out.println("moveRight()");
            for(int i=0; i<cells.length; i++){
                this.cells[i].moveRight();
            }
        } 
        public void moveLeft(){
            for(int i=0; i<cells.length; i++){
                cells[i].moveLeft();
            }
        }
        private int index = 100000;
        /** 在 Tetromino 上添加方法  */
        public void rotateRight() {
            index++;//index = 10001
            // index % states.length = 10001 % 4 = 1
            State s = states[index%states.length];//s1
            // [0] + s1 = [1]
            Cell o = cells[0];//获取当前的轴
            //轴与相对位置的和作为旋转以后的格子位置
            cells[1].setRow(o.getRow()+s.row1);
            cells[1].setCol(o.getCol()+s.col1);
            cells[2].setRow(o.getRow()+s.row2);
            cells[2].setCol(o.getCol()+s.col2);
            cells[3].setRow(o.getRow()+s.row3);
            cells[3].setCol(o.getCol()+s.col3);
        }
        /** 在 Tetromino 上添加方法  */
        public void rotateLeft() {
            index--;//index = 10001
            // index % states.length = 10001 % 4 = 1
            State s = states[index%states.length];//s1
            // [0] + s1 = [1]
            Cell o = cells[0];//获取当前的轴
            cells[1].setRow(o.getRow()+s.row1);
            cells[1].setCol(o.getCol()+s.col1);
            cells[2].setRow(o.getRow()+s.row2);
            cells[2].setCol(o.getCol()+s.col2);
            cells[3].setRow(o.getRow()+s.row3);
            cells[3].setCol(o.getCol()+s.col3);
        }
        
        @Override
        public String toString() {
            return Arrays.toString(cells); 
        }
        
        /** Tetromino 类中添加的 内部类 用于记录旋转状态 */
        protected class State{
            int row0,col0,row1,col1,row2,col2,row3,col3;
    
            public State(int row0, int col0, int row1, int col1,
                    int row2, int col2,
                    int row3, int col3) {
                this.row0 = row0;
                this.col0 = col0;
                this.row1 = row1;
                this.col1 = col1;
                this.row2 = row2;
                this.col2 = col2;
                this.row3 = row3;
                this.col3 = col3;
            }      
        }
        
    }//Tetromino 类的结束
    class T extends Tetromino{
        public T() {
            cells[0] = new Cell(0, 4, Tetris.T);
            cells[1] = new Cell(0, 3, Tetris.T);
            cells[2] = new Cell(0, 5, Tetris.T);
            cells[3] = new Cell(1, 4, Tetris.T);
            states = new State[]{
                    new State(0,0, 0,-1, 0,1, 1, 0),
                    new State(0,0, -1,0, 1,0, 0,-1),
                    new State(0,0, 0,1,  0,-1, -1,0),
                    new State(0,0, 1,0, -1,0, 0,1)};
        }
    }
    class I extends Tetromino{
        public I() {
            cells[0] = new Cell(0, 4, Tetris.I);
            cells[1] = new Cell(0, 3, Tetris.I);
            cells[2] = new Cell(0, 5, Tetris.I);
            cells[3] = new Cell(0, 6, Tetris.I);
            states = new State[]{
                    new State(0,0, 0,1, 0,-1, 0,-2),
                    new State(0,0, -1,0, 1,0,2,0)};
        }
    }
    class L extends Tetromino {
        public L() {
            cells[0] = new Cell(0, 4, Tetris.L);
            cells[1] = new Cell(0, 3, Tetris.L);
            cells[2] = new Cell(0, 5, Tetris.L);
            cells[3] = new Cell(1, 3, Tetris.L);
            states = new State[]{
                    new State(0,0, 0,-1, 0,1, 1,-1 ),
                    new State(0,0, -1,0, 1,0, -1,-1),
                    new State(0,0, 0,1, 0,-1, -1,1),
                    new State(0,0, 1,0, -1,0, 1,1)};    
        }
    }
    
    class J extends Tetromino {
        public J() {
            cells[0] = new Cell(0, 4, Tetris.J);
            cells[1] = new Cell(0, 3, Tetris.J);
            cells[2] = new Cell(0, 5, Tetris.J);
            cells[3] = new Cell(1, 5, Tetris.J);
            states = new State[]{
                    new State(0,0, 0,-1, 0,1, 1,1),
                    new State(0,0, -1,0, 1,0, 1,-1),
                    new State(0,0, 0,1, 0,-1, -1,-1),
                    new State(0,0, 1,0, -1,0, -1,1 )};
        }
    }
    
    class S extends Tetromino {
        public S() {
            cells[0] = new Cell(0, 4, Tetris.S);
            cells[1] = new Cell(0, 5, Tetris.S);
            cells[2] = new Cell(1, 3, Tetris.S);
            cells[3] = new Cell(1, 4, Tetris.S);
            states = new State[]{
                new State(0,0, 0,1, 1,-1, 1,0 ),
                new State(0,0, -1,0, 1,1, 0,1 )};
        }
    }
    
    class Z extends Tetromino {
        public Z() {
            cells[0] = new Cell(1, 4, Tetris.Z);
            cells[1] = new Cell(0, 3, Tetris.Z);
            cells[2] = new Cell(0, 4, Tetris.Z);
            cells[3] = new Cell(1, 5, Tetris.Z);
            states = new State[]{
                    new State(0,0, -1,-1, -1,0, 0,1 ),
                    new State(0,0, -1,1, 0,1, 1,0 )};
        }
    }
    
    class O extends Tetromino {
        public O() {
            cells[0] = new Cell(0, 4, Tetris.O);
            cells[1] = new Cell(0, 5, Tetris.O);
            cells[2] = new Cell(1, 4, Tetris.O);
            cells[3] = new Cell(1, 5, Tetris.O);
            states = new State[]{
                    new State(0,0, 0,1, 1,0, 1,1 ),
                    new State(0,0, 0,1, 1,0, 1,1 )};
        }
    }
  • 相关阅读:
    Jmeter之http性能测试实战 非GUI模式压测 NON-GUI模式 结果解析TPS——干货(十一)
    UI Recorder 自动化测试 回归原理(九)
    UI Recorder 自动化测试 录制原理(八)
    UI Recorder 自动化测试 整体架构(七)
    UI Recorder 自动化测试 配置项(六)
    UI Recorder 自动化测试 工具栏使用(五)
    UI Recorder 自动化测试 回归测试(四)
    UI Recorder 自动化测试 录制(三)
    UI Recorder 自动化测试工具安装问题疑难杂症解决(二)
    UI Recorder 自动化测试安装教程(一)
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/7220327.html
Copyright © 2011-2022 走看看