第三個題目是俄羅斯方塊遊戲。該遊戲算法比較簡單,主要功夫都在界面體驗上了,比如方塊圖形、使用者控制、消去與累計等。
圖形我們采用GDI+畫圖方式顯示,共8種圖形,當然可以根據自己的喜好随意定制。如何表示圖形?我們可以借鑒馬賽克效果。把所有圖形都用3*3矩陣表示,0表示背景色顯示,1表示着色顯示。比如
{0,0,0},
{0,1,0}, 表示 T型,看出來了嗎?每個數字位置其實就是一個正方形小塊。
{1,1,1}
使用者控制?簡單KeyPress事件實作就好。當然還有一個無需使用者控制的就是自動下落,可以使用Timer實作。
消去算法?^_^,當然很簡單,如果一行上有為0的單元格,那麼表示沒有充滿,就不用消去;否則就要消去。累計就是數組追加,消去就是元素删除。
當然了,消去與累計都需要将資料的變化展現到界面上,那就是畫圖。Graphics對象我們都會使用,在該windows窗體遊戲中,我們可以實作OnPaint事件。每當需要重繪的時候,比如使用者控制,消去等,就調用窗體refresh,那麼自然會觸發Paint事件。以下是代碼示例:
public int[][,] figures = new int[8][,]//8種圖形
{
new int[3,3] {
{0,0,0},
{0,1,0},
},
new int[3,3]
{0,2,2},
{2,2,0}
{3,3,0},
{0,3,3}
new int[2,2]
{4,4},
{4,4}
{5,0,0},
{5,5,0}
{0,6,0},
{6,6,0}
new int[4,4]
{7,0,0,0},
{7,0,0,0}
new int[3,3]
{0,8,0},
{8,8,8},
{0,0,0}
}
};
你能從上面的定義看出有哪些圖形嗎?^_^,為什麼不為0的地方不全是1?因為我想讓不同的圖形顯示不同的顔色,如果無此要求則不必這樣。
在具體畫圖時,我們需要将将數組大小轉換為區域邊長方格數
int conversize(int sz)
{
int s = 0;
if (sz == 4) s = 2;
if (sz == 9) s = 3;
if (sz == 16) s = 4;
return s;
}
當然出現的圖形是随機的,直接用Random就可以做到。
記住無論什麼動作引起的圖形變化,包括移動、旋轉等都要用Refresh,以便重新整理遊戲界面。例如向左
public void moveLeft()
if (check(figure, px - 1, py)) px = px - 1;
Refresh();//this.Refresh();
protected override void OnPaint(PaintEventArgs e)這個熟悉吧?嗯,界面就是它畫出來的。你要在界面顯示什麼,就在裡面畫什麼。記住,是全部界面,因為我們的這個遊戲沒有任何其他資源,沒有任何控件,隻有圖形。
當然了,圖形位置移動必須要要檢查越界和是否遇到障礙物。也就是上述的check方法。基本思路就是圖形經過的位置中無越界并且無不為0的單元格存在。
bool check(int[,] fg, int x, int y)
int sz = conversize(fg.Length);
for (int i = 0; i < sz; i++)
for (int j = 0; j < sz; j++)
{
int rx = i + x;
int ry = j + y;
if ((rx < 0 || rx > 9 || ry < 0 || ry > 19) && fg[i, j] != 0) return false;
if (!(rx < 0 || rx > 9 || ry < 0 || ry > 19))
if (board[rx, ry] != 0 && fg[i, j] != 0) return false;
}
return true;
旋轉怎麼實作?一個純數組倒序排列的簡單題目,不是嗎?
最後是遊戲難度的問題,等級越高,降落速度越快,其實就是把等級數字跟計時器的Interval挂鈎就是了。
其他的就不多說了。有興趣的可以把它做成控件,友善大家使用。祝你玩的開心。
明天搞那個木馬記錄器……
本文轉自 王傑瑞 51CTO部落格,原文連結:http://blog.51cto.com/wangjierui/56005,如需轉載請自行聯系原作者