欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

一、项目概述

运行效果图

1

image-20260404225457095

1.1 应用简介

俄罗斯方块是一款经典的益智消除游戏,玩家需要操控不同形状的方块从顶部落下,通过旋转和移动将方块排列成完整的横行,当一行被填满时即可消除并获得分数。游戏采用简洁直观的操控方式,玩家只需使用方向键或点击按钮即可控制方块的移动和旋转,适合各年龄段玩家。

游戏提供7种标准方块类型,每种方块拥有独特的形状和颜色。随着游戏进行,方块下落速度会逐渐加快,考验玩家的反应能力和空间规划能力。消除的行数越多,获得的分数越高,连续消除多行还可获得额外加分。

1.2 核心功能

功能模块 功能描述 实现方式
方块生成 随机生成7种方块 工厂模式 + 随机算法
方块移动 左右移动、下落、硬降落 状态更新 + 碰撞检测
方块旋转 顺时针旋转90度 矩阵变换
碰撞检测 检测边界和已放置方块 坐标遍历检测
消行逻辑 检测并消除满行 数组操作
计分系统 消行获得分数 状态管理
等级系统 随分数提升等级 动态难度调整
预览功能 显示下一个方块 独立绘制面板

1.3 方块类型

方块 英文标识 颜色 形状 特点
I型 I 青色 ▬▬▬▬ 长条形,适合消四行
O型 O 黄色 ▬▬
▬▬
正方形,无法旋转变形
T型 T 紫色 ▬▬▬
─▬─
T字形,灵活多变
S型 S 绿色 ─▬▬
▬▬─
S形,适合填补空隙
Z型 Z 红色 ▬▬─
─▬▬
Z形,与S型镜像
J型 J 蓝色 ▬─
▬▬▬
J字形,L型镜像
L型 L 橙色 ─▬
▬▬▬
L字形,J型镜像

1.4 技术栈

技术领域 技术选型 版本要求
开发框架 Flutter >= 3.0.0
编程语言 Dart >= 2.17.0
设计规范 Material Design 3 -
状态管理 setState -
目标平台 鸿蒙OS API 21+

1.5 项目结构

lib/
└── main_tetris.dart
    ├── TetrisApp                # 应用入口
    ├── TetrominoType            # 方块类型枚举
    ├── Tetromino                # 方块数据模型
    ├── GamePage                 # 游戏主页面
    ├── BoardPainter             # 游戏板绘制器
    └── NextPiecePainter         # 预览方块绘制器

二、系统架构

2.1 整体架构图

Game Logic

Data Layer

Presentation Layer

游戏主页面

开始界面

游戏界面

暂停界面

结束界面

Tetromino
方块模型

TetrominoType
方块类型

游戏状态
分数/等级/行数

游戏循环
_gameTimer

碰撞检测
_isValidPosition

消行逻辑
_clearLines

方块生成
Tetromino.random

2.2 类图设计

creates

manages

uses

uses

contains

TetrisApp

+Widget build()

GamePage

+Widget build()

_GamePageState

-List<List> board

-Tetromino _currentPiece

-Tetromino _nextPiece

-int _score

-int _level

-int _lines

-int _highScore

-bool _gameStarted

-bool _gameOver

-bool _paused

-Timer _gameTimer

+void _startGame()

+void _drop()

+void _hardDrop()

+void _lockPiece()

+void _clearLines()

+void _moveLeft()

+void _moveRight()

+void _rotate()

+bool _isValidPosition()

Tetromino

+TetrominoType type

+Color color

+List<List> shape

+int x

+int y

+void rotate()

+void rotateBack()

+Tetromino clone()

+factory Tetromino.random()

«enumeration»

TetrominoType

I

O

T

S

Z

J

L

BoardPainter

+List<List> board

+Tetromino currentPiece

+double cellSize

+void paint()

+bool shouldRepaint()

2.3 游戏流程图

点击

碰撞

无碰撞

重新开始

退出

应用启动

显示开始界面

玩家点击

开始游戏

生成当前方块

生成下一个方块

游戏循环

自动下落

方块下移一格

碰撞检测

锁定方块

更新位置

消行检测

有满行?

消除满行

计算分数

生成新方块

游戏结束?

显示结束界面

玩家选择

结束

2.4 消行流程

游戏状态 分数计算 消行检测 锁定方块 游戏循环 游戏状态 分数计算 消行检测 锁定方块 游戏循环 loop [遍历每一行- ] alt [存在满行] 方块无法下移 将方块写入游戏板 检测满行 判断是否全满 移除满行 顶部插入空行 传递消除行数 计算得分 更新分数/行数/等级 生成新方块

三、核心模块设计

3.1 数据模型设计

