ccf160402-俄罗斯方块
题目
问题描述
俄罗斯方块是俄罗斯人阿列克谢·帕基特诺夫发明的一款休闲游戏。
游戏在一个15行10列的方格图上进行,方格图上的每一个格子可能已经放置了方块,或者没有放置方块。每一轮,都会有一个新的由4个小方块组成的板块从方格图的上方落下,玩家可以操作板块左右移动放到合适的位置,当板块中某一个方块的下边缘与方格图上的方块上边缘重合或者达到下边界时,板块不再移动,如果此时方格图的某一行全放满了方块,则该行被消除并得分。
在这个问题中,你需要写一个程序来模拟板块下落,你不需要处理玩家的操作,也不需要处理消行和得分。
具体的,给定一个初始的方格图,以及一个板块的形状和它下落的初始位置,你要给出最终的方格图。
游戏在一个15行10列的方格图上进行,方格图上的每一个格子可能已经放置了方块,或者没有放置方块。每一轮,都会有一个新的由4个小方块组成的板块从方格图的上方落下,玩家可以操作板块左右移动放到合适的位置,当板块中某一个方块的下边缘与方格图上的方块上边缘重合或者达到下边界时,板块不再移动,如果此时方格图的某一行全放满了方块,则该行被消除并得分。
在这个问题中,你需要写一个程序来模拟板块下落,你不需要处理玩家的操作,也不需要处理消行和得分。
具体的,给定一个初始的方格图,以及一个板块的形状和它下落的初始位置,你要给出最终的方格图。
输入格式
输入的前15行包含初始的方格图,每行包含10个数字,相邻的数字用空格分隔。如果一个数字是0,表示对应的方格中没有方块,如果数字是1,则表示初始的时候有方块。输入保证前4行中的数字都是0。
输入的第16至第19行包含新加入的板块的形状,每行包含4个数字,组成了板块图案,同样0表示没方块,1表示有方块。输入保证板块的图案中正好包含4个方块,且4个方块是连在一起的(准确的说,4个方块是四连通的,即给定的板块是俄罗斯方块的标准板块)。
第20行包含一个1到7之间的整数,表示板块图案最左边开始的时候是在方格图的哪一列中。注意,这里的板块图案指的是16至19行所输入的板块图案,如果板块图案的最左边一列全是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 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
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 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
思路
1.解题的重点是找到第一个与方块接触到的位置,找到这个位置后,因为方块是一个整体,确定停留首先与方格图中为1的格子接触到的方块,其他的也依次就被安置在这里了。
2.要注意的有几个点:1)将最下面的一行置1,这样如果这个方块刚好落的位置本来没有格子为1,也不会因为找不到1而一直往下移;
2)本来的想法是通过将板块在对应位置与原来的格子叠加,找到是哪一个位置先接触到。后来实现不了,然后百度了一下别人的思路,果然是有价值的参考。因为一个板块有4个小块组成,确定每个小块在整个板块中的行、列,就可以将“累加往下移动的行数”看做“板块下落”的过程。在这个过程中,判断首先为1的格子,即首次接触点。(首次接触点的条件是格子与该方块中小块第一次碰到,而且是碰到的小块中行号最小被接触的,因为这样最先碰到)
3)我一开始写的判断条件,只是循坏每个块,想法是找到先接触。本身块的行列定位就是按从下往上来的,但是如果存在上方的小块先碰到格子,我原来的算法就没有判断,因此之前一直是70分。然后就是进行一下判断,循环四个小块,找到每个小块先碰到的格子,确保最终的格子,是行号最小的(最先碰到)。就可以100分啦!
3.并且发现自己对二维数组的用法都很模糊了。。。复习一下。(这个链接讲得很清楚,http://c.biancheng.net/view/1423.html)
定义一个三行四列的二维数组,stu[3][4],3 行的编号为 0〜2,而 4 列的编号则为 0〜3。 行和列的元素值都是从0开始的 也就是元素值是从stu[0][0],到stu[2][3]。 我之前一直试图从1开始觉得会更好理解,结果......理解是好理解,输出就乱了
题解
#include<iostream> using namespace std; struct block{ int row; int col; }; int main(){ int before[16][11]; for(int i=0;i<15;i++){ for(int j=0;j<10;j++){ scanf("%d",&before[i][j]);//初始方格图 } } for(int j=0;j<10;j++){ before[15][j]=1; } int add[4][4]; for(int i=0;i<4;i++){ for(int j=0;j<4;j++){ scanf("%d",&add[i][j]);//板块 } } block blocks[4]; int k=1; //处理板块,最下面一行是有元素的 for(int i=3;i>=0;i--){ for(int j=0;j<4;j++){ if(add[i][j]==1){ blocks[k].row=i; blocks[k].col=j; k++; } } } int n; scanf("%d",&n);//最左边开始的时候是在方格图的哪一列中 int m;//掉到哪一行 //处理板块掉落,只关注板块的最左列和最右列 for(int i=1;i<=4;i++){
int breakFlag=0;//结束循环标志
for(int j=0;j<=15;j++){
if(before[j+blocks[i].row][n+blocks[i].col-1]==1){
//应该要判断哪个块接触到的点行号最小
if(i==1){
m=j-1;
}
if(m>j-1){
m=j-1;
}
break;
}
}
}for(int i=1;i<=4;i++){ before[m+blocks[i].row][n+blocks[i].col-1]=1; //printf("-----%d %d %d %d %d %d\n",m+blocks[i].row,n+blocks[i].col,m,i,blocks[i].row,blocks[i].col); } //输出结果 for(int i=0;i<15;i++){ for(int j=0;j<10;j++){ if(j!=0){ printf(" "); } printf("%d",before[i][j]); } printf("\n"); } return 0; }