俄罗斯方块案例

代码展示

package main;
 
import utils.SourceUtil;
 
import javax.swing.*;
 
 
/**
 * @author woyin
 * @since 2023/7/10  17:17
 */
public class Test {
    
    
    public static void main(String[] args) {
    
    
        //创建俄罗斯方块界面
        JFrame jFrame = new JFrame("俄罗斯方块");
 
        //规划俄罗斯方块界面设计
        Bockpanel bockpanel = new Bockpanel();
        //添加设计好的界面
        jFrame.add(bockpanel);
 
        //为界面添加Logo
        jFrame.setIconImage(SourceUtil.tetrisLogoImage);
        //设置界面属性,大小
        jFrame.setSize(535, 595);//页面大小
        jFrame.setDefaultCloseOperation(3);//关闭窗口
        jFrame.setLocationRelativeTo(null);//居中
        jFrame.setResizable(false);//固定页面,不可伸缩
        jFrame.setVisible(true);//可视化
 
        //游戏开始
        bockpanel.start();
    }
}
package main;
 
import domain.Blockmodel;
import domain.Cell;
 
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.function.Consumer;
 
 
/**
 * @author woyin
 * @since 2023/7/11  9:40
 */
//自定义监听,实现自由下落
public class KeyActionListener extends KeyAdapter implements ActionListener {
    
    
    //创建Bockpanel属性
    public Bockpanel bockpanel;
    //关卡级别
    protected int level = 1;
    //所得分数
    protected int score = 0;
    //下落时间
    protected int delay = 1000;
    protected Timer timer = new Timer(delay, this);
    //游戏暂定标识符
    private boolean flag = true;
    //游戏暂停时间计算
    protected long preGameTime = 0;
    //记录游戏开始时间
    protected Date startTime = new Date();
    //计数器,计数消的行数
    int lines = 0;
 
    //设置Bockpanel属性值
    public KeyActionListener(Bockpanel bockpanel) {
    
    
        this.bockpanel = bockpanel;
    }
 
    //对键盘进行监听
    @Override
    public void keyPressed(KeyEvent e) {
    
    
        int t = e.getKeyCode();
        switch (t) {
    
    
            //左移
            case KeyEvent.VK_LEFT:
                if (flag) {
    
    
                    moveLeftAction();
                    //刷新屏幕
                    bockpanel.repaint();
                }
                break;
            //右移
            case KeyEvent.VK_RIGHT:
                if (flag) {
    
    
                    moveRinghtAction();
                    //刷新屏幕
                    bockpanel.repaint();
                }
                break;
            //下移
            case KeyEvent.VK_DOWN:
                if (flag) {
    
    
                    moveDownAction();
                    //刷新屏幕
                    bockpanel.repaint();
                }
                break;
            case KeyEvent.VK_UP:
                if (flag) {
    
    
                    //判断方块是否在第一行
                    if (canStartRote()) {
    
    
                        //左旋
                        bockpanel.currentOne.moveLeftRote();
                        //判断是否能够左旋
                        if (canRote()) {
    
    
                            //右旋
                            bockpanel.currentOne.moveRightRote();
                        }
                        //刷新屏幕
                        bockpanel.repaint();
                    }
                }
                break;
            //暂停游戏
            case KeyEvent.VK_ENTER:
                if (flag) {
    
    
                    //游戏停止
                    timer.stop();
                    //获取停止时间
                    Date stopTime = new Date();
                    //计算游戏开始到暂停的时间
                    preGameTime += stopTime.getTime() - startTime.getTime();
                    //改变状态
                    flag = false;
                } else {
    
    
                    //游戏开始
                    timer.start();
                    //记录游戏开始时间
                    startTime = new Date();
                    //改变状态
                    flag = true;
                }
                break;
        }
    }
 
