【CSP试题回顾】201604-2-俄罗斯方块

本文详细描述了在CSP-201604-2项目中,如何通过碰撞检测函数canPlace和绘制终态图函数placePiece来处理俄罗斯方块游戏中的板块放置与网格更新。着重介绍了这两个函数的工作原理以及它们在游戏逻辑中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CSP-201604-2-俄罗斯方块

关键点:碰撞检测+绘制终态图

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;
}

这个函数接受两个参数:rowcol,分别代表放置板块的起始行和列。函数逐个遍历板块的每个小方块,如果遇到板块的一个实心部分(即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;
}

请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值