CCF201604-2 俄罗斯方块(JAVA版)
问题描述
俄罗斯方块是俄罗斯人阿列克谢·帕基特诺夫发明的一款休闲游戏。
游戏在一个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
首先做这题,要把方块放进界面中去考虑。在界面中,考察方块的的每一列距离其正下方的是否被填充方格,距离多远
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//初始化界面
int[][] map = new int[15][10];
for(int i = 0;i<15;i++){
for(int j = 0;j<10;j++){
map[i][j] = sc.nextInt();
}
}
//初始化方块
int[][] block = new int[4][4];
for(int i = 0;i<4;i++){
for(int j = 0;j<4;j++){
block[i][j] = sc.nextInt();
}
}
//输入偏移量
int position = sc.nextInt();
//因为position是方块(4行4列)位于整个界面的第几列
//如果是3的话,其实就是距离界面map左边界两个空格
//所以要-1,体现距离
position--;
sc.close();
//只需要找到方块下落的最短距离distance
int distance = Integer.MAX_VALUE;
//continue跳转到这里,这块就是找下降的最短距离
for(int i = 0;i<4;i++){
//一列一列的遍历,找上界和下界
//上界
int upBound = -1;
for(int j = 0;j<4;j++){
if(block[j][i]==1){
upBound = j;
}
}
//遍历完方块的每一列,如果upBound没有改变,仍然是-1
//说明方块中的这列没有小方块,看下一列
if(upBound==-1){
continue;//不再执行下面的程序,跳转到for循环
}
//设置下界,界面最下面行的索引是14,总要体现本列没有填充的时候对应的是15
int downBound = 15;
//遍历界面,对应于方块正下方的区域,是否被填充,因为上面0-3行是方块在占用
for(int j = 14;j>=4;j--){
//这里的i+position考虑到了偏移
if(map[j][i+position]==1){
downBound = j;//找到下界,没找到的话,就是前面的15
}
}
//找最短的距离,一列一列的找的
if((downBound-upBound)<distance){
distance = downBound-upBound;
}
}
//将方块放置到界面上
for(int i = 0;i<4;i++){
for(int j = 0;j<4;j++){
//找到方块中有填充的位置,填充到对应的界面中
if(block[i][j]==1){
//此处画图理解,为什么要-1
map[i+distance-1][j+position] = block[i][j];
}
}
}
//遍历打印出最终界面
for(int i = 0; i < 15; i++){
for(int j = 0 ; j < 10; j++){
System.out.print(map[i][j] + " ");
}
System.out.println();
}
}
}
【测试结果】