• 俄罗斯方块


    一.准备工作
    先创建一个新的Java项目命名为“俄罗斯方块”。再在该项目中创建一个文件夹命名为”images”,并将所需的图片素材拖入该文件夹。

    二.代码呈现 
    编写小方块类:
    import java.awt.image.BufferedImage;
     
     
    /**
     * 描述:小方块类
     * 属性:行,列以及单元格的图片
     * 方法: 左移一格,右移一格,下移一格
     */
     
    public class Cell {
        private int row;
        private int col;
        private BufferedImage image;
     
        public Cell() {
        }
     
        public Cell(int row, int col, BufferedImage image) {
            this.row = row;
            this.col = col;
            this.image = image;
        }
     
        public int getRow() {
            return row;
        }
     
        public void setRow(int row) {
            this.row = row;
        }
     
        public int getCol() {
            return col;
        }
     
        public void setCol(int col) {
            this.col = col;
        }
     
        public BufferedImage getImage() {
            return image;
        }
     
        public void setImage(BufferedImage image) {
            this.image = image;
        }
        //左移
        public void left() {
            col--;
        }
        //右移
        public void right() {
            col++;
        }
        //下移
        public void soft() {
            row++;
        }
    }
     

    编写四方格父类:
    /**
     * 描述:四方格父类
     * 属性:Cell[]数组用于创建4个小方块
     * 方法:左移一格,右移一格,下移一格,变形
     */
    public class Tetromino {
        protected Cell[] cells = new Cell[4];
     
        //左移
        public void moveLeft() {
            for (Cell cell : cells) {
                cell.left();
            }
        }
        //右移
        public void moveRight() {
            for (Cell cell : cells) {
                cell.right();
            }
        }
        //下移
        public void sftDrop() {
            for (Cell cell : cells) {
                cell.drop();
            }
        }
        //随机生成四方格
        public static Tetromino randomOne() {
            int num = (int)(Math.random() * 7);
            Tetromino tetromino = null;
            switch (num) {
                case 0 :
                    tetromino = new I();
                    break;
                case 1 :
                    tetromino = new J();
                    break;
                case 2 :
                    tetromino = new L();
                    break;
                case 3 :
                    tetromino = new O();
                    break;
                case 4 :
                    tetromino = new S();
                    break;
                case 5 :
                    tetromino = new T();
                    break;
                case 6 :
                    tetromino = new Z();
                    break;
            }
            return tetromino;
        }
        //编写旋转状态
        protected State[] states;
        //声明旋转次数
        protected int count = 10000;
        /**描述:四方格旋转状态的内部类
         * 属性:记录四方格的相对位置
         */
        class State {
            int row0,col0,row1,col1,row2,col2,row3,col3;
     
            public State(){
     
            }
     
            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;
            }
     
            public int getRow0() {
                return row0;
            }
     
            public void setRow0(int row0) {
                this.row0 = row0;
            }
     
            public int getRow1() {
                return row1;
            }
     
            public void setRow1(int row1) {
                this.row1 = row1;
            }
     
            public int getRow2() {
                return row2;
            }
     
            public void setRow2(int row2) {
                this.row2 = row2;
            }
     
            public int getRow3() {
                return row3;
            }
     
            public void setRow3(int row3) {
                this.row3 = row3;
            }
     
            public int getCol0() {
                return col0;
            }
     
            public void setCol0(int col0) {
                this.col0 = col0;
            }
     
            public int getCol1() {
                return col1;
            }
     
            public void setCol1(int col1) {
                this.col1 = col1;
            }
     
            public int getCol2() {
                return col2;
            }
     
            public void setCol2(int col2) {
                this.col2 = col2;
            }
     
            public int getCol3() {
                return col3;
            }
     
            public void setCol3(int col3) {
                this.col3 = col3;
            }
        }
        //编写顺时针旋转四方格方法
        public void rotateRight() {
            if (states.length == 0) {
                return;
            }
            //旋转次数加1
            count++;
            //获取当前状态
            State s = states[count % states.length];
            Cell cell = cells[0];
            int row = cell.getRow();
            int col = cell.getCol();
            //变形
            cells[1].setRow(row + s.row1);
            cells[1].setCol(col + s.col1);
            cells[2].setRow(row + s.row2);
            cells[2].setCol(col + s.col2);
            cells[3].setRow(row + s.row3);
            cells[3].setCol(col + s.col3);
        }
        //逆时针旋转四方格方法
        public void rotateLeft() {
            //旋转次数加1
            count--;
            //获取当前状态
            State s = states[count % states.length];
            Cell cell = cells[0];
            int row = cell.getRow();
            int col = cell.getCol();
            //变形
            cells[1].setRow(row + s.row1);
            cells[1].setCol(col + s.col1);
            cells[2].setRow(row + s.row2);
            cells[2].setCol(col + s.col2);
            cells[3].setRow(row + s.row3);
            cells[3].setCol(col + s.col3);
        }
        //顺时针旋转
        public void rotateRightAction() {
            Tetromino currentOne = null;
            currentOne.rotateRight();
            //判断是否越界或者重合,否则恢复原来的状态
            if (outOfBounds() || coincide()) {
                currentOne.rotateLeft();
            }
        }
        private boolean coincide() {
            // TODO Auto-generated method stub
            return false;
        }
        private boolean outOfBounds() {
            // TODO Auto-generated method stub
            return false;
        }
        //判断游戏是否结束,结束返回true,继续返回false
        public boolean isGameOver() {
            Cell[] cells = nextOne.cells;
            for (Cell cell : cells) {
                int row = cell.getRow();
                int col = cell.getCol();
                if (wall[row][col] != null) {
                    return true;
                }
            }
            return false;
        }
        //判断当前行是否满,满返回true,没有满返回false
        public boolean isFullLine(int row) {
            Cell[] cells = wall[row];
            for (Cell cell : cells) {
                if (cell == null) {
                    return false;
                }
            }
            return true;
        }
        //创建销行方法
        public void  destroyLine() {
            //统计当前形参行数
            int line = 0;
            Cell[] cells = currentOne.cells;
            for (Cell cell : cells) {
                int row = cell.getRow();
                //判断当前行是否满
                if (isFullLine(row)) {
                    line++;
                    //将消除行以上的方块下落到对应行数
                    for (int i = row; i > 0; i--) {
                        System.arraycopy(wall[i - 1],0,wall[i],0,wall[0].length);
                    }
                    //重新创造第一行
                    wall[0] = new Cell[9];
                }
            }
            //更新分数
            totalScore += scores_pool[line];
            //更新消除行数
            totalLine += line;
        }
        //判断四方格能否下落
        public boolean canDrop() {
            Cell[] cells = currentOne.cells;
            for (Cell cell : cells) {
                int row = cell.getRow();
                int col = cell.getCol();
                //判断能否全部到达底部
                if (row == wall.length - 1) {
                    return false;
                } else if(wall[row + 1][col] != null) { //判断该位置是否有方块
                    return false;
                }
            }
            return true;
        }
        //按键一次四方格下落一个
        public void sortDropAction() {
            //判断能否下落
            if (canDrop()) {
                //当前四方格下落一格
                currentOne.softDrop();
            } else {
                //把四方格嵌入墙中
                landToWall();
                //判断能否销行
                destroyLine();
                //判断游戏是否结束
                if (isGameOver()) {
                    game_state = GAMEOVER;
                } else {
                    //继续生成四方格
                    currentOne = nextOne;
                    nextOne = Tetromino.randomOne();
                }
            }
     
        }
        //把四方格嵌入墙中
        private void landToWall() {
            Cell[] cells = currentOne.cells;
            for (Cell cell : cells) {
                int row = cell.getRow();
                int col = cell.getCol();
                wall[row][col] = cell;
            }
        }
        //瞬间下落
        public void handDropAction() {
            while (canDrop()) {
                currentOne.softDrop();
            }
            //把四方格嵌入墙中
            landToWall();
            //判断能否销行
            destroyLine();
            //判断游戏是否结束
            if (isGameOver()) {
                game_state = GAMEOVER;
            } else {
                //继续生成四方格
                currentOne = nextOne;
                nextOne = Tetromino.randomOne();
            }
        }
        public void start() {
            game_state = PLAYING;
            KeyListener listener = new KeyAdapter() {
                @Override
                public void keyPressed(KeyEvent e) {
                    int code = e.getKeyCode();
                    switch (code) {
                        case KeyEvent.VK_DOWN: //↓
                            sortDropAction(); //下落一格
                            break;
                        case KeyEvent.VK_LEFT://←
                            moveLeftAction(); //左移一格
                            break;
                        case KeyEvent.VK_RIGHT: //→
                            moveRightAction(); //右移一格
                            break;
                        case KeyEvent.VK_UP://↑
                            rotateRightAction();//顺时针旋转
                            break;
                        case KeyEvent.VK_SPACE://空格
                            handDropAction();//瞬间下落
                            break;
                        case KeyEvent.VK_P: //p
                            //判断游戏是否在运行,没有才能暂停
                            if (game_state == PLAYING) {
                                game_state = PAUSE;
                            }
                            break;
                        case KeyEvent.VK_C:
                            //游戏暂停后,才能继续
                            if (game_state == PAUSE) {
                                game_state = PLAYING;
                            }
                            break;
                        case KeyEvent.VK_R:
                            //重新开始游戏,把游戏状态变为正在游戏
                            game_state = PLAYING;
                            //界面清空
                            wall = new Cell[ROW][COL];
                            currentOne = Tetromino.randomOne();
                            nextOne = Tetromino.randomOne();
                            //数据清空
                            totalLine = 0;
                            totalScore = 0;
                            break;
     
                    }
                }
            };
            //把俄罗斯方块窗口设置为焦点
            this.addKeyListener(listener);
            this.requestFocus();
     
            while(true){
                //判断,当前游戏状态在游戏中时,每隔0.5秒下落
                if(game_state == PLAYING){
                    try {
                        Thread.sleep(700);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //判断能否下落
                    if(canDrop()){
                        currentOne.softDrop();
                    }else{
                        //嵌入到墙中
                        landToWall();
                        //判断能否消行
                        destroyLine();
                        //判断游戏是否结束
                        if(isGameOver()){
                            game_state = GAMEOVER;
                        }else{
                            currentOne = nextOne;
                            nextOne = Tetromino.randomOne();
                        }
                    }
                }
                //重新绘制
                repaint();
            }
        }
     
     
    }

    编写俄罗斯方块主类:
    import javax.imageio.ImageIO;
    import javax.swing.*;
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
     
    //俄罗斯方块主类
    public class Tetris extends JPanel {
        static int ROW=18;
        static int COL=9;
        //声明正在下落的方块
        private Tetromino currentOne = Tetromino.randomOne();
        //声明将要下落的方块
        private Tetromino nextOne = Tetromino.randomOne();
        //声明游戏主区域
        private Cell[][] wall = new Cell[ROW][COL];
        //声明单元格像素为48像素
        private static final int CELL_SIZE=48;
        //游戏分数池
        int[] scores_pool = {0, 1, 2, 5, 10};
        //游戏总分
        private int totalScore = 0;
        //游戏消除总行数
        private int totalLine = 0;
        //游戏的状态:游戏中,游戏暂停,游戏结束
        private static final int PLAYING=0;
        private static final int PAUSE=1;
        private static final int GAMEOVER=2;
        //声明变量来存放当前游戏状态
        private int game_state;
        //数组显示当前游戏状态
        String[] show_state= {"P[暂停]","C[继续]","R[重开]"};
        //静态载入图片
        public static BufferedImage I;
        public static BufferedImage J;
        public static BufferedImage L;
        public static BufferedImage O;
        public static BufferedImage S;
        public static BufferedImage T;
        public static BufferedImage Z;
        public static BufferedImage backImage;
     
        static {
            try {
                I = ImageIO.read(new File(pathname:"images/I.png"));
                J = ImageIO.read(new File(pathname:"images/J.png"));
                L = ImageIO.read(new File(pathname:"images/L.png"));
                O = ImageIO.read(new File(pathname:"images/O.png"));
                S = ImageIO.read(new File(pathname:"images/S.png"));
                T = ImageIO.read(new File(pathname:"images/T.png"));
                Z = ImageIO.read(new File(pathname:"images/Z.png"));
                backImage=ImageIO.read(new File(pathname:"images/background.png"));
            } catch (IOException e) {
                e.printStackTrace();
            }
            
        }
        public static void main(String[] args) {
            //创建窗口对象
            JFrame frame = new JFrame(title:"俄罗斯方块");
            //创建游戏窗口(即面板)
            Tetris panel = new Tetris();
            //把面板嵌入到窗口中
            frame.add(panel);
            //设置可见
            frame.setVisible(true);
            //设置窗口尺寸
            frame.setSize(width:810,height:940);
            //设置窗口居中
            frame.setLocationRelativeTo(null);
            //设置窗口关闭时程序中止
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            //游戏逻辑封装在方法中
            panel.start();
        }
        @Override
        public void paint(Graphics g) {
            g.drawImage(backImage,x:0,y:0,observer:null);
            
            //平移坐标轴
            g.translate(x:22, y:15);
            
            //绘制游戏主区域
            paintWall(g);
            
            //绘制正在下落的四方格
            paintCurrentOne(g);
            
            //绘制下一个下落的四方格
            paintNextOne(g);
            
            //绘制游戏得分
            paintScore(g);
            
            //绘制游戏当前状态
            paintState(g);
        }
        //绘制游戏当前状态
        private void paintState(Graphics g) {
            if(game_state==PLAYING) {
                g.drawString(show_state[0],x:500,y:660);
            }else if(game_state==PAUSE) {
                g.drawString(show_state[1],x:500,y:660);
            }else if(game_state==GAMEOVER) {
                g.drawString(show_state[2],x:500,y:660);
                g.setColor(Color.red);
                g.setFont(new Font(Font.SANS_SERIF,Font.BOLD,size:60));
                g.drawString(str:"GAMEOVER!",x:30,y:400);
            }
        }
        
        private void paintNextOne(Graphics g) {
            Cell[] cells=nextOne.cells;
            for(Cell cell:cells) {
                int x=cell.getCol()*CELL_SIZE+370;
                int y=cell.getRow()*CELL_SIZE+25;
                g.drawImage(cell.getImage(),x,y,observer:null);
            }
        }
        private void paintCurrentOne(Graphics g) {
            Cell[] cells=currentOne.cells;
            for(Cell cell:cells) {
                int x=cell.getCol()*CELL_SIZE;
                int y=cell.getRow()*CELL_SIZE;
                g.drawImage(cell.getImage(),x,y,observer:null);
            }
        }
        
        private void paintWall(Graphics g) {
            for(int i=0;i
                for(int j=0;j
                    int x=j*CELL_SIZE;
                    int y=i*CELL_SIZE;
                    Cell cell=wall[i][j];
                    //判断当前单元格是否有小方格,如果无则绘制矩形,否则将小方块嵌到墙中
                    if(cell==null) {
                        g.drawRect(x,y,CELL_SIZE,CELL_SIZE);
                    }else {
                        g.drawImage(cell.getImage(), x, y, observer.null);
                    }
                }
            }
        }
        //判断方块是否出界,出界返回true,没有则返回false
        public boolean outOfBounds() {
            Cell[] cells = currentOne.cells;
            for (Cell cell : cells) {
                int col = cell.getCol();
                int row = cell.getRow();
                if (col < 0 || col > COL - 1 || row < 0 || row > ROW - 1) {
                    return true;
                }
            }
            return false;
        }
        //判断方块是否重合,重合返回true,没有返回false
        public boolean coincide() {
            Cell[] cells = currentOne.cells;
            for (Cell cell : cells) {
                int col = cell.getCol();
                int row = cell.getRow();
                if (wall[row][col] != null) {
                    return true;
                }
            }
            return false;
        }
        //按键←触发左移
        public void moveLeftAction() {
            currentOne.moveLeft();
            //判断是否越界或者重合,如果是则右移恢复原来的状态,不是则左移
            if (outOfBounds() || coincide()) {
                currentOne.moveRight();
            }
        }
        //按键→触发右移
        public void moveRightAction() {
            currentOne.moveRight();
            //判断是否越界或者重合,如果是则左移恢复原来的状态,不是则右移
            if (outOfBounds() || coincide()) {
                currentOne.moveLeft();
            }
        }
     
    }

    分别创建并初始化7种形状:
    public 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[2];
            //相对坐标
            states[0] = new State(0,0,0,-1,0,1,0,2);
            states[1] = new State(0,0,-1,0,1,0,2,0);
        }
    }
    public 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);
            //4种状态
            states = new State[4];
            states[0] = new State(0,0,0,1,0,1,1,1);
            states[1] = new State(0,0,-1,0,1,0,1,-1);
            states[2] = new State(0,0,0,1,0,-1,-1,-1);
            states[3] = new State(0,0,1,0,-1,0,-1,1);
        }
    }
    public 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);
            //4种状态
            states = new State[4];
            //初始化
            states[0] = new State(0,0,0,-1,0,1,1,-1);
            states[1] = new State(0,0,-1,0,1,0,-1,-1);
            states[2] = new State(0,0,0,1,0,-1,-1,1);
            states[3] = new State(0,0,1,0,-1,0,1,1);
        }
    }
    public 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);
            //0种状态
            states = new State[0];
        }
    }
    public 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);
            //2种状态
            states = new State[2];
            //初始化相对位置
            states[0] = new State(0,0,0,1,1,-1,1,0);
            states[1] = new State(0,0,1,0,-1,-1,0,-1);
        }
    }
    public 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);
     
            //4种状态
            states = new State[4];
            //初始化相对坐标
            states[0] = new State(0,0,0,-1,0,1,1,0);
            states[1] = new State(0,0,-1,0,1,0,0,-1);
            states[2] = new State(0,0,0,1,0,-1,-1,0);
            states[3] = new State(0,0,1,0,-1,0,0,1);
        }
    }

    public 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[2];
            //初始化相对位置
            states[0] = new State(0,0,-1,-1,-1,0,0,1);
            states[1] = new State(0,0,-1,1,0,1,1,0);
        }
    }
    三.结果呈现

    文章知识点与官方知识档案匹配,可进一步学习相关知识

  • 相关阅读:
    记录Android 知乎图片选择器Matisse的注意事项
    微信公众号支付/微信内置浏览器微信h5支付报错:当前页面的URL未注册:https:∥xxxxxx!解决方法一看就会
    剑指offer 38:字符串的排列
    人工智能--k近邻算法2-归一化、交叉验证、网格搜索、数据分割方法总结、两案例实现
    31C++编程提高篇----2、类模板原理
    在不使用js在情况下只用css实现瀑布流效果
    小明OJ——字符串移位包含问题
    【校招VIP】前端链表算法之快慢指针题型
    第一章 教育基础(01 教育与教育学的产生与发展)
    ECCV 2022 | 悉尼大学提出:绝对尺度感知,鲁棒,以及可泛化的自监督单目深度估计网络DynaDepth
  • 原文地址:https://blog.csdn.net/2301_76534925/article/details/134450385