javaoop-day05-TetrisGame

Cell

package com.tetris;

import java.awt.image.BufferedImage;

//格子
public class Cell {
    private int row;
    private int col;
    private BufferedImage image;

    public Cell(int row, int col, BufferedImage image) {
        super();
        this.row = row;
        this.col = col;
        this.image = image;
    }

    public void drop() {
        row++;
    }

    public void moveLeft() {
        col--;
    }

    public void moveRight() {
        col++;
    }

    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 int getRow() {
        return row;
    }

    public void setRow(int row) {this.row = row;}

    public String toString() {
        return row + "," + col;
    }

}





Tertis

package com.tetris;
/**
 * coincide():判断当前方块是否与墙壁上的方块重合。
 * moveLeftAction():尝试将当前方块向左移动一格,如果超出边界或与墙壁上的方块重合,则向右移动一格。
 * outOfBounds():检查当前方块是否超出边界。
 * softDropAction():如果可以下落,则让当前方块下落一格,否则将其固定在墙上,检查并销毁满行,并检查游戏是否结束,然后更新当前方块为下一个方块。
 * hardDropAction():让当前方块尽可能多地向下移动,然后将其固定在墙上,检查并销毁满行,并检查游戏是否结束,然后更新当前方块为下一个方块。
 * destroyLines():检查并销毁满行,更新得分。
 * fullCells(int row):检查指定行是否全部被方块占据。
 * removeLine(int row):移除指定行的方块,将上方的方块下移一行。
 * landToWall():将当前方块固定在墙上。
 * canDrop():检查当前方块是否可以下落。
 * rotateRightAction():尝试将当前方块顺时针旋转90度,如果超出边界或与墙壁上的方块重合,则逆时针旋转90度。
 * rotateLeftAction():尝试将当前方块逆时针旋转90度,如果超出边界或与墙壁上的方块重合,则顺时针旋转90度。
 * startAction():开始游戏,重置游戏状态,初始化当前方块和下一个方块,设置定时器每700毫秒触发一次软下降动作。
 * clearWall():清除墙上的所有方块。
 * pauseAction():暂停游戏,停止定时器。
 * continueAction():继续游戏,重新开始定时器每700毫秒触发一次软下降动作。
 * checkGameOver():检查游戏是否结束,如果墙的最下方有方块,则游戏结束。
 * main(String[] args):游戏主方法,创建游戏窗口和游戏实例,并开始游戏。
 */

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 java.util.Timer;
import java.util.TimerTask;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

//俄罗斯方块类
public class Tetris extends JPanel {
    // 分数
    private int score;
    //行数
    private int lines;
    public static final int ROWS = 20;//行数
    public static final int COLS = 10;//列数
    // 方块墙, 墙是Tetris的组件
    private Cell[][] wall = new Cell[ROWS][COLS];
    // 正在下落的方块
    private Tetromino tetromino;
    //下一个下落的方块
    private Tetromino nextOne;
    // 图片素材的装载
    public static BufferedImage background;
    public static BufferedImage gameOver;
    public static BufferedImage I;
    public static BufferedImage T;
    public static BufferedImage S;
    public static BufferedImage J;
    public static BufferedImage L;
    public static BufferedImage O;
    public static BufferedImage Z;