    //判断是否能够左旋
    private boolean canRote() {
    
    
        for (Cell cell : bockpanel.currentOne.cell) {
    
    
            //判断左旋后是否越界
            if (cell.getRow() < 0 || cell.getRow() > 19 || cell.getCol() < 0 || cell.getCol() > 9) {
    
    
                return true;
            }
            //判断左旋后所在单元格是否有俄罗斯方块
            if (bockpanel.wall[cell.getRow()][cell.getCol()] != null) {
    
    
                return true;
            }
        }
        return false;
    }
 
    //判断方块是否在第一行,第一行不能旋转
    private boolean canStartRote() {
    
    
        for (Cell cell : bockpanel.currentOne.cell) {
    
    
            //判断方格
            if (cell.getRow() <= 0) {
    
    
                return false;
            }
        }
        return true;
    }
 
    //下移
    private void moveDownAction() {
    
    
        //判断是否能够下移
        if (ifcandown()) {
    
    
            bockpanel.currentOne.movedown();
        }
    }
 
    //右移
    private void moveRinghtAction() {
    
    
        //判断能否右移
        if (canRight()) {
    
    
            bockpanel.currentOne.moveright();
        }
    }
 
    //能否右移判断
    private boolean canRight() {
    
    
        for (Cell cell : bockpanel.currentOne.cell) {
    
    
            //判断获取当前俄罗斯方块行数是否已经到边界
            if (cell.getCol() == 9) {
    
    
                return false;
                //判断获取当前俄罗斯方块行数右方是否有俄罗斯方块
            } else if (bockpanel.wall[cell.getRow()][cell.getCol() + 1] != null) {
    
    
                return false;
            }
        }
        return true;
    }
 
    //能否左移
    private void moveLeftAction() {
    
    
        //判断能否左移
        if (canLefy()) {
    
    
            bockpanel.currentOne.moveleft();
        }
    }
 
    //能否左移判断
    private boolean canLefy() {
    
    
        for (Cell cell : bockpanel.currentOne.cell) {
    
    
            //判断获取当前俄罗斯方块行数是否已经到边界
            if (cell.getCol() == 0) {
    
    
                return false;
                //判断获取当前俄罗斯方块行数左方是否有俄罗斯方块
            } else if (bockpanel.wall[cell.getRow()][cell.getCol() - 1] != null) {
    
    
                return false;
            }
        }
        return true;
    }
 
    //俄罗斯方块下落逻辑
    @Override
    public void actionPerformed(ActionEvent e) {
    
    
        //判断是否能够下落
        if (ifcandown()) {
    
    
            //俄罗斯方块下落一格
            bockpanel.currentOne.movedown();
        } else {
    
    
            //判断游戏是否结束
            if (ifGameOver()) {
    
    
                //游戏结束
                timer.stop();
                //设置再来一次窗口
                int op = JOptionPane.showConfirmDialog(null, "Game Over! 再来一局");
                //判断是否再次游戏
                if (op == JOptionPane.YES_OPTION) {
    
    
                    //清空棋盘
                    bockpanel.wall = new Cell[20][10];
                    //重新开始
                    timer.restart();
                    //清空时间
                    preGameTime = 0;
                    startTime = new Date();
                } else if (op == JOptionPane.NO_OPTION) {
    
    
                    //退出系统
                    System.exit(0);
                }
            } else {
    
    
                //将棋子位子录入棋盘
                lanToWall();
                //消除棋子堆满的一行
                destroyLine();
                //将当前俄罗斯方块替换成下一个俄罗斯方块
                bockpanel.currentOne = bockpanel.NextOne;
                //重新获取下一个俄罗斯方块
                bockpanel.NextOne = Blockmodel.randomOne();
            }
        }
        //刷新页面
        bockpanel.repaint();
    }
 
    //将棋子位子录入棋盘
    private void lanToWall() {
    
    
        //遍历棋子
        for (Cell cell : bockpanel.currentOne.cell) {
    
    
            //棋子信息录入棋盘
            bockpanel.wall[cell.getRow()][cell.getCol()] = cell;
        }
    }
 