3.1.1 方块类型枚举 (TetrominoType)
enum TetrominoType {
  I,  // I型方块 - 长条
  O,  // O型方块 - 正方形
  T,  // T型方块 - T字形
  S,  // S型方块 - S形
  Z,  // Z型方块 - Z形
  J,  // J型方块 - J字形
  L,  // L型方块 - L字形
}
3.1.2 方块模型 (Tetromino)
class Tetromino {
  final TetrominoType type;    // 方块类型
  final Color color;           // 方块颜色
  List<List<int>> shape;       // 形状矩阵
  int x;                       // X坐标
  int y;                       // Y坐标

  // 顺时针旋转
  void rotate() {
    final n = shape.length;
    final rotated = List.generate(
      n, 
      (i) => List.generate(n, (j) => shape[n - j - 1][i])
    );
    shape = rotated;
  }

  // 克隆方块
  Tetromino clone() {
    return Tetromino(
      type: type,
      color: color,
      shape: List.generate(shape.length, (i) => List.from(shape[i])),
      x: x,
      y: y,
    );
  }
}
3.1.3 方块形状矩阵

T型

0

1

0

1

1

1

O型

1

1

1

1

I型

0

0

0

0

1

1

1

1

方块 形状矩阵 (4x4)
I [[0,0,0,0],[1,1,1,1],[0,0,0,0],[0,0,0,0]]
O [[1,1],[1,1]]
T [[0,1,0],[1,1,1],[0,0,0]]
S [[0,1,1],[1,1,0],[0,0,0]]
Z [[1,1,0],[0,1,1],[0,0,0]]
J [[1,0,0],[1,1,1],[0,0,0]]
L [[0,0,1],[1,1,1],[0,0,0]]

3.2 页面结构设计

3.2.1 游戏主页面

GamePage

顶部状态栏

游戏区域

侧边面板

底部控制栏

分数

等级

行数

最高分

游戏板 10x20

下一个方块预览

操作说明

左移按钮

下落按钮

旋转按钮

右移按钮

硬降落按钮

暂停按钮

3.2.2 游戏状态流转

点击开始

按P键/点击暂停

继续游戏

方块堆满

重新开始

退出游戏

待开始

游戏中

暂停

游戏结束

3.3 游戏逻辑设计

3.3.1 核心状态变量
class _GamePageState extends State<GamePage> {
  // 游戏板尺寸
  static const int boardWidth = 10;
  static const int boardHeight = 20;
  static const double cellSize = 28;

  // 游戏状态
  List<List<Color?>> _board = [];      // 游戏板数据
  Tetromino? _currentPiece;             // 当前方块
  Tetromino? _nextPiece;                // 下一个方块
  
  // 分数系统
  int _score = 0;                       // 当前分数
  int _level = 1;                       // 当前等级
  int _lines = 0;                       // 消除行数
  int _highScore = 0;                   // 最高分
  
  // 游戏状态标志
  bool _gameStarted = false;            // 游戏是否开始
  bool _gameOver = false;               // 游戏是否结束
  bool _paused = false;                 // 是否暂停
  
  // 定时器
  Timer? _gameTimer;                    // 游戏主循环
  Duration _dropInterval = const Duration(milliseconds: 800);
}
3.3.2 游戏循环逻辑
void _drop() {
  if (_currentPiece == null) return;

  // 尝试下移方块
  final newPiece = _currentPiece!.clone();
  newPiece.y++;

  if (_isValidPosition(newPiece)) {
    // 可以继续下落
    setState(() {
      _currentPiece = newPiece;
    });
  } else {
    // 无法下落,锁定方块
    _lockPiece();
  }
}

void _lockPiece() {
  // 将方块写入游戏板
  for (int i = 0; i < _currentPiece!.shape.length; i++) {
    for (int j = 0; j < _currentPiece!.shape[i].length; j++) {
      if (_currentPiece!.shape[i][j] == 1) {
        final boardY = _currentPiece!.y + i;
        final boardX = _currentPiece!.x + j;
        _board[boardY][boardX] = _currentPiece!.color;
      }
    }
  }
  
  // 消行检测
  _clearLines();
  
  // 生成新方块
  _spawnNewPiece();
}

四、UI设计规范

4.1 配色方案

游戏采用深色赛博朋克风格,营造科技感十足的游戏氛围:

颜色类型 色值 用途
背景色 #1A1A2E 页面背景
面板背景 #16213E 卡片、面板
游戏板背景 #0F0F23 游戏区域
边框色 #0891B2 边框、强调
文字主色 #FFFFFF 主要文字
文字次色 #9CA3AF 次要文字

方块专属颜色:

// I型 - 青色
Colors.cyan

// O型 - 黄色
Colors.yellow

// T型 - 紫色
Colors.purple

// S型 - 绿色
Colors.green

// Z型 - 红色
Colors.red

// J型 - 蓝色
Colors.blue