    // 加载静态的图片资源
    static {
        try {
            I = ImageIO.read(Tetris.class.getClassLoader().getResourceAsStream("I.png"));
            J = ImageIO.read(Tetris.class.getClassLoader().getResourceAsStream("J.png"));
            L = ImageIO.read(Tetris.class.getClassLoader().getResourceAsStream("L.png"));
            O = ImageIO.read(Tetris.class.getClassLoader().getResourceAsStream("O.png"));
            S = ImageIO.read(Tetris.class.getClassLoader().getResourceAsStream("S.png"));
            T = ImageIO.read(Tetris.class.getClassLoader().getResourceAsStream("T.png"));
            Z = ImageIO.read(Tetris.class.getClassLoader().getResourceAsStream("Z.png"));
            background = ImageIO.read(Tetris.class.getClassLoader().getResourceAsStream("background.png"));
            BufferedImage gameover = ImageIO.read(Tetris.class.getClassLoader().getResourceAsStream("gameover.png"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //重绘
    public void paint(Graphics g) {
        g.drawImage(background, 0, 0, null);
        //translate 可以平移绘制坐标系
        g.translate(15, 15);
        paintWall(g);//画墙
        paintTetromino(g);//画正在下落的方块
        paintNextOne(g);//画下一个方块
        paintScore(g);//画分数
        g.translate(-15, -15);
        if (finish) {
            g.drawImage(gameOver, 0, 0, null);
        }
    }

    public static final int FONT_COLOR = 0x667799;
    public static final int FONT_SIZE = 30;//字号

    private void paintScore(Graphics g) {
        int x = 290;
        int y = 162;
        g.setColor(new Color(FONT_COLOR));
        //font 字体
        Font font = g.getFont();//获取当前画笔的默认字体
        //用新字号创建字体
        font = new Font(font.getName(), Font.BOLD, FONT_SIZE);
        g.setFont(font);
        g.drawString("SCORE:" + score, x, y);
        y += 56;
        g.drawString("LINES:" + lines, x, y);
        y += 56;
        String str = "[P]Pause";
        if (pause) {
            str = "[C]Continue";
        }
        if (finish) {
            str = "[S]Start!";
        }
        g.drawString(str, x, y);
    }

    private void paintNextOne(Graphics g) {
        if (nextOne == null) {
            return;
        }
        Cell[] cells = nextOne.cells;
        for (int i = 0; i < cells.length; i++) {
            Cell cell = cells[i];
            int x = CELL_SIZE * (cell.getCol() + 10);
            int y = CELL_SIZE * (cell.getRow() + 1);
            g.drawImage(cell.getImage(), x - 1, y - 1, null);
        }
    }

    private void paintTetromino(Graphics g) {
        //System.out.println(this.tetromino);
        if (tetromino == null) {
            return;
        }
        Cell[] cells = tetromino.cells;
        for (int i = 0; i < cells.length; i++) {
            Cell cell = cells[i];
            int x = CELL_SIZE * cell.getCol();
            int y = CELL_SIZE * cell.getRow();
            g.drawImage(cell.getImage(), x - 1, y - 1, null);
        }
    }

    public static final int CELL_SIZE = 26;

    /* 将wall(二维数组)的内容绘制到面板上
     * 每个格子(迭代)都绘制出来.
     * 如果: 没有方块的地方绘制空白格
     *   有方块(Cell)的地方, 绘制方块的贴图
     */
    private void paintWall(Graphics g) {
        for (int row = 0; row < wall.length; row++) {
            Cell[] line = wall[row];
            for (int col = 0; col < line.length; col++) {
                Cell cell = line[col];
                int x = col * CELL_SIZE;
                int y = row * CELL_SIZE;
                if (cell == null) {
                    g.setColor(new Color(0x0FFFFFF, true));
                    //drawRect 绘制矩形格子
                    g.drawRect(x, y, CELL_SIZE, CELL_SIZE);
                } else {
                    g.drawImage(cell.getImage(), x - 1, y - 1, null);
                }
            }
        }
    }

    // Tetris 类中 添加方法 action() 用于 启动软件
    public void action() {
        startAction();//启动游戏
        KeyListener l = new KeyAdapter() {
            //在按键按下时候执行
            public void keyPressed(KeyEvent e) {
                int key = e.getKeyCode();
                if (finish) {
                    if (key == KeyEvent.VK_S) {
                        startAction();
                        repaint();
                    }
                    return;
                }
                if (pause) {
                    if (key == KeyEvent.VK_C) {
                        continueAction();
                        repaint();
                    }
                    return;
                }
                switch (key) {
                    case KeyEvent.VK_P:
                        pauseAction();
                        break;
                    case KeyEvent.VK_DOWN:
                        softDropAction();
                        break;
                    case KeyEvent.VK_RIGHT:
                        moveRightAction();
                        break;
                    case KeyEvent.VK_LEFT:
                        moveLeftAction();
                        break;
                    case KeyEvent.VK_SPACE:
                        hardDropAction();
                        break;
                    case KeyEvent.VK_UP:
                        rotateRightAction();
                        break;
                    case KeyEvent.VK_Z:
                        rotateLeftAction();
                        break;
                }
                repaint();
            }
        };
        this.addKeyListener(l);//在当前面板上绑定了键盘监听l
        this.requestFocus();//为当前面板请求键盘输入焦点
    }

    // 在Tetris类中添加 向右移动流程控制方法
    public void moveRightAction() {
        tetromino.moveRight();
        if (outOfBounds() || coincide()) {//coincide重合
            tetromino.moveLeft();
        }
    }

    // 检查正在下落的方块是否与墙上的砖块重合
    private boolean coincide() {
        Cell[] cells = tetromino.cells;
        for (int i = 0; i < cells.length; i++) {
            Cell cell = cells[i];
            int row = cell.getRow();
            int col = cell.getCol();
            if (row >= 0 && row < ROWS && col >= 0 && col < COLS &&
                    wall[row][col] != null) {
                //重合
                return true;
            }
        }
        return false;
    }

    public void moveLeftAction() {
        tetromino.moveLeft();
        if (outOfBounds() || coincide()) {
            tetromino.moveRight();
        }
    }

    // Bound 边界, 检查是否出界的算法
    private boolean outOfBounds() {
        Cell[] cells = tetromino.cells;
        for (int i = 0; i < cells.length; i++) {
            Cell cell = cells[i];
            int col = cell.getCol();
            if (col < 0 || col >= COLS) {
                return true;
            }
        }
        return false;
    }

    public void softDropAction() {
        if (canDrop()) {// 能下落吗?
            tetromino.softDrop();
        } else {
            landToWall();// 四格方块着陆到墙上
            destroyLines();// 销毁满行
            checkGameOver();// 检查游戏是否结束
            tetromino = nextOne;
            nextOne = Tetromino.randomOne();
        }
    }

    public void hardDropAction() {
        while (canDrop()) {// 能下落吗?
            tetromino.softDrop();
        }
        landToWall();// 四格方块着陆到墙上
        destroyLines();// 销毁满行
        checkGameOver();// 检查游戏是否结束
        tetromino = nextOne;
        nextOne = Tetromino.randomOne();
    }


    public static final int[] SCORE_TABLE = {0, 1, 10, 50, 100};
    private void destroyLines() {
        int lines = 0;
        for (int row = 0; row < wall.length; row++) {
            if (fullCells(row)) {
                removeLine(row);
                lines++;
            }
        }
        this.lines += lines;
        this.score += SCORE_TABLE[lines];
    }

    private boolean fullCells(int row) {
        Cell[] line = wall[row];
        for (Cell cell : line) {
            if (cell == null) {
                return false;
            }
        }
        return true;
    }

    private void removeLine(int row) {
        for (int i = row; i >= 1; i--) {
            //cp [i-1] -> [i]
            System.arraycopy(wall[i - 1], 0, wall[i], 0, COLS);
        }
        Arrays.fill(wall[0], null);
    }

    private void landToWall() {
        Cell[] cells = tetromino.cells;
        for (Cell cell : cells) {
            int row = cell.getRow();
            int col = cell.getCol();
            wall[row][col] = cell;
        }
    }

    private boolean canDrop() {
        Cell[] cells = tetromino.cells;
        for (int i = 0; i < cells.length; i++) {
            Cell cell = cells[i];
            int row = cell.getRow();
            if (row == ROWS - 1) {
                return false;
            }
        }
        for (Cell cell : cells) {//增强版foreach循环
            int row = cell.getRow();
            int col = cell.getCol();
            if (wall[row + 1][col] != null) {
                return false;
            }
        }
        return true;
    }

    // Tetris 类中的 rotateRightAction() 旋转流程控制
    public void rotateRightAction() {
        tetromino.rotateRight();
        if (outOfBounds() || coincide()) {
            tetromino.rotateLeft();
        }
    }

    public void rotateLeftAction() {
        tetromino.rotateLeft();
        if (outOfBounds() || coincide()) {
            tetromino.rotateRight();
        }
    }

    // 为了配合 定时事件,
    //  还修改了键盘事件监听action()
    //以及界面绘制方法 paint() paintScrore()

    // Tetris 类中 增加2个属性, 和一个Timer实例
    private boolean pause;//暂停
    private boolean finish;//结束
    private Timer timer;//下落定时器

    // 开始流程
    public void startAction() {
        clearWall();
        pause = false;
        finish = false;
        tetromino = Tetromino.randomOne();
        nextOne = Tetromino.randomOne();
        lines = 0;
        score = 0;
        timer = new Timer();
        timer.schedule(new TimerTask() {
            public void run() {
                softDropAction();
                repaint();
            }
        }, 700, 700);
    }

    private void clearWall() {
        for (Cell[] line : wall) {
            Arrays.fill(line, null);
        }
    }

    public void pauseAction() {
        pause = true;
        timer.cancel();//停止定时器上的一切任务!
    }

    public void continueAction() {
        pause = false;
        timer = new Timer();
        timer.schedule(new TimerTask() {
            public void run() {
                softDropAction();
                repaint();
            }
        }, 700, 700);
    }

    private void checkGameOver() {
        if (wall[0][4] != null) {//游戏该结束了!
            finish = true;
            timer.cancel();
            repaint();
        }
    }

    //Tetris 类中的main方法, 用于初始化界面
    public static void main(String[] args) {
        JFrame frame = new JFrame("俄罗斯方块");
        frame.setSize(525, 580);
        Tetris tetris = new Tetris();//继承JPanel
        //Background 背景
        tetris.setBackground(new Color(0xffff00));
        frame.add(tetris);//添加俄罗斯方块游戏到窗口框中
        //Default默认 Close关闭 Operation操作
        //当关闭窗口时候, 将Java软件也结束
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);//会尽快调用paint()
        tetris.action();
    }
}

Teromino

package com.tetris;


import java.util.Arrays;
import java.util.Random;

//四格方块

public abstract class Tetromino {
    protected Cell[] cells = new Cell[4];
    //旋转状态

    protected State[] states;
    //获取旋转状态序号

    protected int index = 10000;

    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;
        }
    }

    //向右转

    public void rotateRight() {
        // 1) 获得当前的轴
        // 2) 获得下个状态的变化数据
        // 3) 利用+法实现数据变化
        //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);
        Cell o = cells[0];//t0=[3,4][3,3][3,5][4,4]
        int row = o.getRow();//3
        int col = o.getCol();//4
        index++;//10001
        //               10001 % 4 = 1
        State s = states[index % states.length];//
        //s = (0,0,-1,0,1,0,0,-1)
        //t1=[3,4][2,4][4,4][3,3]
        cells[1].setRow(row + s.row1);//3+-1 = 2->cells[1].row
        cells[1].setCol(col + s.col1);//4+0 = 4->cells[1].col
        cells[2].setRow(row + s.row2);//3+1 = 4->cells[2].row
        cells[2].setCol(col + s.col2);//4+0 = 4->cells[2].col
        cells[3].setRow(row + s.row3);//3+0 = 3->cells[2].row
        cells[3].setCol(col + s.col3);//4+-1 = 3->cells[2].col
    }

    //向右转

    public void rotateLeft() {
        Cell o = cells[0];//t0=[3,4][3,3][3,5][4,4]
        int row = o.getRow();//3
        int col = o.getCol();//4
        index--;//10000
        State s = states[index % states.length];//
        cells[1].setRow(row + s.row1);//3+-1 = 2->cells[1].row
        cells[1].setCol(col + s.col1);//4+0 = 4->cells[1].col
        cells[2].setRow(row + s.row2);//3+1 = 4->cells[2].row
        cells[2].setCol(col + s.col2);//4+0 = 4->cells[2].col
        cells[3].setRow(row + s.row3);//3+0 = 3->cells[2].row
        cells[3].setCol(col + s.col3);//4+-1 = 3->cells[2].col
    }


    //私有构造器
    private Tetromino() {
    }

    //下落一步
    public void softDrop() {
        for (int i = 0; i < cells.length; i++) {
            cells[i].drop();
        }
    }

    public void moveLeft() {
        for (int i = 0; i < cells.length; i++) {
            cells[i].moveLeft();
        }
    }

    public void moveRight() {
        for (int i = 0; i < cells.length; i++) {
            cells[i].moveRight();
        }
    }

    public String toString() {
        return Arrays.toString(cells);
    }

    //只能通过这个工厂方法创建 4格方块的实例
    public static Tetromino randomOne() {
        Random r = new Random();
        int type = r.nextInt(7);
        switch (type) {
            case 0:
                return new T();//静态方法只能使用静态内部类
            case 1:
                return new S();
            case 2:
                return new Z();
            case 3:
                return new L();
            case 4:
                return new J();
            case 5:
                return new O();
            case 6:
                return new I();
        }
        return null;
    }

    // 利用内部类封装了子类实现的细节
    private static 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[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);
        }
    }

    private static 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)};

        }
    }

    private static 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)};
        }
    }

    private static 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)};
        }
    }

    private static 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)};
        }
    }

    private static 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)};
        }
    }

    private static 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)};
        }
    }
}

  • 16
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值