CCF試題 201604-2 俄羅斯方塊

問題描述

俄羅斯方塊是俄羅斯人阿列克謝·帕基特諾夫發明的一款休閒遊戲。
  遊戲在一個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

代碼實現

#include <iostream>

using namespace std;

class Point {
	public:
		short x; //行下標 
		short y; //列下標 
		short mark; //標記當前對象方塊在板塊圖案中是否位於自身列的最下面 ,在最下面mark爲1 
}; 

//俄羅斯方塊遊戲 
int main() {
	short panel[15][10]; //遊戲界面 0代表無,1代表有方塊 
	Point points[4]; //板塊圖案內四個方塊 
	short i,j,k;
	short position; //板塊圖案開始降落的位置1~7 
	short max = -1; //記錄行下標最大的那個下標 

	for (i = 0; i < 15; i++) {
		for (j = 0; j < 10; j++) {
			cin >> panel[i][j];
		}
	}
	k = 0; //四個方塊的計數器 
	for (i = 0; i < 4; i++) {
		for (j = 0; j < 4; j++) {
			short temp;
			cin >> temp;
			if (temp == 1) { //記錄每個方塊的位置
				points[k].x = i;
				points[k].y = j;
				points[k++].mark = 1; //標記初始化爲1,默認是最下面的 
			} 
		}
	}
	cin >> position;
	for (i = 0; i < 4; i++) {
		for (j = 0; j < 4; j++) {
			if (i != j && points[i].y == points[j].y) { //兩個方塊在同一列 
				short temp = i < j ? i : j; //取出i,j中較小的 
				points[temp].mark = 0; //較小的不是最下面的 
			}
		}
	}
	//將板塊圖放入遊戲界面position位置,改變每個方塊的列下標 
	for (i = 0; i < 4; i++) {
		points[i].y += position - 1;
		//尋找最大行下標 
		if (max < points[i].x)
			max = points[i].x;
	}
	
	while (max < 14) {
		for (i = 0; i < 4; i++) {
			//板塊圖中mark=1的方塊下方有方塊時,終止下落 
			if (points[i].mark == 1 
			&& panel[points[i].x + 1][points[i].y] == 1) {
				break;
			} 
		}
		//符合下落條件 
		if (i == 4) {
			max++;
			//板塊圖所有方塊行下標+1 
			for (j = 0; j < 4; j++) {
				points[j].x++;
			}
		} else { //不符合下落條件 
			break;
		}
	}
	//繪製最終位置 
	for (i = 0; i < 4; i++) {
		panel[points[i].x][points[i].y] = 1;
	}
	//輸出遊戲界面
	for (i = 0; i < 15; i++) {
		for (j = 0; j < 10; j++) {
			cout << panel[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
}

首先用一個15×10的二維數組來存儲遊戲界面,每個元素代表一格,0代表此處沒有方塊,1代表此處有方塊。我並沒有再用一個4×4的二維數組來存儲板塊圖案,而是用了一個Point類來記錄了下落圖形的四個方塊的位置。

算法中前兩個循環是用來接收輸入的遊戲界面數據和板塊圖案數據,同時讀入 position (1~7),代表遊戲開始時板塊圖案的初始位置。接下來的一個循環我從points數組裏的四個方塊中找出其下方還有方塊的那些,並將其mark設置爲0,代表其下方存在方塊,此後在做下落判斷的時候就可以不用判斷這些方塊。下面一個循環將板塊圖案四個方塊的座標根據position初始位置,更改爲在遊戲界面裏的座標,同時記錄行座標的最大值。接下來的while循環就是判斷當前板塊圖案能否下落,能下落就更改四個方塊的座標,不能下落就跳出循環。接下來就將四個方塊的座標在遊戲界面數組中置爲1,同時打印出遊戲界面即可。

以上都是我個人的一個解題思路,可能存在一些不太靈活的地方,歡迎小夥伴們提出各種更好的解題思路。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章