Java俄罗斯方块小游戏
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;public class TetrisGame extends JFrame implements ActionListener, KeyListener {private final int BOARD_WIDTH = 10;private final int BOARD_HEIGHT = 20;private final int CELL_SIZE = 30;private Timer timer;private Board board;private Shape currentShape;public TetrisGame() {initUI();}private void initUI() {board = new Board();add(board);timer = new Timer(500, this);timer.start();setTitle("俄罗斯方块游戏");setSize(BOARD_WIDTH * CELL_SIZE, BOARD_HEIGHT * CELL_SIZE);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setLocationRelativeTo(null);addKeyListener(this);setFocusable(true);}public static void main(String[] args) {SwingUtilities.invokeLater(() -> {TetrisGame tetrisGame = new TetrisGame();tetrisGame.setVisible(true);});}@Overridepublic void actionPerformed(ActionEvent e) {// 定时器触发,尝试向下移动当前方块if (board.canMoveDown(currentShape)) {currentShape.moveDown();} else {// 如果无法继续下移,将当前方块加入游戏板并生成新的方块board.addShape(currentShape);currentShape = new Shape();if (!board.canMoveDown(currentShape)) {// 如果新生成的方块无法下移,游戏结束timer.stop();JOptionPane.showMessageDialog(this, "游戏结束!");System.exit(0);}}repaint();}@Overridepublic void keyTyped(KeyEvent e) {}@Overridepublic void keyPressed(KeyEvent e) {// 根据按键事件执行相应操作if (e.getKeyCode() == KeyEvent.VK_LEFT && board.canMoveLeft(currentShape)) {// 左移currentShape.moveLeft();} else if (e.getKeyCode() == KeyEvent.VK_RIGHT && board.canMoveRight(currentShape)) {// 右移currentShape.moveRight();} else if (e.getKeyCode() == KeyEvent.VK_DOWN && board.canMoveDown(currentShape)) {// 下移currentShape.moveDown();} else if (e.getKeyCode() == KeyEvent.VK_SPACE && board.canRotate(currentShape)) {// 旋转currentShape.rotate();}repaint();}@Overridepublic void keyReleased(KeyEvent e) {}// 游戏板class Board extends JPanel {private boolean[][] filledCells;public Board() {filledCells = new boolean[BOARD_HEIGHT][BOARD_WIDTH];currentShape = new Shape();}// 判断是否可以左移public boolean canMoveLeft(Shape shape) {for (Cell cell : shape.getCells()) {if (cell.getX() <= 0 || filledCells[cell.getY()][cell.getX() - 1]) {return false;}}return true;}// 判断是否可以右移public boolean canMoveRight(Shape shape) {for (Cell cell : shape.getCells()) {if (cell.getX() >= BOARD_WIDTH - 1 || filledCells[cell.getY()][cell.getX() + 1]) {return false;}}return true;}// 判断是否可以下移public boolean canMoveDown(Shape shape) {for (Cell cell : shape.getCells()) {if (cell.getY() >= BOARD_HEIGHT - 1 || filledCells[cell.getY() + 1][cell.getX()]) {return false;}}return true;}// 判断是否可以旋转public boolean canRotate(Shape shape) {Shape rotatedShape = shape.getRotatedShape();for (Cell cell : rotatedShape.getCells()) {if (cell.getX() < 0 || cell.getX() >= BOARD_WIDTH || cell.getY() >= BOARD_HEIGHT || filledCells[cell.getY()][cell.getX()]) {return false;}}return true;}// 将方块加入已填充单元格public void addShape(Shape shape) {for (Cell cell : shape.getCells()) {filledCells[cell.getY()][cell.getX()] = true;}clearLines();}// 消除满行private void clearLines() {for (int i = BOARD_HEIGHT - 1; i >= 0; i--) {boolean isFullLine = true;for (int j = 0; j < BOARD_WIDTH; j++) {if (!filledCells[i][j]) {isFullLine = false;break;}}if (isFullLine) {moveLinesDown(i);}}}// 将上方所有行向下移动private void moveLinesDown(int row) {for (int i = row; i > 0; i--) {for (int j = 0; j < BOARD_WIDTH; j++) {filledCells[i][j] = filledCells[i - 1][j];}}}@Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);drawBoard(g);drawShape(g, currentShape);}// 绘制游戏板private void drawBoard(Graphics g) {for (int i = 0; i < BOARD_HEIGHT; i++) {for (int j = 0; j < BOARD_WIDTH; j++) {if (filledCells[i][j]) {g.setColor(Color.BLUE);g.fillRect(j * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE);g.setColor(Color.BLACK);g.drawRect(j * CELL_SIZE, i * CELL_SIZE, CELL_SIZE, CELL_SIZE);}}}}// 绘制方块private void drawShape(Graphics g, Shape shape) {for (Cell cell : shape.getCells()) {g.setColor(Color.RED);g.fillRect(cell.getX() * CELL_SIZE, cell.getY() * CELL_SIZE, CELL_SIZE, CELL_SIZE);g.setColor(Color.BLACK);g.drawRect(cell.getX() * CELL_SIZE, cell.getY() * CELL_SIZE, CELL_SIZE, CELL_SIZE);}}}// 单元格class Cell {private int x;private int y;public Cell(int x, int y) {this.x = x;this.y = y;}public int getX() {return x;}public int getY() {return y;}}// 方块class Shape {private List<Cell> cells;public Shape() {cells = new ArrayList<>();// 初始化形状Random random = new Random();int shapeType = random.nextInt(7); // 0 到 6switch (shapeType) {case 0: // Icells.add(new Cell(3, 0));cells.add(new Cell(3, 1));cells.add(new Cell(3, 2));cells.add(new Cell(3, 3));break;case 1: // Jcells.add(new Cell(4, 0));cells.add(new Cell(4, 1));cells.add(new Cell(4, 2));cells.add(new Cell(3, 2));break;case 2: // Lcells.add(new Cell(3, 0));cells.add(new Cell(3, 1));cells.add(new Cell(3, 2));cells.add(new Cell(4, 2));break;case 3: // Ocells.add(new Cell(4, 0));cells.add(new Cell(4, 1));cells.add(new Cell(3, 0));cells.add(new Cell(3, 1));break;case 4: // Scells.add(new Cell(4, 1));cells.add(new Cell(3, 1));cells.add(new Cell(3, 0));cells.add(new Cell(2, 0));break;case 5: // Tcells.add(new Cell(3, 0));cells.add(new Cell(3, 1));cells.add(new Cell(3, 2));cells.add(new Cell(4, 1));break;case 6: // Zcells.add(new Cell(2, 1));cells.add(new Cell(3, 1));cells.add(new Cell(3, 0));cells.add(new Cell(4, 0));break;}}public List<Cell> getCells() {return cells;}// 左移public void moveLeft() {for (Cell cell : cells) {cell.x--;}}// 右移public void moveRight() {for (Cell cell : cells) {cell.x++;}}// 下移public void moveDown() {for (Cell cell : cells) {cell.y++;}}// 旋转public void rotate() {int centerX = cells.get(1).getX();int centerY = cells.get(1).getY();for (Cell cell : cells) {int x = cell.getX() - centerX;int y = cell.getY() - centerY;cell.x = centerX - y;cell.y = centerY + x;}}// 获取旋转后的形状public Shape getRotatedShape() {Shape rotatedShape = new Shape();rotatedShape.cells.clear();rotatedShape.cells.addAll(this.cells);rotatedShape.rotate();return rotatedShape;}}
}