    //消除棋子堆满的一行
    private void destroyLine() {
    
    
        //创建数组,用来储存要消除的行
        ArrayList<Integer> rowList = new ArrayList<>();
        //遍历当前俄罗斯方块
        for (Cell cell : bockpanel.currentOne.cell) {
    
    
            //判断一行是否堆满
            if (isFullLine(cell.getRow())) {
    
    
                rowList.add(cell.getRow());
            }
        }
        //对集合进行排序
        Collections.sort(rowList);
        rowList.forEach(integer -> {
    
    
            //消除的行数加一
            lines++;
            //将消除的一行信息清空
            bockpanel.wall[integer] = new Cell[10];
            //将消除行的上面行移下来
            int i = integer;
            for (; i > 0; i--) {
    
    
                //将上一行的信息移到下一行
                System.arraycopy(bockpanel.wall[i - 1], 0, bockpanel.wall[i], 0, 10);
            }
            //补充第一行的方格
            bockpanel.wall[0] = new Cell[10];
            score = 10 * lines;
            if (score == 10 * level) {
    
    
                level++;
                delay -= 10;
                if (delay >= 0) {
    
    
                    timer.setDelay(delay);
                }
            }
        });
    }
 
    //判断一行是否堆满
    private boolean isFullLine(int row) {
    
    
        //获取当前俄罗斯方块行数的所有列数
        Cell[] wall = bockpanel.wall[row];
        for (Cell cell : wall) {
    
    
            //判断这一行是否堆满
            if (cell == null) {
    
    
                return false;
            }
        }
        return true;
    }
 
    //判断游戏是否结束
    private boolean ifGameOver() {
    
    
        for (Cell cell : bockpanel.currentOne.cell) {
    
    
            //获取当前俄罗斯方块行数是否出界
            if (cell.getRow() <= 0) {
    
    
                return true;
            }
        }
        return false;
    }
 
    //判断游戏是否结束
    private boolean ifcandown() {
    
    
        for (Cell cell : bockpanel.currentOne.cell) {
    
    
            //判断获取当前俄罗斯方块行数是否已经到底
            if (cell.getRow() == 19) {
    
    
                return false;
                //判断获取当前俄罗斯方块行数下方是否有俄罗斯方块
            } else if (bockpanel.wall[cell.getRow() + 1][cell.getCol()] != null) {
    
    
                return false;
            }
        }
        return true;
    }
 
}
package main;
 
import domain.Blockmodel;
import domain.Cell;
import utils.SourceUtil;
 
import javax.swing.*;
import java.awt.*;
import java.text.SimpleDateFormat;
import java.util.Date;
 
/**
 * @author woyin
 * @since 2023/7/10  17:22
 */
//创建单独画布类,满足业务的需求
public class Bockpanel extends JPanel {
    
    
    //设计20*10的网状格子
    public Cell[][] wall = new Cell[20][10];
    //每个网状格子的长宽为26
    private static final int CELL_SIZE = 26;
    //创建当前方块
    public Blockmodel currentOne = Blockmodel.randomOne();
    //创建下一个方块
    public Blockmodel NextOne = Blockmodel.randomOne();
    //实例化KeyActionListener
    KeyActionListener keyActionListener = new KeyActionListener(this);
 
    //规划游戏界面
    @Override
    public void paint(Graphics g) {
    
    
        //为界面添加背景图片
        g.drawImage(SourceUtil.backgroundImage, 0, 0, null);
        //画好游戏进行的网状格子
        paintWall(g);
        //补充右侧信息
        paintGameInfo(g);
 
        //展示当前要移动的方块
        paintCurrentOne(g);
        //展示下一个要移动的方块
        paintNextOne(g);
    }
 
    private void paintGameInfo(Graphics g) {
    
    
        //设置字体属性
        Font font = new Font("楷体", Font.CENTER_BASELINE, 22);
        g.setFont(font);
        g.setColor(Color.magenta);
        //显示设置的字体
        g.drawString("关 卡:" + keyActionListener.level, 300, 175);
        g.drawString("分 数:" + keyActionListener.score, 300, 235);
        //创建游戏结束时间
        Date now = new Date();
        //整个游戏时间
        long l = now.getTime() - keyActionListener.startTime.getTime() + keyActionListener.preGameTime;
        //格式化时间
        Date date = new Date(l);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("mm分钟ss秒");
        String gameTime = simpleDateFormat.format(date);
        //显示游戏时间
        g.drawString("时 间:" + gameTime, 300, 290);
    }
 
