C语言俄罗斯方块:方块下落函数陷入无限循环无法正常下落
问题
我正在为大一计算机科学项目编写俄罗斯方块游戏,目前方块下移函数存在问题。我使用二维数组表示游戏状态(示例为方形 Tetromino):
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
我期望该函数能将游戏状态修改为:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 2 1 0 0 0 0
但实际该函数并未将方块下移至最后一行后退出循环,而是直接陷入无限循环。以下是负责方块下移的函数代码:
void block_falling(int gamestate[NO_BLOCKS_FOR_GAP][NUMBER_OF_BLOCKS_HORIZONTALLY]) { int temporary_storage; bool is_falling = true; while (is_falling) { for (int row_counter = 0; row_counter < NO_BLOCKS_FOR_GAP; row_counter++) { for (int column_counter = 0; column_counter < NUMBER_OF_BLOCKS_HORIZONTALLY; column_counter++) { if ((gamestate[row_counter][column_counter] == 1) || (gamestate[row_counter][column_counter] == 2)) { if (row_counter != NO_BLOCKS_FOR_GAP - 1) { temporary_storage = gamestate[row_counter][column_counter]; gamestate[row_counter][column_counter] = gamestate[row_counter - 1][column_counter]; gamestate[row_counter - 1][column_counter] = temporary_storage; } if (row_counter == NO_BLOCKS_FOR_GAP - 1) { is_falling = false; } } } } } }
我确认下移逻辑本身是正确的,因为将如下代码片段重复执行10次,方块会下移10格:
for (int row_counter = 0; row_counter < NO_BLOCKS_FOR_GAP; row_counter++) { for (int column_counter = 0; column_counter < NUMBER_OF_BLOCKS_HORIZONTALLY; column_counter++) { if ((gamestate[row_counter][column_counter] == 1) || (gamestate[row_counter][column_counter] == 2)) { temporary_storage = gamestate[row_counter][column_counter]; gamestate[row_counter][column_counter] = gamestate[row_counter - 1][column_counter]; gamestate[row_counter - 1][column_counter] = temporary_storage; } } }
修复方案
你的代码存在三个核心问题:
- 行遍历方向错误:从第0行开始遍历,交换当前行和上一行元素,本质是让方块上移,测试时的下移只是意外效果,逻辑完全错误。
- 交换逻辑颠倒:要实现下移,应该把当前行的方块和下一行(
row_counter+1)交换,而不是上一行。 - 退出条件无效:仅在遍历到最后一行时停止循环,但此时方块根本没到达底部,导致无限循环。正确的退出条件是判断方块是否还能继续下移。
修改后的函数代码如下:
void block_falling(int gamestate[NO_BLOCKS_FOR_GAP][NUMBER_OF_BLOCKS_HORIZONTALLY]) { int temporary_storage; bool can_fall; do { can_fall = false; // 从倒数第二行向上遍历,避免覆盖未处理的方块 for (int row_counter = NO_BLOCKS_FOR_GAP - 2; row_counter >= 0; row_counter--) { for (int column_counter = 0; column_counter < NUMBER_OF_BLOCKS_HORIZONTALLY; column_counter++) { if ((gamestate[row_counter][column_counter] == 1) || (gamestate[row_counter][column_counter] == 2)) { // 检查下一行是否为空,允许下移 if (gamestate[row_counter + 1][column_counter] == 0) { // 交换当前行与下一行元素,实现下移 temporary_storage = gamestate[row_counter][column_counter]; gamestate[row_counter][column_counter] = gamestate[row_counter + 1][column_counter]; gamestate[row_counter + 1][column_counter] = temporary_storage; can_fall = true; // 标记本次循环仍可下移 } } } } } while (can_fall); // 直到无法下移为止 }
关键修改说明:
- 从下往上遍历行:从倒数第二行开始向上处理,确保下方的方块先完成下移,不会被上方未处理的元素覆盖。
- 正确的下移交换:将当前行方块与下一行的空位置交换,真正实现向下移动。
- 动态判断下落状态:每次循环后检查是否发生了下移操作,若没有则说明方块已到底或被阻挡,自动退出循环。
这样修改后,方块会自动下落至底部,不会陷入无限循环,完全符合预期效果。
内容的提问来源于stack exchange,提问作者user21105733
相关产品推荐
相关产品推荐

