試題編號: 201604-2
試題名稱: 俄羅斯方塊
時間限制: 1.0s
內存限制: 256.0MB
問題描述:
俄羅斯方塊是俄羅斯人阿列克謝·帕基特諾夫發明的一款休閒遊戲。
遊戲在一個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
思路:將4×4板塊中的圖形從頂端開始下落,依次判斷板塊最後一行的每一列是否可以下降,全部通過則下降,否則停止
import java.util.*;
public class T201604_2 {
static int[][] arr1 = new int[15][10]; // 15×10方格圖
static int[][] arr2 = new int[4][4]; // 4×4下落板塊
static int pos, tot = 0; // 從pos列開始下落,總共可移動tot行
static int[] record = new int[4]; // 記錄4×4板塊最底行所在15×10方格圖的行數
public static void main(String[] args) {
input();
move();
}
// 輸入
static void input(){
Scanner sc = new Scanner(System.in);
for (int i = 0; i < arr1.length; i++)
for (int j = 0; j < arr1[i].length; j++)
arr1[i][j] = sc.nextInt();
for (int i = 0; i < arr2.length; i++)
for (int j = 0; j < arr2[i].length; j++)
arr2[i][j] = sc.nextInt();
// 將4×4板塊中的圖形移動至最低端
/**
* 例如:
* - - - - - - - -
* - * * * - - - -
* - - * - ----> - * * *
* - - - - - - * -
*/
while(arr2[3][0]==0 && arr2[3][1]==0 && arr2[3][2]==0 && arr2[3][3]==0){
for (int i = 2; i >= 0; i--) {
for (int j = 0; j < 4; j++) {
arr2[i+1][j] = arr2[i][j];
if(i==0)arr2[i][j]=0;
}
}
}
pos = sc.nextInt()-1;
sc.close();
// 初始化記錄行
for (int i = 0; i < record.length; i++) record[i] = -1;
}
static void move(){
for (int i = 3; i >= 0; i--)
for (int j = 0; j < 4; j++)
if(arr2[i][j]==1 && record[j]==-1) record[j]=i;
// 下移
while(true){
boolean flag = true;
for (int i = 0; i < 4; i++) {
if(record[i]!=-1){
// 越界或不能移動則終止,否則記錄
if(record[i]+1>14 || arr1[record[i]+1][pos+i]!=0){ flag = false;break;}
else record[i]++;
}
}
if(!flag) break;
else tot++;
}
// 修改移動結果並輸出
for (int i = 0; i < arr1.length; i++) {
for (int j = 0; j < arr1[i].length; j++) {
if(i>=tot && i<tot+4 && j>=pos && j<pos+4) arr1[i][j]+=arr2[i-tot][j-pos];
System.out.print(arr1[i][j]);
if(j!=arr1[i].length-1)System.out.print(" ");
}
System.out.println();
}
}
}