    //画出游戏进行格子
    private void paintWall(Graphics g) {
    
    
        for (int i = 0; i < 20; i++) {
    
    
            for (int j = 0; j < 10; j++) {
    
    
                Cell cell = wall[i][j];
                //判断当前单元格是否为俄罗斯方块
                if (cell == null) {
    
    
                    g.drawRect(j * CELL_SIZE + 15, i * CELL_SIZE + 15, CELL_SIZE, CELL_SIZE);
                } else {
    
    
                    g.drawImage(cell.getImage(), j * CELL_SIZE + 15, i * CELL_SIZE + 15, null);
                }
            }
        }
    }
 
    //画出当前要移动的方块的位置
    private void paintNextOne(Graphics g) {
    
    
        Cell[] cells = NextOne.cell;
        for (Cell cell : cells) {
    
    
            g.drawImage(cell.getImage(), cell.getCol() * 26 + 280, cell.getRow() * 26 + 40, null);
        }
    }
 
    //画出下一个要移动的方块的位置
    private void paintCurrentOne(Graphics g) {
    
    
        Cell[] cells = currentOne.cell;
        for (Cell cell : cells) {
    
    
            g.drawImage(cell.getImage(), cell.getCol() * 26 + 15, cell.getRow() * 26 + 15, null);
        }
    }
 
    public void start() {
    
    
        //为Bockpanel添加键盘监听
        this.addKeyListener(keyActionListener);
        //为KeyActionListener类设置bockpanel值
        //打开界面集中鼠标
        this.requestFocus();
        //下落时间
        Timer timer = keyActionListener.timer;
        //启动游戏
        timer.start();
    }
}
 

这一段代码放在main包下,一共有三个类

package utils;
 
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
 
/**
 * @author woyin
 * @since 2023/7/10  14:57
 */
public class SourceUtil {
    
    
    public static BufferedImage iImage;
    public static BufferedImage jImage;
    public static BufferedImage lImage;
    public static BufferedImage oImage;
    public static BufferedImage sImage;
    public static BufferedImage tImage;
    public static BufferedImage zImage;
    public static BufferedImage backgroundImage;
    public static BufferedImage tetrisLogoImage;
 
    /**
     * 静态代码块,加载一次静态资源
     */
    static {
    
    
/**
 * ImageIO.read()方法可以读取项目下的静态资源文件
 */
        try {
    
    
            iImage = ImageIO.read(SourceUtil.class.getResource("../image/I.png"));
            jImage = ImageIO.read(SourceUtil.class.getResource("../image/J.png"));
            lImage = ImageIO.read(SourceUtil.class.getResource("../image/L.png"));
            oImage = ImageIO.read(SourceUtil.class.getResource("../image/O.png"));
            sImage = ImageIO.read(SourceUtil.class.getResource("../image/S.png"));
            tImage = ImageIO.read(SourceUtil.class.getResource("../image/T.png"));
            zImage = ImageIO.read(SourceUtil.class.getResource("../image/Z.png"));
            backgroundImage = ImageIO.read(SourceUtil.class.getResource("../image/background.png"));
            tetrisLogoImage = ImageIO.read(SourceUtil.class.getResource("../image/tetrisLogo.png"));
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }
}

这一段代码放在utils包下,只有一个类

package domain;
 
import java.util.Random;
 
/**
 * @author woyin
 * @since 2023/7/10  14:41
 */
//方块的抽象父类
public class Blockmodel {
    
    
    //创建方块数组,用来存储方块的七种形状的单元格
    public Cell[] cell = new Cell[4];
    //变形数组
    public State[] states;
 
