天天看點

俄羅斯方塊——圖形程式設計

第三個題目是俄羅斯方塊遊戲。該遊戲算法比較簡單,主要功夫都在界面體驗上了,比如方塊圖形、使用者控制、消去與累計等。

圖形我們采用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,如需轉載請自行聯系原作者

繼續閱讀