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 )};
        }
    }
  • 相关阅读:
    fabric 网络操作中遇到的问题
    springBoot项目启动初始化数据
    行为验证码AJ-Captcha
    RestControllerAdvice注解无效问题
    记录美团一面问题
    关于springMVC
    作业08-集合
    选择排序
    Centos7 使用Minikube搭建Kubernetes集群
    Vscode 配置 Go语言插件
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/7220327.html
Copyright © 2011-2022 走看看