    //左移
    public void moveleft() {
    
    
        for (Cell cel : cell) {
    
    
            cel.left();
        }
    }
 
    //右移
    public void moveright() {
    
    
        for (Cell cel : cell) {
    
    
            cel.right();
        }
    }
 
    //下移
    public void movedown() {
    
    
        for (Cell cel : cell) {
    
    
            cel.down();
        }
    }
 
    public int count;
 
    //左旋转
    public void moveLeftRote() {
    
    
        if (this instanceof O) {
    
    
            return;
        }
        if (count == 0) {
    
    
            count = 4;
        }
        count--;
        State state = states[count % states.length];
        cell[1].setRow(cell[0].getRow() + state.row1);
        cell[1].setCol(cell[0].getCol() + state.col1);
        cell[2].setRow(cell[0].getRow() + state.row2);
        cell[2].setCol(cell[0].getCol() + state.col2);
        cell[3].setRow(cell[0].getRow() + state.row3);
        cell[3].setCol(cell[0].getCol() + state.col3);
    }
 
    //右旋转
    public void moveRightRote() {
    
    
        if (this instanceof O) {
    
    
            return;
        }
        if (count == 4) {
    
    
            count = 0;
        }
        count++;
        State state = states[count % states.length];
        cell[1].setRow(cell[0].getRow() + state.row1);
        cell[1].setCol(cell[0].getCol() + state.col1);
        cell[2].setRow(cell[0].getRow() + state.row2);
        cell[2].setCol(cell[0].getCol() + state.col2);
        cell[3].setRow(cell[0].getRow() + state.row3);
        cell[3].setCol(cell[0].getCol() + state.col3);
    }
 
    //随机生成七种方块之一
    public static Blockmodel randomOne() {
    
    
        Blockmodel b = new Blockmodel();
        Random random = new Random();
        //每一个字对应一种方块形状
        int t = random.nextInt(6);
        switch (t) {
    
    
            case 0:
                b = new I();
                break;
            case 1:
                b = new J();
                break;
            case 2:
                b = new Z();
                break;
            case 3:
                b = new O();
                break;
            case 4:
                b = new S();
                break;
            case 5:
                b = new T();
                break;
        }
        return b;
    }
}
package domain;
 
import java.awt.image.BufferedImage;
 
/**
 * @author woyin
 * @since 2023/7/10  14:33
 */
//单元格类,组成俄罗斯方块的基本单位
public class Cell {
    
    
    //行
    private int row;
    //列
    private int col;
    //单元格所存存储的颜色
    private BufferedImage image;
 
    public Cell() {
    
    
 
    }
 
