C++实现俄罗斯方块时如何完成方块旋转与碰撞检测

来源:Golang编程网作者:北京SEO公司头衔:草根站长
导读:本期聚焦于小伙伴创作的《C++实现俄罗斯方块时如何完成方块旋转与碰撞检测》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++实现俄罗斯方块时如何完成方块旋转与碰撞检测》有用,将其分享出去将是对创作者最好的鼓励。

用C++实现俄罗斯方块时,方块旋转和碰撞检测是保证游戏正常运行的核心逻辑。方块旋转需要定义不同形状的所有旋转状态,碰撞检测则需要判断方块移动或旋转后的位置是否超出边界或者与已落下的方块重叠。

C++实现俄罗斯方块时如何完成方块旋转与碰撞检测

方块的数据结构设计

首先需要定义方块的基础数据结构,我们可以用二维数组表示方块的每个旋转状态,用坐标记录当前方块的左上角位置。以下是基础的结构定义:

// 定义方块的形状,每个元素是一个旋转状态,每个旋转状态是4x4的二维数组
// 1表示有方块,0表示空
int blockShapes[7][4][4][4] = {
    // I型方块
    {
        {{0,0,0,0},{1,1,1,1},{0,0,0,0},{0,0,0,0}},
        {{0,0,1,0},{0,0,1,0},{0,0,1,0},{0,0,1,0}},
        {{0,0,0,0},{0,0,0,0},{1,1,1,1},{0,0,0,0}},
        {{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0}}
    },
    // O型方块
    {
        {{0,0,0,0},{0,1,1,0},{0,1,1,0},{0,0,0,0}},
        {{0,0,0,0},{0,1,1,0},{0,1,1,0},{0,0,0,0}},
        {{0,0,0,0},{0,1,1,0},{0,1,1,0},{0,0,0,0}},
        {{0,0,0,0},{0,1,1,0},{0,1,1,0},{0,0,0,0}}
    }
    // 其他形状省略,结构类似
};

// 当前方块的状态
struct CurrentBlock {
    int type;       // 方块类型 0-6
    int rotate;     // 旋转状态 0-3
    int x;          // 方块左上角x坐标(列)
    int y;          // 方块左上角y坐标(行)
} currentBlock;

方块旋转的实现逻辑

方块旋转的核心是切换当前方块的旋转状态,旋转后需要先进行碰撞检测,如果检测不通过则回退旋转状态。旋转状态的切换逻辑很简单,顺时针旋转时状态加1,超过3则回到0,逆时针旋转则相反。

旋转状态切换代码

// 顺时针旋转方块
void rotateBlockClockwise() {
    int oldRotate = currentBlock.rotate;
    // 切换旋转状态
    currentBlock.rotate = (currentBlock.rotate + 1) % 4;
    // 检测旋转后是否碰撞
    if (checkCollision(currentBlock.x, currentBlock.y, currentBlock.type, currentBlock.rotate)) {
        // 碰撞则回退状态
        currentBlock.rotate = oldRotate;
    }
}

// 逆时针旋转方块
void rotateBlockCounterClockwise() {
    int oldRotate = currentBlock.rotate;
    currentBlock.rotate = (currentBlock.rotate - 1 + 4) % 4;
    if (checkCollision(currentBlock.x, currentBlock.y, currentBlock.type, currentBlock.rotate)) {
        currentBlock.rotate = oldRotate;
    }
}

碰撞检测的实现方法

碰撞检测需要验证三个条件:方块位置没有超出游戏区域的左右边界、没有超出底部边界、没有和已经固定的方块重叠。游戏区域通常用一个二维数组表示,0表示空,1表示有固定方块。

碰撞检测函数实现

// 游戏区域大小,行和列
const int GAME_ROWS = 20;
const int GAME_COLS = 10;
// 游戏区域数组,存储已经固定的方块
int gameArea[GAME_ROWS][GAME_COLS] = {0};

// 碰撞检测函数,参数分别是方块的x、y坐标,类型,旋转状态
bool checkCollision(int x, int y, int type, int rotate) {
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            // 如果当前位置方块有元素
            if (blockShapes[type][rotate][i][j] == 1) {
                int realX = x + j;
                int realY = y + i;
                // 检测是否超出左右边界
                if (realX < 0 || realX >= GAME_COLS) {
                    return true;
                }
                // 检测是否超出底部边界
                if (realY >= GAME_ROWS) {
                    return true;
                }
                // 检测是否和已固定的方块重叠,顶部超出不需要检测
                if (realY >= 0 && gameArea[realY][realX] == 1) {
                    return true;
                }
            }
        }
    }
    return false;
}

实际调用示例

在游戏主循环中,当玩家按下旋转键时调用旋转函数,移动方块时也需要先调用碰撞检测验证位置是否合法。以下是简单的调用示例:

// 处理玩家输入
void handleInput() {
    // 假设按下上键顺时针旋转
    if (keyUpPressed) {
        rotateBlockClockwise();
    }
    // 按下左键向左移动
    if (keyLeftPressed) {
        if (!checkCollision(currentBlock.x - 1, currentBlock.y, currentBlock.type, currentBlock.rotate)) {
            currentBlock.x--;
        }
    }
    // 按下右键向右移动
    if (keyRightPressed) {
        if (!checkCollision(currentBlock.x + 1, currentBlock.y, currentBlock.type, currentBlock.rotate)) {
            currentBlock.x++;
        }
    }
    // 按下下键快速下落
    if (keyDownPressed) {
        if (!checkCollision(currentBlock.x, currentBlock.y + 1, currentBlock.type, currentBlock.rotate)) {
            currentBlock.y++;
        }
    }
}

注意事项

  • 方块形状的定义要准确,每个旋转状态的坐标要对应正确,避免出现旋转后形状异常的问题
  • 碰撞检测时要考虑方块在游戏区域顶部的情况,顶部超出不需要判定为碰撞,否则新生成的方块无法显示
  • 旋转和移动操作都要先检测再执行,避免方块卡进边界或者重叠
  • 如果方块有特殊的旋转中心,需要调整形状数组的定义,保证旋转后的位置符合预期

C++俄罗斯方块方块旋转碰撞检测游戏开发修改时间:2026-07-16 05:21:32

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。