// L型 - 橙色
Colors.orange

4.2 字体规范

元素 字号 字重 颜色
游戏标题 36px Bold #FFFFFF
分数数值 20px Bold 对应颜色
标签文字 12px Regular #9CA3AF
按钮文字 14px Medium #FFFFFF
操作说明 11px Regular #9CA3AF

4.3 组件规范

4.3.1 游戏界面布局
┌─────────────────────────────────────────────────────────────┐
│   分数: 1500      等级: 3      行数: 25      最高分: 5000   │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────────────────┐    ┌──────────┐                  │
│   │                     │    │ 下一个   │                  │
│   │                     │    │  ┌──┐    │                  │
│   │                     │    │  │██│    │                  │
│   │                     │    │  │██│    │                  │
│   │        ██           │    └──────────┘                  │
│   │        ██           │                                  │
│   │   ██████████        │    ┌──────────┐                  │
│   │        ██████       │    │ 操作说明 │                  │
│   │                     │    │ ← → 移动 │                  │
│   │                     │    │ ↑   旋转 │                  │
│   │                     │    │ ↓   加速 │                  │
│   │                     │    │ 空格 直落│                  │
│   │                     │    │ P   暂停 │                  │
│   └─────────────────────┘    └──────────┘                  │
│                                                             │
│   [←]  [↓]  [↻]  [→]  [⤓]  [⏸]                            │
└─────────────────────────────────────────────────────────────┘
4.3.2 方块绘制效果
┌─────────────┐
│ ▓▓▓▓▓▓▓▓▓▓ │ ← 高光边
│ ▓▓▓▓▓▓▓▓▓▓ │
│ ▓▓▓▓▓▓▓▓▓▓ │
│ ▓▓▓▓▓▓▓▓▓▓ │ ← 阴影边
└─────────────┘
4.3.3 开始界面
┌─────────────────────────────────────────────────┐
│                                                 │
│                  🎮                             │
│                                                 │
│              俄罗斯方块                         │
│               TETRIS                            │
│                                                 │
│         ┌───────────────────┐                   │
│         │       👆          │                   │
│         │  点击屏幕开始游戏  │                   │
│         │   最高分: 5000    │                   │
│         └───────────────────┘                   │
│                                                 │
└─────────────────────────────────────────────────┘

五、核心功能实现

5.1 方块生成

factory Tetromino.random() {
  final types = [
    (TetrominoType.I, Colors.cyan, [
      [0, 0, 0, 0],
      [1, 1, 1, 1],
      [0, 0, 0, 0],
      [0, 0, 0, 0],
    ]),
    // ... 其他方块类型
  ];

  final random = math.Random();
  final selected = types[random.nextInt(types.length)];
  return Tetromino(
    type: selected.$1,
    color: selected.$2,
    shape: List.generate(
      selected.$3.length, 
      (i) => List.from(selected.$3[i])
    ),
  );
}

5.2 方块旋转

void _rotate() {
  if (_currentPiece == null || _gameOver || _paused) return;

  final newPiece = _currentPiece!.clone();
  newPiece.rotate();

  // 基本旋转
  if (_isValidPosition(newPiece)) {
    setState(() => _currentPiece = newPiece);
    return;
  }

  // 墙踢检测 - 尝试左移
  newPiece.x--;
  if (_isValidPosition(newPiece)) {
    setState(() => _currentPiece = newPiece);
    return;
  }

  // 墙踢检测 - 尝试右移
  newPiece.x += 2;
  if (_isValidPosition(newPiece)) {
    setState(() => _currentPiece = newPiece);
  }
}

5.3 碰撞检测

bool _isValidPosition(Tetromino piece) {
  for (int i = 0; i < piece.shape.length; i++) {
    for (int j = 0; j < piece.shape[i].length; j++) {
      if (piece.shape[i][j] == 1) {
        final boardY = piece.y + i;
        final boardX = piece.x + j;

        // 边界检测
        if (boardX < 0 || boardX >= boardWidth || boardY >= boardHeight) {
          return false;
        }

        // 已放置方块检测
        if (boardY >= 0 && _board[boardY][boardX] != null) {
          return false;
        }
      }
    }
  }
  return true;
}

5.4 消行逻辑

void _clearLines() {
  int linesCleared = 0;

  setState(() {
    // 从底部向上遍历
    for (int i = boardHeight - 1; i >= 0; i--) {
      // 检查是否满行
      if (_board[i].every((cell) => cell != null)) {
        // 移除满行
        _board.removeAt(i);
        // 顶部插入空行
        _board.insert(0, List.generate(boardWidth, (j) => null));
        linesCleared++;
        i++; // 重新检查当前行
      }
    }
  });

  if (linesCleared > 0) {
    // 计分:1行100分,2行300分,3行500分,4行800分
    final points = [0, 100, 300, 500, 800];
    setState(() {
      _lines += linesCleared;
      _score += points[linesCleared] * _level;
      
      // 每10行升一级
      final newLevel = (_lines ~/ 10) + 1;
      if (newLevel > _level) {
        _level = newLevel;
        _updateSpeed();
      }
    });
  }
}