    public Cell(int col, int row, 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 down() {
    
    
        row++;
    }
}
package domain;
 
import utils.SourceUtil;
 
/**
 * @author woyin
 * @since 2023/7/10  15:07
 */
public class I extends Blockmodel {
    
    
    //对I方块进行初始化
    public I() {
    
    
        cell[0] = new Cell(4, 0, SourceUtil.iImage);
        cell[1] = new Cell(3, 0, SourceUtil.iImage);
        cell[2] = new Cell(5, 0, SourceUtil.iImage);
        cell[3] = new Cell(6, 0, SourceUtil.iImage);
        //储存方块其它形状
        super.states = new State[2];
        states[0] = new State(0, -1, 0, 1, 0, 2);
        states[1] = new State(1, 0, -1, 0, -2, 0);
    }
}
 
package domain;
 
import utils.SourceUtil;
 
/**
 * @author woyin
 * @since 2023/7/10  15:19
 */
public class J extends Blockmodel {
    
    
    //对J方块进行初始化
    public J() {
    
    
        cell[0] = new Cell(4, 0, SourceUtil.jImage);
        cell[1] = new Cell(3, 0, SourceUtil.jImage);
        cell[2] = new Cell(5, 0, SourceUtil.jImage);
        cell[3] = new Cell(3, 1, SourceUtil.jImage);
        //储存方块其它形状
        super.states = new State[4];
        states[0] = new State(0, -1, 0, 1, 1, 1);
        states[1] = new State(-1, 0, 1, 0, 1, -1);
        states[2] = new State(0, 1, 0, -1, -1, -1);
        states[3] = new State(1, 0, -1, 0, -1, 1);
    }
}
package domain;
 
import utils.SourceUtil;
 
/**
 * @author woyin
 * @since 2023/7/10  15:28
 */
public class O extends Blockmodel {
    
    
    //对O方块进行初始化
    public O() {
    
    
        cell[0] = new Cell(4, 0, SourceUtil.oImage);
        cell[1] = new Cell(5, 0, SourceUtil.oImage);
        cell[2] = new Cell(4, 1, SourceUtil.oImage);
        cell[3] = new Cell(5, 1, SourceUtil.oImage);
    }
}
package domain;
 
import utils.SourceUtil;
 
/**
 * @author woyin
 * @since 2023/7/10  15:25
 */
public class S extends Blockmodel {
    
    
    //对S方块进行初始化
    public S() {
    
    
        cell[0] = new Cell(4, 1, SourceUtil.sImage);
        cell[1] = new Cell(3, 0, SourceUtil.sImage);
        cell[2] = new Cell(4, 0, SourceUtil.sImage);
        cell[3] = new Cell(5, 1, SourceUtil.sImage);
        //储存方块其它形状
        super.states = new State[4];
        states[0] = new State(0, -1, 0, 1, 1, 1);
        states[1] = new State(-1, 0, 1, 0, 1, -1);
        states[2] = new State(0, 1, 0, -1, -1, -1);
        states[3] = new State(1, 0, -1, 0, -1, 1);
    }
}
package domain;
 
/**
 * @author woyin
 * @since 2023/7/13  10:57
 */
public class State {
    
    
    int row1, col1;
    int row2, col2;
    int row3, col3;
 
    public State() {
    
    
    }
 
    public State(int row1, int col1, int row2, int col2, int row3, int col3) {
    
    
        this.row1 = row1;
        this.col1 = col1;
        this.row2 = row2;
        this.col2 = col2;
        this.row3 = row3;
        this.col3 = col3;
    }
}
package domain;
 
import utils.SourceUtil;
 
/**
 * @author woyin
 * @since 2023/7/10  15:17
 */
public class T extends Blockmodel {
    
    
    //对T方块进行初始化
    public T() {
    
    
        cell[0] = new Cell(4, 0, SourceUtil.tImage);
        cell[1] = new Cell(3, 0, SourceUtil.tImage);
        cell[2] = new Cell(5, 0, SourceUtil.tImage);
        cell[3] = new Cell(4, 1, SourceUtil.tImage);
        //储存方块其它形状
        super.states = new State[4];
        states[0] = new State(0, -1, 0, 1, 1, 1);
        states[1] = new State(-1, 0, 1, 0, 1, -1);
        states[2] = new State(0, 1, 0, -1, -1, -1);
        states[3] = new State(1, 0, -1, 0, -1, 1);
    }
}
 
package domain;
 
import utils.SourceUtil;
 
/**
 * @author woyin
 * @since 2023/7/10  15:22
 */
public class Z extends Blockmodel {
    
    
    //对Z方块进行初始化
    public Z() {
    
    
        cell[0] = new Cell(4, 0, SourceUtil.zImage);
        cell[1] = new Cell(5, 0, SourceUtil.zImage);
        cell[2] = new Cell(3, 1, SourceUtil.zImage);
        cell[3] = new Cell(4, 1, SourceUtil.zImage);
        //储存方块其它形状
        super.states = new State[4];
        states[0] = new State(0, -1, 0, 1, 1, 1);
        states[1] = new State(-1, 0, 1, 0, 1, -1);
        states[2] = new State(0, 1, 0, -1, -1, -1);
        states[3] = new State(1, 0, -1, 0, -1, 1);
    }
}

这一段代码放在domain,y一共有9各类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/2201_75506216/article/details/131946078