题目
问题描述
俄罗斯方块是俄罗斯人阿列克谢·帕基特诺夫发明的一款休闲游戏。
游戏在一个15行10列的方格图上进行,方格图上的每一个格子可能已经放置了方块,或者没有放置方块。每一轮,都会有一个新的由4个小方块组成的板块从方格图的上方落下,玩家可以操作板块左右移动放到合适的位置,当板块中某一个方块的下边缘与方格图上的方块上边缘重合或者达到下边界时,板块不再移动,如果此时方格图的某一行全放满了方块,则该行被消除并得分。
在这个问题中,你需要写一个程序来模拟板块下落,你不需要处理玩家的操作,也不需要处理消行和得分。
具体的,给定一个初始的方格图,以及一个板块的形状和它下落的初始位置,你要给出最终的方格图。
输入格式
输入的前15行包含初始的方格图,每行包含10个数字,相邻的数字用空格分隔。如果一个数字是0,表示对应的方格中没有方块,如果数字是1,则表示初始的时候有方块。输入保证前4行中的数字都是0。
输入的第16至第19行包含新加入的板块的形状,每行包含4个数字,组成了板块图案,同样0表示没方块,1表示有方块。输入保证板块的图案中正好包含4个方块,且4个方块是连在一起的(准确的说,4个方块是四连通的,即给定的板块是俄罗斯方块的标准板块)。
第20行包含一个1到7之间的整数,表示板块图案最左边开始的时候是在方格图的哪一列中。注意,这里的板块图案指的是16至19行所输入的板块图案,如果板块图案的最左边一列全是0,则它的左边和实际所表示的板块的左边是不一致的(见样例)
输出格式
输出15行,每行10个数字,相邻的数字之间用一个空格分隔,表示板块下落后的方格图。注意,你不需要处理最终的消行。
样例
输入:
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 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 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0
1 1 1 0 0 0 1 1 1 1
0 0 0 0 1 0 0 0 0 0
0 0 0 0
0 1 1 1
0 0 0 1
0 0 0 0
3
输出:
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 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 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0
1 1 1 1 1 1 1 1 1 1
0 0 0 0 1 1 0 0 0 0
分析
判断最后方块落在屏幕的那个位置,可以直接使用程序模拟方块的下落过程,在下落过程中两个方块重合了或方块下落过程中出了下界,则模拟结束。可以得到方块下落的层数,然后可输出最后的显示结果。
代码
/*
20190916
ccf试题2:俄罗斯方块
*/
#include <iostream>
using namespace std;
int matrix[16][10];
int block[4][4];
int column;
//用于保存方块的位置
struct Squares{
int row;
int col;
};
Squares square[5];
int len = 0;
int main(){
//接收数据
for(int i=0; i<15; i++){
for(int j=0; j<10; j++){
cin >>matrix[i][j];
}
}
for(int i=0; i<4; i++){
for(int j=0; j<4; j++){
cin >>block[i][j];
//先获取板块中的方块
if(block[i][j] == 1){
square[len].row = i;
square[len].col = j;
len++;
}
}
}
cin >>column;
column--;
for(int i=0; i<len; i++){
square[i].col += column;
}
//摸拟运行,方块位置下降
int drop = 0;
bool put = true;
while(put){
for(int i=0; i<len; i++){
//遇到了方块
if(matrix[square[i].row+drop][square[i].col] == 1){
put = false;
break;
}
//到了底部
if((drop+square[i].row) == 15){
put = false;
break;
}
}
if(put){
drop++;
}
else{
break;
}
}
for(int i=0; i<len; i++){
matrix[square[i].row+drop-1][square[i].col] = 1;
}
for(int i=0; i<15; i++){
for(int j=0; j<10; j++){
cout <<matrix[i][j]<<" ";
}
cout <<endl;
}
return 0;
}
总结
模拟方块下落的方法有两种,一种是直接模拟4x4的16个方块下落,这样坐标转换繁琐,我最开始使用的这种方法,最后又对程序修修改改,然后得了90分;还有一种方法是将4个方块拿出来,只对这4个方块进行模拟,这样要简单很多。
如果想进一步节省时间,可以先计算出一个drop的值,而不是从0开始。