5.5 硬降落

void _hardDrop() {
  if (_currentPiece == null) return;

  // 持续下落直到碰撞
  while (true) {
    final newPiece = _currentPiece!.clone();
    newPiece.y++;
    if (_isValidPosition(newPiece)) {
      _currentPiece = newPiece;
    } else {
      break;
    }
  }
  
  // 立即锁定
  _lockPiece();
}

六、游戏机制

6.1 得分系统

消除行数

1行

2行

3行

4行

100 × 等级

300 × 等级

500 × 等级

800 × 等级

消除行数 基础分数 实际得分
1行 100 100 × 等级
2行 300 300 × 等级
3行 500 500 × 等级
4行 800 800 × 等级

6.2 等级系统

等级 所需行数 下落间隔
1 0-9 800ms
2 10-19 720ms
3 20-29 640ms
4 30-39 560ms
5 40-49 480ms
10 90+ 80ms

下落间隔计算公式:

T = max ⁡ ( 100 , 800 − ( L e v e l − 1 ) × 80 ) T = \max(100, 800 - (Level - 1) \times 80) T=max(100,800(Level1)×80)

6.3 墙踢机制

尝试旋转

基本旋转有效?

完成旋转

尝试左移一格

左移后有效?

尝试右移一格

右移后有效?

旋转失败


七、扩展功能规划

7.1 后续版本规划

2024-01-07 2024-01-14 2024-01-21 2024-01-28 2024-02-04 2024-02-11 2024-02-18 2024-02-25 2024-03-03 2024-03-10 2024-03-17 核心游戏 7种方块 消行逻辑 幽灵方块 暂存功能 音效系统 多人对战 排行榜 成就系统 V1.0 基础版本 V1.1 增强版本 V1.2 进阶版本 俄罗斯方块开发计划

7.2 功能扩展建议

7.2.1 幽灵方块

显示方块落点预览:

  • 半透明显示最终位置
  • 帮助玩家精准放置
  • 可开关显示
7.2.2 暂存功能

增加策略深度:

  • 按键暂存当前方块
  • 与暂存区方块交换
  • 每个方块只能暂存一次
7.2.3 成就系统

解锁游戏成就:

  • 首次消行
  • 连续消四行
  • 达到10级
  • 累计消除100行

八、注意事项

8.1 开发注意事项

  1. Timer管理:游戏结束或暂停时及时取消Timer

  2. 碰撞检测:使用克隆对象进行预检测,避免直接修改原对象

  3. 消行逻辑:从底部向上遍历,避免索引错乱

  4. 状态管理:方块位置变化时及时更新UI

8.2 常见问题

问题 原因 解决方案
方块穿透 碰撞检测遗漏 检查边界条件
旋转异常 墙踢逻辑错误 完善墙踢检测
消行错误 索引计算错误 从底部向上遍历
分数异常 重复计分 使用状态标记

8.3 游戏提示

🎮 游戏小贴士 🎮

尽量保持游戏板平整,避免产生空洞。
I型方块留着消四行,得分最高。
快速下落可以争取更多思考时间。
合理使用硬降落快速锁定方块。


九、运行说明

9.1 环境要求

环境 版本要求
Flutter SDK >= 3.0.0
Dart SDK >= 2.17.0
鸿蒙OS API 21+

9.2 运行命令

# 查看可用设备
flutter devices

# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_tetris.dart

# 运行到Web服务器
flutter run -d web-server -t lib/main_tetris.dart --web-port 8080

# 运行到Windows
flutter run -d windows -t lib/main_tetris.dart

# 代码分析
flutter analyze lib/main_tetris.dart

十、总结

俄罗斯方块游戏应用通过经典的玩法机制、精美的视觉效果和富有挑战性的难度递增系统,为玩家提供了一个耐玩有趣的益智体验。游戏采用深色赛博朋克风格,7种标准方块各具特色;核心玩法简单易懂,适合各年龄段玩家;等级系统确保游戏的持续挑战性。

核心功能涵盖完整的游戏循环,包括方块生成、移动旋转、碰撞检测、消行计分和等级提升。游戏中的方块采用矩阵表示,旋转使用矩阵变换实现;消行逻辑从底部向上遍历,确保正确性;分数系统根据消除行数给予不同奖励,鼓励玩家追求高分。

通过本游戏,希望能够为玩家带来经典的游戏体验,在方块堆叠中体验策略规划的乐趣。

**经典玩法,永恒乐趣**

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