【每月一个小游戏】俄罗斯方块

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Tetris extends JPanel implements ActionListener {
    private static final long serialVersionUID = 1L;
    private static final int BLOCK_SIZE = 30;
    private static final int BOARD_WIDTH = 10;
    private static final int BOARD_HEIGHT = 20;
    private static final int GAME_SPEED = 500;
    private Timer timer;
    private Block currentBlock;
    private ArrayList<Block> blocks;
    private int[][] board;
    private Random random;

    public Tetris() {
        setPreferredSize(new Dimension(BLOCK_SIZE * BOARD_WIDTH, BLOCK_SIZE * BOARD_HEIGHT));
        setBackground(Color.WHITE);
        timer = new Timer(GAME_SPEED, this);
        random = new Random();
        board = new int[BOARD_HEIGHT][BOARD_WIDTH];
        blocks = new ArrayList<Block>();
        addNewBlock();
        timer.start();
    }

    private void addNewBlock() {
        int type = random.nextInt(7);
        int x = BOARD_WIDTH / 2 - 1;
        int y = 1;
        currentBlock = new Block(type, x, y);
        if (isColliding(currentBlock)) {
            timer.stop();
            JFrame frame = (JFrame) getTopLevelAncestor();
            frame.setTitle("Game Over!");
            return;
        }
        blocks.add(currentBlock);
    }

    private boolean isColliding(Block block) {
        for (Point p : block.getPoints()) {
            int x = block.getX() + p.x;
            int y = block.getY() + p.y;
            if (x < 0 || x >= BOARD_WIDTH || y >= BOARD_HEIGHT || board[y][x] != 0) {
                return true;
            }
        }
        return false;
    }

    private void mergeBlocks() {
        for (Point p : currentBlock.getPoints()) {
            int x = currentBlock.getX() + p.x;
            int y = currentBlock.getY() + p.y;
            board[y][x] = currentBlock.getType() + 1;
        }
        blocks.remove(currentBlock);
    }

    private void clearLines() {
        int lines = 0;
        for (int i = BOARD_HEIGHT - 1; i >= 0; i--) {
            boolean isLineFull = true;
            for (int j = 0; j < BOARD_WIDTH; j++) {
                if (board[i][j] == 0) {
                    isLineFull = false;
                    break;
                }
            }
            if (isLineFull) {
                for (int j = i; j > 0; j--) {
                    System.arraycopy(board[j - 1], 0, board[j], 0, BOARD_WIDTH);
                }
                lines++;
                i++;
            }
        }
        if (lines > 0) {
            JFrame frame = (JFrame) getTopLevelAncestor();
            frame.setTitle(String.format("Tetris - Score: %d", lines));
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        currentBlock.moveDown();
        if (isColliding(currentBlock)) {
            currentBlock.moveUp();
            mergeBlocks();
            addNewBlock();
            clearLines();
        }
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (int i = 0; i < BOARD_HEIGHT; i++) {
            for (int j = 0; j < BOARD_WIDTH; j++) {
                int type = board[i][j];
                if (type > 0) {
                    g.setColor(getBlockColor(type));
                    g.fillRect(j * BLOCK_SIZE, i * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
                    g.setColor(Color.BLACK);
                    g.drawRect(j * BLOCK_SIZE, i * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
                }
            }
        }
        for (Block block : blocks) {
            int type = block.getType() + 1;
            g.setColor(getBlockColor(type));
            for (Point p : block.getPoints()) {
                int x = block.getX() + p.x;
                int y = block.getY() + p.y;
                g.fillRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
                g.setColor(Color.BLACK);
                g.drawRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
            }
        }
    }

    private Color getBlockColor(int type) {
        switch (type) {
            case 1:
                return Color.BLUE;
            case 2:
                return Color.RED;
            case 3:
                return Color.GREEN;
            case 4:
                return Color.YELLOW;
            case 5:
                return Color.ORANGE;
            case 6:
                return Color.PINK;
            case 7:
                return Color.CYAN;
            default:
                return Color.WHITE;
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Tetris");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.add(new Tetris());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private static class Block {
        private int type;
        private int x;
        private int y;
        private Point[] points;

        public Block(int type, int x, int y) {
            this.type = type;
            this.x = x;
            this.y = y;
            this.points = getPointsForType(type);
        }

        public void moveLeft() {
            x--;
        }

        public void moveRight() {
            x++;
        }

        public void moveDown() {
            y++;
        }

        public void moveUp() {
            y--;
        }

        public int getType() {
            return type;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }

        public Point[] getPoints() {
            return points;
        }

        private Point[] getPointsForType(int type) {
            switch (type) {
                case 0:
                    return new Point[]{new Point(0, 0), new Point(1, 0), new Point(0, 1), new Point(1, 1)};
                case 1:
                    return new Point[]{new Point(0, 0), new Point(1, 0), new Point(2, 0), new Point(3, 0)};
                case 2:
                    return new Point[]{new Point(0, 0), new Point(1, 0), new Point(0, 1), new Point(0, 2)};
                case 3:
                    return new Point[]{new Point(0, 0), new Point(1, 0), new Point(1, 1), new Point(2, 1)};
                case 4:
                    return new Point[]{new Point(0, 1), new Point(1, 1), new Point(1, 0), new Point(2, 0)};
                case 5:
                    return new Point[]{new Point(0, 0), new Point(0, 1), new Point(1, 1), new Point(1, 2)};
                case 6:
                    return new Point[]{new Point(1, 0), new Point(1, 1), new Point(0, 1), new Point(0, 2)};
                default:
                    return new Point[0];
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值