关键点:碰撞检测+绘制终态图
1.碰撞检测
碰撞检测是此程序中的一个关键环节,用于判断俄罗斯方块是否能够被放置在当前位置。这是通过
canPlace
函数实现的。下面是canPlace
函数的具体内容和工作方式:
bool canPlace(int row, int col) { // 检查板块是否能够放到当前位置
for (int i = 0; i < piece.size(); ++i) {
for (int j = 0; j < piece[0].size(); ++j) {
if (piece[i][j] == 1) { // 如果板块的这一部分是实心的
if (row + i >= 15 || col + j >= 10 || grid[row + i][col + j] == 1) return false;
}
}
}
return true;
}
这个函数接受两个参数:row
和col
,分别代表放置板块的起始行和列。函数逐个遍历板块的每个小方块,如果遇到板块的一个实心部分(即piece[i][j]
为1):
- 它会检查这个实心部分是否会超出方格图底部(
row + i >= 15
)或右边界(col + j >= 10
),或者这个位置在方格图上已经有一个方块(grid[row + i][col + j] == 1
)。 - 如果上述任一条件为真,则当前位置不能放置板块,函数返回
false
。 - 如果所有实心部分都没有碰撞,函数返回
true
,表示板块可以放置在这个位置。
2.绘制终态图
绘制终态图是指在碰撞检测后,确定了板块的最终位置,然后在方格图上更新这个位置的过程。这是通过
placePiece
函数实现的。这里是它的具体实现:
void placePiece(int row, int col) { // 将板块放置到方格图上
for (int i = 0; i < piece.size(); ++i) {
for (int j = 0; j < piece[0].size(); ++j) {
if (piece[i][j] == 1) { // 如果板块的这一部分是实心的
grid[row + i][col + j] = 1; // 在方格图上标记为实心
}
}
}
}
在这个函数中,同样通过双重循环遍历板块的每个小方块。对于板块中的每一个实心部分(piece[i][j] == 1
):
- 我们在方格图的对应位置将值更新为1(
grid[row + i][col + j] = 1
),表示这个位置现在有一个方块。
这样,一旦所有必要的更新完成后,方格图就会反映出板块的最终位置,这就完成了绘制终态图的过程。在这之后,程序将遍历和打印出更新后的方格图,以显示板块下落后的最终状态。
解题思路
代码通过逐行检查来模拟板块的下落过程,直到找到一个合适的位置来放置板块,然后更新方格图,并输出最终结果。
1. 初始化方格图和板块形状
grid
变量存储了15行10列的方格图,使用二维向量表示。如果某个元素为0,则表示对应位置没有方块;如果为1,则表示已有方块。piece
变量存储了新加入的板块的形状,也是一个4行4列的二维向量。这个板块形状包含了4个小方块,以1表示。
2. 输入
- 通过标准输入接收方格图和板块形状的具体值。
- 接收一个整数
n
,表示板块下落时最左边的列(注意,输入的列是从1开始计数的,所以在程序内部需要将其减去1以转换为基于0的索引)。
3. 模拟板块下落
- 程序定义了一个
canPlace
函数来检查当前位置是否可以放置板块。它遍历板块的每一个小方块,检查放置后是否会超出方格图的边界或与已有方块冲突。 - 在主循环中,程序从方格图的最上方开始向下遍历,使用
canPlace
检查每一行是否能够放下当前的板块。一旦找到一个位置无法放置板块,就记录上一个可以放置的位置,然后跳出循环。
4. 放置板块
- 一旦确定了板块的最终位置,程序使用
placePiece
函数将板块放置在方格图上。这个函数遍历板块的每一个小方块,如果该小方块存在(即值为1),则将对应的方格图位置更新为1。
5. 输出结果
- 最后,程序遍历并输出更新后的方格图。每一行输出后跟一个换行符。
完整代码
#include <iostream>
#include <vector>
using namespace std;
int n, finalRow;
vector<vector<int>> grid(15, vector<int>(10)), piece(4, vector<int>(4));
bool canPlace(int row, int col) { // 检查板块是否能够放到当前位置
for (int i = 0; i < piece.size(); ++i) {
for (int j = 0; j < piece[0].size(); ++j) {
if (piece[i][j] == 1) {
if (row + i >= 15 || grid[row + i][col + j] == 1) return false;
}
}
}
return true;
}
void placePiece(int row, int col) { // 将板块放置到方格图上
for (int i = 0; i < piece.size(); ++i) {
for (int j = 0; j < piece[0].size(); ++j) {
if (piece[i][j] == 1) grid[row + i][col + j] = 1;
}
}
}
int main() {
for (int i = 0; i < 15; i++) { // 输入初始的方格图
for (int j = 0; j < 10; j++) {
cin >> grid[i][j];
}
}
for (int i = 0; i < 4; i++) { // 输入新加入的板块形状
for (int j = 0; j < 4; j++) {
cin >> piece[i][j];
}
}
cin >> n;
n -= 1; // 调整为基于0的索引
for (int row = 0; row < 15; row++) { // 模拟板块下落
if (canPlace(row, n)) finalRow = row;
else break;
}
placePiece(finalRow, n); // 放置板块
for (int i = 0; i < 15; i++) { // 输出最终的方格图
for (int j = 0; j < 10; j++) {
cout << grid[i][j] << " ";
}
cout << endl;
}
return 0;
}