zoukankan      html  css  js  c++  java
  • [苦逼程序员成长之路]2、俄罗斯方块游戏

    这个是学完面向对象之后写的,也是跟着老师写的,跟飞扬小鸟不同的是,写这个的时候,对java的语法结构有了很多的了解,对java有了一定的语感,对java的基础知识和数据类型也有了系统的认识。

    写的时候,首先跟着老师分析了俄罗斯方块的业务需求,然后根据业务需求设计出大致的类和方法,在写游戏的时候,根据具体的需求继续添加设计需要的方法,下面是我自己根据业务需求文档写的程序设计大致结构:

    俄罗斯方块
        对象:
            Cell   //组成俄罗斯方块的基础一个一个小格子
                属性:
                    int row;//格子所在行
                    int col;//格子所在列
                    BufferedImage image;//格子所在位置填充的图片
                方法:
                    /*get set方法*/
                    getRow()
                    getCol()
                    getImage()
                    setRow(row) 
                    setCol(col)
                    setImage(Image)
                    /*格子下落方法*/
                    drop()    
                    /*格子左移*/
                    moveLeft(){
                    /*格子右移*/    
                    moveRight(){
                        
                        
                    
                
            Tetromino         //抽象类,定义4格方块
                属性:
                    Cell[] cells //组成4格方块的格子
                    state    //变形用数组
                    type    //数组列长
                方法:
                    Tetromino tetromino()//工厂方法:生成随机一种4格方块
                    softDrop()//软下落
                    
                    moveLeft()//四格方块左移
                    moveRight()//四格方块右移
                    rotate()//四格方块变形
                    
                    
                    
            (T S J L I Z O 类继承于Tetromino类)    
    
            Tetris //俄罗斯方块类,整个游戏的运行和操作
                属性:tetromino//正在下落的4格方块
                    nextOne//即将进场的4个方块
                    score//分数
                    lines//总共消除的行数
                    wall[][]//游戏场地
                    ROWS//游戏场地的总行数
                    COLS//游戏场地的总列数
                    
                
                方法:    /*四格方块的运动方法*/
                    softDropAction()
                    hardDropAction()
                    moveLeftAction()
                    moveRightAction()
                    /*消除方法 及 消除一行的方法*/
                    destroy()
                    deletLine()
                    /*判断方法*/
                    fullLines()    //判断一行满了没有
                    outOfWall()//判断4格方块出界了没有
                    coincide()//判断4个方块有没有重合
                    isgameOver()//判断游戏结束了没有
                    canDrop()//判断4个方块还能不能下落

    下面就是具体的代码了

    首先是Cell类:

    package com.tarena.tetris;
    
    import java.awt.image.BufferedImage;
    /**
     * 组成俄罗斯方块的格子
     * 
     * @author 
     *
     */
     class Cell {
        /**
         * 格子所在的列、行、图片
         */
        public int col;
        public int row;
        BufferedImage image;
        
        public Cell(int row, int col, BufferedImage image) {
            super();
            this.col = col;
            this.row = row;
            this.image = image;
        }
        public int getCol() {
            return col;
        }
        public void setCol(int col) {
            this.col = col;
        }
        public int getRow() {
            return row;
        }
        public void setRow(int row) {
            this.row = row;
        }
        public BufferedImage getImage() {
            return image;
        }
        public void setImage(BufferedImage image) {
            this.image = image;
        }
        
        //下落
        public void drop(){

    这个是Tetromino类:

    package com.tarena.tetris;
    
    import java.util.Random;
    
    /**
     * 四格方块类
     * 
     * @author 
     * 
     */
    class Tetromino {
        Cell[] cells = new Cell[4];
        int type;// 方块可变换的种类
        int[][] state;// 用于变形的数据
    
        /**
         * 工厂方法,随机生成方块 生成[0,7)的随机数,用t接受,用来决定生成四格方块的类型
         */
        public Tetromino randomOne() {
    
            Random r = new Random();
            int t = r.nextInt(7);
            switch (t) {
            case 0:
                return new I();
            case 1:
                return new J();
            case 2:
                return new L();
            case 3:
                return new O();
            case 4:
                return new S();
            case 5:
                return new Z();
            case 6:
                return new T();
            }
    
            return null;
        }
    
        int ss = 10;// 用语变形取余数循环
    
        /*
         * 变形
         */
        public void rotateRight() {
            ss++;
            Cell o = cells[0];
            int row = o.getRow();
            int col = o.getCol();
            cells[1].setRow(row + state[ss % type][2]);
            cells[1].setCol(col + state[ss % type][3]);
            cells[2].setRow(row + state[ss % type][4]);
            cells[2].setCol(col + state[ss % type][5]);
            cells[3].setRow(row + state[ss % type][6]);
            cells[3].setCol(col + state[ss % type][7]);
        }
    
        public void rotatLeft() {
            ss--;
            Cell o = cells[0];
            int row = o.getRow();
            int col = o.getCol();
            cells[1].setRow(row + state[ss % type][2]);
            cells[1].setCol(col + state[ss % type][3]);
            cells[2].setRow(row + state[ss % type][4]);
            cells[2].setCol(col + state[ss % type][5]);
            cells[3].setRow(row + state[ss % type][6]);
            cells[3].setCol(col + state[ss % type][7]);
    
        }
    
        /*
         * 下落 右移 左移
         */
        public void softDrop() {
            for (Cell cell : cells) {
                cell.drop();
            }
        }
    
        public void moveRight() {
            for (Cell cell : cells) {
                cell.moveRight();
            }
        }
    
        public void moveLeft() {
            for (Cell cell : cells) {
                cell.moveLeft();
            }
        }
    }
    
    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);
            type = 2;
            state = new int[][] { { 0, 0, 0, -1, 0, 1, 0, 2 },
                    { 0, 0, -1, 0, 1, 0, 2, 0 } };
    
        }
    }
    
    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);
            type = 4;
            state = new int[][] { { 0, 0, 0, 1, 0, -1, -1, 0 },
                    { 0, 0, 1, 0, -1, 0, 0, 1 }, { 0, 0, 0, -1, 0, 1, 1, 0 },
                    { 0, 0, -1, 0, 1, 0, 0, -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);
            type = 4;
            state = new int[][] { { 0, 0, 0, 1, 0, -1, -1, -1 },
                    { 0, 0, 1, 0, -1, 0, -1, 1 }, { 0, 0, 0, -1, 0, 1, 1, 1 },
                    { 0, 0, -1, 0, 1, 0, 1, -1 } };
    
        }
    }
    
    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);
    
            type = 4;
            state = new int[][] { { 0, 0, 0, 1, 0, -1, -1, 1 },
                    { 0, 0, 1, 0, -1, 0, 1, 1 }, { 0, 0, 0, -1, 0, 1, 1, -1 },
                    { 0, 0, -1, 0, 1, 0, -1, -1 } };
    
        }
    }
    
    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);
            type = 2;
            state = new int[][] { { 0, 0, 0, 1, 1, 0, 1, 1 },
                    { 0, 0, 0, 1, 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);
            type = 2;
            state = new int[][] { { 0, 0, 0, 1, 1, -1, 1, 0 },
                    { 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);
            type = 2;
            state = new int[][] { { 0, 0, -1, -1, -1, 0, 0, 1 },
                    { 0, 0, -1, 1, 0, 1, 1, 0 } };
    
        }
    }

    最后是游戏类也即Tetris类:

    package com.tarena.tetris;
    
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.awt.image.BufferedImage;
    import java.util.Arrays;
    
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    /**
     * 俄罗斯方块的主体程序
     * 
     * @author 锟铰斤拷
     * 
     */
    @SuppressWarnings("serial")
    public class Tetris extends JPanel {
        /**
         * 各种图片数据
         */
        protected static BufferedImage I;
        protected static BufferedImage J;
        protected static BufferedImage L;
        protected static BufferedImage O;
        protected static BufferedImage S;
        protected static BufferedImage T;
        protected static BufferedImage Z;
        protected static BufferedImage background;
        protected static BufferedImage gameOver;
        private static final int COLS = 10;
        private static final int ROWS = 20;
        /**
         * 消行得分数据
         */
        private static int lines = 0;
        private static int score = 0;
    
        protected Tetromino tetromino = new Tetromino().randomOne();// 下落的方块
        protected Tetromino nextOne = new Tetromino().randomOne();//下一个方块
        private Cell wall[][] = new Cell[ROWS][COLS];//
        /**
         * 游戏状态数据
         */
        private static int state;
        private static final int PLAYING = 0;
        private static final int GAMEOVER = 1;
        private static final int PAUSE = 2;
        private static final String[] State = { "[P]Pause", "[S]Restart",
                "[C]Continue" };
    
        /**
         * 方块下落速度控制数据
         */
        private static int speed = 10;
        private int index = -5;
        private int ss = 0;
    
        static {
    
            try {
                I = ImageIO.read(Tetris.class.getResource("I.png"));
                J = ImageIO.read(Tetris.class.getResource("J.png"));
                L = ImageIO.read(Tetris.class.getResource("L.png"));
                O = ImageIO.read(Tetris.class.getResource("O.png"));
                S = ImageIO.read(Tetris.class.getResource("S.png"));
                T = ImageIO.read(Tetris.class.getResource("T.png"));
                Z = ImageIO.read(Tetris.class.getResource("Z.png"));
                background = ImageIO.read(Tetris.class.getResource("tetris.png"));
                gameOver = ImageIO.read(Tetris.class.getResource("game-over.png"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 定义action方法控制游戏运行
         */
        public void action() {
            /**
             * 按键控制游戏
             */
            KeyListener l = new KeyAdapter() {
                public void keyPressed(KeyEvent e) {
                    int key = e.getKeyCode();
                    /*
                     * 各种按键功能
                     */
                    if (key == KeyEvent.VK_Q) {
                        System.exit(0);
                    }
    //                if (key == KeyEvent.VK_P) {
    //                    state=PAUSE;
    //                    return;
    //                }
    //                if (state == GAMEOVER) {
    //                    if (key == KeyEvent.VK_S) {
    //                        restart();   
    //                    
    //                    }
    //                    
    //                }
                    if (state == PAUSE) {
                        if (key == KeyEvent.VK_C) {
                            state = PLAYING;
                            
                        }else{
                            return;
                        }
                    
                    }
    
                    switch (key) {
                    case KeyEvent.VK_DOWN:
                        softDropAction();
                        break;
                    case KeyEvent.VK_LEFT:
                        moveLeftAction();
                        break;
                    case KeyEvent.VK_RIGHT:
                        moveRightAction();
                        break;
                    case KeyEvent.VK_UP:
                        rotateAction();
                        break;
                    case KeyEvent.VK_SPACE:
                        hardDropAcation();
                        break;
                    case KeyEvent.VK_P:
                        state=PAUSE;
                        break;
                    case KeyEvent.VK_S:
                        if(state==GAMEOVER){
                            restart();
                        }
                        break;
                    
                    }
    
                    repaint();
    
                
                }
    
            };
            
    
            this.addKeyListener(l);
            this.requestFocus();
            while (true) {
                if (speed > 1 && score - ss >= 10) {
                    ss += 10;
                    speed--;
                }
                if (index++ % speed == 0&&state==PLAYING&&!isGameOver()) {
                    softDropAction();
                }
                try {
                    Thread.sleep(100);
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
                
                repaint();
            }
            
    
        }
    
        protected void restart() {
            wall = new Cell[ROWS][COLS];
            tetromino = new Tetromino().randomOne();
            nextOne = new Tetromino().randomOne();
            lines = 0;
            score = 0;
            speed = 10;
            ss = 0;
            index = -5;
            state=PLAYING;
        }
    
        /*
         * 快速下落
         */
        protected void hardDropAcation() {
            while (canDrop()) {
                tetromino.softDrop();
    
            }
            inWall();
            destroyLines();
            if (!isGameOver()) {
    
                tetromino = nextOne;
                nextOne = new Tetromino().randomOne();
    
            }
        }
    
        /*
         * 实现方块的旋转
         */
        protected void rotateAction() {
            tetromino.rotateRight();
            if (outOfWall() || coincide()) {
                tetromino.rotatLeft();
    
            }
    
        }
    
        /*
         * 右移
         */
        protected void moveRightAction() {
            tetromino.moveRight();
            if (outOfWall() || coincide()) {
                tetromino.moveLeft();
    
            }
    
        }
    
        /*
         * 判断方块有没有和墙上的格子重合
         */
        private boolean coincide() {
            Cell[] cells = tetromino.cells;
            for (Cell cell : cells) {
                int row = cell.getRow();
                int col = cell.getCol();
                if (wall[row][col] != null) {
                    return true;
                }
            }
            return false;
        }
    
        /*
         * 左移
         */
        protected void moveLeftAction() {
            tetromino.moveLeft();
            if (outOfWall() || coincide()) {
    
                tetromino.moveRight();
            }
    
        }
    
        /*
         *判断出没出界
         */
        private boolean outOfWall() {
            Cell[] cells = tetromino.cells;
            for (Cell cell : cells) {
                int row = cell.getRow();
                int col = cell.getCol();
                if (row > ROWS - 1 || row < 0 || col > COLS - 1 || col < 0) {
                    return true;
                }
            }
            return false;
        }
    
        /*
         * 缓慢下落
         */
        protected void softDropAction() {
            if (canDrop()) {
                tetromino.softDrop();
            } else {
                inWall();
                destroyLines();
                if (!isGameOver()) {
    
                    tetromino = nextOne;
                    nextOne = new Tetromino().randomOne();
    
                } else {
                    state = GAMEOVER;
                }
            }
    
        }
    
        /*
         * 将方块放到墙上
         */
        private void inWall() {
            Cell[] cells = tetromino.cells;
            for (Cell cell : cells) {
                int row = cell.getRow();
                int col = cell.getCol();
                // BufferedImage image=cell.getImage();
                wall[row][col] = cell;
            }
        }
    
        /*
         * 判断游戏是否结束
         */
        private boolean isGameOver() {
            Cell[] cells = nextOne.cells;
            for (Cell cell : cells) {
                int row = cell.getRow();
                int col = cell.getCol();
                if (wall[row][col] != null) {
                    state=GAMEOVER;
                    return true;
                }
            }
            return false;
        }
    
        /**
         * 判断是否还能下落
         * 
         * @return
         */
        private boolean canDrop() {
            Cell[] cells = tetromino.cells;
            for (Cell cell : cells) {
                int row = cell.getRow();
                int col = cell.getCol();
                if (row >= ROWS - 1 || wall[row + 1][col] != null) {
                    return false;
                }
            }
            return true;
        }
    
        /*
         * 消行 得分
         */
        int[] scores = { 0, 1, 10, 50, 100 };
    
        private void destroyLines() {
            int line = 0;
            for (int row = 0; row < ROWS; row++) {
                if (fullLine(row)) {
                    deleteLine(row);
                    line++;
                }
            }
            lines += line;
            score += scores[line];
    
        }
    
        /*
         * 判断一行是否满了
         */
        private boolean fullLine(int row) {
            for (int i = 0; i < COLS; i++) {
                if (wall[row][i] == null) {
                    return false;
                }
            }
    
            return true;
        }
    
        /*
         * 删除一行
         */
        private void deleteLine(int row) {
            for (int i = row; i > 0; i--) {
                wall[i] = Arrays.copyOf(wall[i - 1], COLS);
            }
            Arrays.fill(wall[0], null);
        }
    
        /**
         * 重写绘图方法
         */
        public void paint(Graphics g) {
            g.drawImage(background, 0, 0, null);//背景图
            g.translate(15, 15);// 换坐标
            paintWall(g);
            paintTetris(g);
            paintNextOne(g);
            paintScores(g);
            paintState(g);
    
        }
    
        /*
         * 绘出游戏所处的状态
         */
        private void paintState(Graphics g) {
    
            String str = State[state];
            g.setColor(new Color(0x667799));
            Font font = g.getFont();
            Font f = new Font(font.getName(), font.getStyle(), 30);
            g.setFont(f);
            
            g.drawString(str, 290, 160 + 56 + 56);
            if (state == GAMEOVER) {
                g.translate(-15, -15);
                g.drawImage(gameOver, 0, 0, null);
            }
            
        }
    
        /*
         * 画出得分
         */
        private void paintScores(Graphics g) {
            String str = "SCORE:" + score;
            g.setColor(new Color(0x667799));
            Font font = g.getFont();
            Font f = new Font(font.getName(), font.getStyle(), 30);
            g.setFont(f);
            g.drawString(str, 290, 160);
    
            str = "LINES:" + lines;
            g.drawString(str, 290, 160 + 56);
        }
    
        /**
         * 画出下一个出场的方块
         * 
         * @param g
         */
        private void paintNextOne(Graphics g) {
            Cell[] cells = nextOne.cells;
            for (Cell cell : cells) {
                int x = (cell.getCol() + 10) * SIZE;
                int y = (cell.getRow() + 1) * SIZE;
                BufferedImage image = cell.getImage();
                g.drawImage(image, x, y, null);
            }
        }
    
        static final int SIZE = 26;
    
        /**
         * 画出正在下落的方块
         * 
         * @param g
         */
        private void paintTetris(Graphics g) {
            Cell[] cells = tetromino.cells;
            for (Cell cell : cells) {
                int x = cell.getCol() * SIZE;
                int y = cell.getRow() * SIZE;
                BufferedImage image = cell.getImage();
                g.drawImage(image, x, y, null);
            }
    
        }
    
        /**
         * 画出墙
         * 
         * @param g
         */
    
        private void paintWall(Graphics g) {
            for (int row = 0; row < ROWS; row++) {
                for (int col = 0; col < COLS; col++) {
    
                    int y = row * SIZE;
                    int x = col * SIZE;
                    g.drawRect(x, y, SIZE, SIZE);
                    if (wall[row][col] != null) {
                        Cell cell = wall[row][col];
                        BufferedImage image = cell.getImage();
                        g.drawImage(image, x, y, null);
                    }
                }
            }
        }
    
        public static void main(String[] args) {
            JFrame frame = new JFrame();
            frame.setSize(525, 550);
            Tetris panel = new Tetris();
            frame.add(panel);
            frame.setLocationRelativeTo(null);
            frame.setUndecorated(true);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
            
            panel.action();
            
            
        }
    
    }

    这一次,知道加注释了,很多地方注释写的不详细,但是因为格式、命名规范很多,就算很久没看了,依然可以很轻松看懂每个方法、每个变量的具体功能,也不在像第一次写飞扬小鸟那样很吃力很生涩,借助于功能分析文档,基本上可以独立完成全部代码,而不用参照老师的代码。

  • 相关阅读:
    js将数字转为千分位/清除千分位
    mybatis中的$和#的区别
    js处理title超长问题
    mybatis错误 Mapped Statements collection does not contain value for
    bootstrap添加多个模态对话框支持
    java.util.Collections.copy()方法注意点
    list通过比较器进行排序
    jquery对radio和checkbox的操作
    c++类简介
    c++ 类
  • 原文地址:https://www.cnblogs.com/djavachen/p/3633072.html
Copyright © 2011-2022 走看看