这是一个用Java Swing实现的俄罗斯方块游戏,具有经典的游戏机制和图形界面。游戏中,玩家需要旋转和移动不断下落的方块,使其填满一行来消除该行并得分。
该项目适合学习Java GUI编程、游戏开发基础以及面向对象编程(OOP)概念。
功能特性
-
图形界面:
- 使用Java Swing库实现用户界面。
- 提供直观的游戏界面,显示当前下落的方块和游戏得分。
-
游戏逻辑:
- 方块自动下落,玩家可以通过键盘控制方块的移动和旋转。
- 当方块填满一行时,该行会被消除,玩家得分增加。
- 游戏结束时,显示最终得分并停止游戏。
-
控件说明:
- 左右箭头键:移动方块左右。
- 上箭头键:旋转方块(顺时针)。
- 下箭头键:旋转方块(逆时针)。
- 空格键:快速下落方块。
- 'D'键:快速下降一行。
- 'P'键:暂停和继续游戏。
-
扩展性:
- 代码结构清晰,便于扩展和修改,例如添加新的方块形状或改变下落速度。
- 通过调整计时器的延迟,可以轻松改变游戏难度。
技术亮点
-
面向对象编程:
- 使用类和对象封装游戏中的方块形状、游戏逻辑和界面。
- 代码模块化,便于理解和维护。
-
事件驱动编程:
- 使用键盘事件和计时器事件控制游戏流程。
- 实现了对用户输入的实时响应,使游戏更加流畅。
-
Swing库的应用:
- 学习如何使用Swing库创建窗口、绘制图形、处理事件。
- 通过定制化绘制方法,展示不同颜色和形状的方块。
游戏界面
游戏代码(展示部分文件,完整代码可下载资源)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;// Tetris游戏主类,继承自JPanel,并实现ActionListener接口
public class Tetris extends JPanel implements ActionListener {private final int BOARD_WIDTH = 10; // 游戏板宽度(单位:格子)private final int BOARD_HEIGHT = 20; // 游戏板高度(单位:格子)private final int CELL_SIZE = 30; // 每个格子的大小(单位:像素)private final int TIMER_DELAY = 500; // 方块下落的时间间隔(单位:毫秒)private Timer timer; // 控制方块下落的计时器private boolean isFallingFinished = false; // 标记是否方块已经落地private boolean isStarted = false; // 标记游戏是否开始private boolean isPaused = false; // 标记游戏是否暂停private int numLinesRemoved = 0; // 记录消除的行数(即得分)private int currentX = 0; // 当前方块的x坐标private int currentY = 0; // 当前方块的y坐标private Shape currentPiece; // 当前的方块形状private Shape.Tetrominoes[] board; // 存储游戏板上的方块private JLabel statusBar; // 显示得分的状态栏public Tetris(JLabel statusBar) {setFocusable(true);currentPiece = new Shape();timer = new Timer(TIMER_DELAY, this);board = new Shape.Tetrominoes[BOARD_WIDTH * BOARD_HEIGHT];clearBoard();addKeyListener(new TAdapter());this.statusBar = statusBar;}// 启动游戏public void start() {if (isPaused) {return;}isStarted = true;isFallingFinished = false;numLinesRemoved = 0;clearBoard();newPiece();timer.start();}// 暂停游戏private void pause() {if (!isStarted) {return;}isPaused = !isPaused;if (isPaused) {timer.stop();statusBar.setText("暂停");} else {timer.start();statusBar.setText(String.valueOf(numLinesRemoved));}repaint();}@Overridepublic void paintComponent(Graphics g) {super.paintComponent(g);doDrawing(g);}// 绘制游戏界面private void doDrawing(Graphics g) {Dimension size = getSize();int boardTop = (int) size.getHeight() - BOARD_HEIGHT * CELL_SIZE;// 绘制游戏板上的方块for (int i = 0; i < BOARD_HEIGHT; i++) {for (int j = 0; j < BOARD_WIDTH; j++) {Shape.Tetrominoes shape = shapeAt(j, BOARD_HEIGHT - i - 1);if (shape != Shape.Tetrominoes.NoShape) {drawSquare(g, j * CELL_SIZE, boardTop + i * CELL_SIZE, shape);}}}// 绘制当前活动的方块if (currentPiece.getShape() != Shape.Tetrominoes.NoShape) {for (int i = 0; i < 4; i++) {int x = currentX + currentPiece.x(i);int y = currentY - currentPiece.y(i);drawSquare(g, x * CELL_SIZE, boardTop + (BOARD_HEIGHT - y - 1) * CELL_SIZE, currentPiece.getShape());}}}// 方块快速下落到最底部private void dropDown() {int newY = currentY;while (newY > 0) {if (!tryMove(currentPiece, currentX, newY - 1)) {break;}newY--;}pieceDropped();}// 方块下落一行private void oneLineDown() {if (!tryMove(currentPiece, currentX, currentY - 1)) {pieceDropped();}}// 清空游戏板private void clearBoard() {for (int i = 0; i < BOARD_HEIGHT * BOARD_WIDTH; i++) {board[i] = Shape.Tetrominoes.NoShape;}}// 处理方块落地后的逻辑private void pieceDropped() {for (int i = 0; i < 4; i++) {int x = currentX + currentPiece.x(i);int y = currentY - currentPiece.y(i);board[(y * BOARD_WIDTH) + x] = currentPiece.getShape();}removeFullLines();if (!isFallingFinished) {newPiece();}}// 生成新的方块private void newPiece() {currentPiece.setRandomShape();currentX = BOARD_WIDTH / 2;currentY = BOARD_HEIGHT - 1 + currentPiece.minY();if (!tryMove(currentPiece, currentX, currentY)) {currentPiece.setShape(Shape.Tetrominoes.NoShape);timer.stop();isStarted = false;statusBar.setText("游戏结束. 分数: " + numLinesRemoved);}}// 尝试移动方块private boolean tryMove(Shape newPiece, int newX, int newY) {for (int i = 0; i < 4; i++) {int x = newX + newPiece.x(i);int y = newY - newPiece.y(i);if (x < 0 || x >= BOARD_WIDTH || y < 0 || y >= BOARD_HEIGHT) {return false;}if (shapeAt(x, y) != Shape.Tetrominoes.NoShape) {return false;}}currentPiece = newPiece;currentX = newX;currentY = newY;repaint();return true;}// 移除填满的行private void removeFullLines() {int numFullLines = 0;for (int i = BOARD_HEIGHT - 1; i >= 0; i--) {boolean lineIsFull = true;for (int j = 0; j < BOARD_WIDTH; j++) {if (shapeAt(j, i) == Shape.Tetrominoes.NoShape) {lineIsFull = false;break;}}if (lineIsFull) {numFullLines++;for (int k = i; k < BOARD_HEIGHT - 1; k++) {for (int j = 0; j < BOARD_WIDTH; j++) {board[(k * BOARD_WIDTH) + j] = shapeAt(j, k + 1);}}}}if (numFullLines > 0) {numLinesRemoved += numFullLines;statusBar.setText(String.valueOf(numLinesRemoved));isFallingFinished = true;currentPiece.setShape(Shape.Tetrominoes.NoShape);repaint();}}// 绘制单个方块private void drawSquare(Graphics g, int x, int y, Shape.Tetrominoes shape) {Color colors[] = { Color.black, Color.red, Color.green, Color.blue, Color.yellow, Color.magenta, Color.orange, Color.cyan };Color color = colors[shape.ordinal()];g.setColor(color);g.fillRect(x, y, CELL_SIZE, CELL_SIZE);g.setColor(color.brighter());g.drawLine(x, y, x + CELL_SIZE - 1, y);g.drawLine(x, y, x, y + CELL_SIZE - 1);g.setColor(color.darker());g.drawLine(x + 1, y + CELL_SIZE - 1, x + CELL_SIZE - 1, y + CELL_SIZE - 1);g.drawLine(x + CELL_SIZE - 1, y + CELL_SIZE - 1, x + CELL_SIZE - 1, y + 1);}// 获取指定位置的方块形状private Shape.Tetrominoes shapeAt(int x, int y) {return board[(y * BOARD_WIDTH) + x];}@Overridepublic void actionPerformed(ActionEvent e) {if (isFallingFinished) {isFallingFinished = false;newPiece();} else {oneLineDown();}}// 键盘适配器类,用于处理用户输入class TAdapter extends KeyAdapter {@Overridepublic void keyPressed(KeyEvent e) {if (!isStarted || currentPiece.getShape() == Shape.Tetrominoes.NoShape) {return;}int keycode = e.getKeyCode();if (keycode == 'p' || keycode == 'P') {pause();return;}if (isPaused) {return;}switch (keycode) {case KeyEvent.VK_LEFT:tryMove(currentPiece, currentX - 1, currentY);break;case KeyEvent.VK_RIGHT:tryMove(currentPiece, currentX + 1, currentY);break;case KeyEvent.VK_DOWN:tryMove(currentPiece.rotateRight(), currentX, currentY);break;case KeyEvent.VK_UP:tryMove(currentPiece.rotateLeft(), currentX, currentY);break;case KeyEvent.VK_SPACE:dropDown();break;case 'd':case 'D':oneLineDown();break;}}}// 主函数,启动Tetris游戏public static void main(String[] args) {JFrame frame = new JFrame("俄罗斯方块");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setSize(320, 640);frame.setLayout(new BorderLayout());frame.setResizable(false); // 禁止调整窗口大小JLabel statusBar = new JLabel("0");frame.add(statusBar, BorderLayout.SOUTH);Tetris game = new Tetris(statusBar);frame.add(game, BorderLayout.CENTER);frame.setVisible(true);game.start();}
}
源代码下载
https://download.csdn.net/download/qq_35759769/89401357https://download.csdn.net/download/qq_35759769/89401357
结论
这个项目不仅是一个有趣的游戏实现,还涵盖了Java编程中许多重要的概念和技术。通过学习和运行这个项目,您将对Java GUI编程、事件驱动编程和游戏开发有更深入的理解。这个俄罗斯方块游戏是一个很好的入门项目,同时也是进一步学习和扩展的良好基础。