# Tetris **Repository Path**: Erick0412/Tetris ## Basic Information - **Project Name**: Tetris - **Description**: 用C写的俄罗斯方块。 - **Primary Language**: C - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-07-01 - **Last Updated**: 2025-07-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # **C语言俄罗斯方块项目 - 技术学习文档** **版本:** 1.13 **作者:** 小火龙Erick **前言** 本篇技术文档旨在对一个基于C语言实现的控制台版“俄罗斯方块”项目进行深入剖析。该项目不仅是C语言编程能力的综合体现,更是一个学习基本游戏开发原理的绝佳案例。文档将系统地介绍项目的功能、技术选型、核心数据结构与算法,帮助读者理解从静态数据到动态交互式游戏的完整构建过程。 ## 1. 项目功能概述 (Functionality Overview) - **经典游戏玩法**: 完整复刻了俄罗斯方块的核心机制,包括方块的随机生成、下落、旋转、移动以及行消除。 - **图形化控制台界面**: 利用Windows控制台API,实现了包含主游戏区、下一个方块预览、实时分数/等级/速度显示以及操作提示的完整游戏界面。 - **动态难度递增**: 游戏引入了等级系统,当分数累计到一定值时,等级提升,方块下落速度随之加快,增加了游戏的挑战性。 - **高分排行榜**: 游戏能够自动记录并持久化存储排名前10的玩家得分。当玩家创造新纪录时,系统会提示输入姓名并更新排行榜。 - **完善的游戏流程**: 提供了包含欢迎菜单、游戏规则、按键说明、游戏主循环、暂停/继续功能以及游戏结束界面的完整用户体验流程。 ## 2. 技术实现方案 (Technical Implementation) 本项目利用C语言标准库结合Windows平台特有的API,构建了一个功能丰富的控制台应用。 | 依赖头文件 | 主要功能 | | --- | --- | | `stdio.h` | 负责标准输入/输出,如 `printf` 绘制界面,以及文件操作(`fopen`, `fprintf`, `fgets`)用于读写高分榜。 | | `stdlib.h` | 提供关键的通用函数:`rand()`/`srand()` 用于生成随机方块,`system()` 用于执行清屏等系统命令,`atoi()` 用于将字符串转换为整数。 | | `windows.h` | **(核心)** 提供访问Windows控制台API的接口,用于实现图形化效果:
- `SetConsoleCursorPosition`: 定位光标,是我们自定义 `gotoxy()` 函数的基础。
- `SetConsoleTextAttribute`: 设置文本颜色,封装为 `setColor()`。
- `SetConsoleCursorInfo`: 控制光标的显示与隐藏。 | | `conio.h` | **(核心)** 提供非阻塞的键盘输入功能:
- `_kbhit()`: 检测是否有按键,不阻塞程序执行,是游戏实时响应的关键。
- `_getch()`: 直接获取按键码,无需等待回车。 | | `time.h` | 使用 `time()` 获取当前时间作为 `srand()` 的种子,确保随机性。 | - `string.h` | 提供字符串处理函数,如 `strcpy`、`strcmp`、`strlen` 和 `strcspn`,主要用于处理高分榜中的玩家姓名。 | **实现概要**: 本项目通过C语言构建底层逻辑,并调用Windows API来渲染图形、处理颜色和实现实时输入,从而在纯文本的控制台环境中模拟出动态的游戏画面。 ## 3. 核心原理剖析 (Core Principles) ### 3.1 核心数据结构 - **方块形态 (`BLOCK_SHAPES`)**: ```c const int BLOCK_SHAPES[7][4][4][4] = { ... }; ``` 这是一个四维常量数组,是整个游戏的核心数据。它的维度定义如下: - `[7]`: 代表7种不同形状的方块 (I, J, L, O, S, T, Z)。 - `[4]`: 代表每种方块的4个旋转形态。 - `[4][4]`: 代表一个4x4的网格,用于描述单个方块的形态。值为 `1` 表示该位置有实体方块,`0` 表示为空。 这种设计将所有方块的形态数据硬编码到程序中,使得渲染和碰撞检测逻辑变得统一和简化。 - **游戏区域 (`gameBoard`)**: ```c int gameBoard[BOARD_HEIGHT][BOARD_WIDTH]; ``` 一个二维整数数组,是游戏主区域的逻辑表示。数组中的每个元素代表一个格子,`0` 表示空格,非 `0` 值(在此项目中为方块颜色代码)表示该格子已被固定的方块占据。 - **当前方块 (`currentBlock`)**: ```c Block currentBlock; // typedef struct { int x, y, type, rotation; } Block; ``` 一个 `Block` 类型的结构体变量,用于存储当前正在下落的方块的所有状态信息,包括其在 `gameBoard` 上的坐标 `(x, y)`、形状 `type` 以及当前的旋转形态 `rotation`。 ### 3.2 游戏主循环 (`runGame`) 游戏的核心是一个由 `while (!isGameOver)` 控制的主循环。每一轮循环都模拟了游戏世界的一个“时间片”,主要包含以下步骤: 1. **处理输入 (`handleInput`)**: 使用 `_kbhit()` 检查是否有用户输入。如果有,则根据按键(移动、旋转、暂停、退出)更新 `currentBlock` 的状态。 2. **更新逻辑 (`updateGame`)**: 当达到预设的下落时间间隔(由 `speed` 变量控制)时,执行游戏逻辑更新。主要是尝试将 `currentBlock` 向下移动一格。 3. **碰撞检测与固化**: 在 `updateGame` 中,会调用 `checkCollision()` 来判断方块下方是否是边界或已有方块。如果发生碰撞,则调用 `lockBlock()` 将当前方块“固化”到 `gameBoard` 中,然后检查是否有可消除的行 (`clearLines()`),并生成新的方块 (`createNewBlock()`)。 4. **渲染**: 在每次状态更新后(如移动、下落),通过 `eraseBlock()` 和 `drawBlock()` 函数在控制台上擦除旧位置、绘制新位置,从而产生动画效果。 5. **游戏节奏控制 (`Sleep`)**: `Sleep()` 函数用于控制循环的频率,保证游戏平滑运行。 ### 3.3 关键算法解析 - **碰撞检测 (`checkCollision`)**: 这是游戏中最关键的算法之一。它接收一个假定要移动到的位置 `(x, y)` 和形态 `(type, rotation)` 作为参数。算法逻辑如下: 1. 遍历该形态的4x4网格。 2. 对于网格中值为 `1` 的每一个点,计算其在 `gameBoard` 上的绝对坐标。 3. 检查该绝对坐标是否超出了游戏区域的左右下边界,或者是否与 `gameBoard` 中已存在的方块重叠。 4. 只要有任何一个点发生碰撞,函数立即返回 `1` (true)。如果所有点都合法,则返回 `0` (false)。 - **行消除 (`clearLines`)**: 当一个方块被固化后,此函数被调用。 1. 从 `gameBoard` 的最底行开始向上逐行检查。 2. 如果发现某一行所有格子都为非 `0` 值(即满行),则记录消除的行数,并将该行以上的所有行依次向下平移一行。 3. 最顶行被清空为 `0`。 4. 根据消除的行数更新分数和等级。 ### 3.4 高分榜的持久化 (`load/saveHighScores`) 高分榜功能通过文件I/O实现数据持久化。 - **数据格式**: 本项目采用纯文本文件 (`.txt`) 存储高分榜,每条记录占用两行:第一行是玩家姓名,第二行是分数。这种格式易于人类阅读和调试。 - **`loadHighScores()`**: 程序启动时调用。它尝试打开 `tetris_scores.txt` 文件,并使用 `fgets()` 逐行读取姓名和分数,填充到 `highScores` 结构体数组中。 - **`saveHighScores()`**: 当有新纪录产生时调用。它以写入模式 (`"w"`) 打开文件(会覆盖旧内容),然后使用 `fprintf()` 将 `highScores` 数组中的所有记录按格式写回文件。 - **`checkAndSaveHighScore()`**: 游戏结束后调用此函数。它判断当前分数是否能进入排行榜。如果可以,则会绘制一个专门的界面,提示用户输入姓名,然后将新纪录插入到 `highScores` 数组的正确位置,并调用 `saveHighScores()` 保存。 ## 4. 编译与运行指南 (Build & Run) 1. **环境要求**: Windows操作系统,并安装C语言编译环境(如 MinGW 或 Dev-C++)。 2. **保存文件**: 将源代码保存为 `tetris.c`。 3. **编译命令 (使用GCC)**: ```bash gcc tetris.c -o tetris.exe ``` 4. **运行程序**: ```bash .\tetris.exe ``` 首次运行时,`tetris_scores.txt` 文件会自动创建(当产生第一个高分记录时)。