自己動手寫俄羅斯方塊(一)

一.思路
1.  設定小方塊的大小和遊戲區的座標
每個俄羅斯方塊都是有4個小方塊構成的,所以我們要先設定好每個小方塊的固定大小,還要確定遊戲區的起始座標(左上角座標);
2.  建立遊戲區
根據自己設定的座標建立一個2010列的遊戲區。每行每列交叉處構成的方格即爲一
個方塊的大小。設定好方格大小後,我們就可以獲得遊戲區的終止座標(右下角座標)。如起始座標爲(50,50),方格大小爲20,那終止座標就是(450250);(50+20*20,50+10*20);
3.  初始化俄羅斯方塊的7種圖形
我們都知道俄羅斯方塊有7種圖形,分別爲:SZLJIOT這幾個字母的形狀。每種圖形經過4個方向的旋轉又可以得到4種圖形(有的可能是1種或2種,因爲有的旋轉過之後跟以前的圖形還是一樣的)。我們將這些圖形做一下初始化,等需要時可以直接調用。我用一個POINT類型的三維數組來實現。如:可以定義一個這樣的三維數組:
const POINT Terics[7][4][4] =

{

  {

      0,0,1,0,0,1,-1,1,

      0,0,0,1,1,1,1,2,

      0,0,1,0,0,1,-1,1,

      0,0,0,1,1,1,1,2

  },

  {

      0,0,1,0,1,1,2,1,

      0,0,0,1,-1,1,-1,2,

      0,0,1,0,1,1,2,1,

      0,0,0,1,-1,1,-1,2

  },

  {

      0,0,0,1,0,2,1,2,

      0,0,0,1,-1,1,-2,1,

      0,0,1,0,1,1,1,2,

      0,0,0,1,1,0,2,0

  },

  {

      0,0,0,1,0,2,-1,2,

      0,0,1,0,2,0,2,1,

      0,0,1,0,0,1,0,2,

      0,0,0,1,1,1,2,1

  },

  {

      0,0,0,1,0,2,0,3,

      0,0,1,0,2,0,3,0,

      0,0,0,1,0,2,0,3,

      0,0,1,0,2,0,3,0

  },

  {

      0,0,1,0,0,1,1,1,

      0,0,1,0,0,1,1,1,

      0,0,1,0,0,1,1,1,

      0,0,1,0,0,1,1,1

  },

  {

      0,0,1,0,2,0,1,1,

      0,0,0,1,0,2,1,1,

      0,0,0,1,-1,1,1,1,

      0,0,0,1,0,2,-1,1

  }

};

第一維的7表示7種圖形,第二維的4表示4個方向,第三維的4表示4point型的數。通過這個三維數組和當前座標我們就可以得出每種圖形4個方塊的左上角座標,也就可以在當前位置畫出各種各樣的圖形了。可能有的人不理解這個三維數組中的數字代表什麼意思,其實我使用的是相對偏移量,在每種圖形的每個方向的4個小方塊中選擇一個作爲基準方塊,它的左上角的座標是(0,0),其他三個小方塊的左上角座標就可以用相對於這個基準方塊的左上角座標的偏移量來表示。具體實現方法在下面會討論。注意:這個三維數組的初始化不是唯一的,根據自己的喜歡,先初始化哪種圖形都可以。
4.  遊戲按鍵
我們只需用到上下左右四個鍵就可以了,上鍵用於改變方向,下鍵用於加速方塊的下移,左右鍵用於方塊的左右移動。注意我們每次移動的是一個小方塊的距離。
當用戶點擊遊戲開始時,方塊會自上而下落下,如果用戶不按任何鍵,則方塊正常下落。這個可以由SetTimer來完成,我們在WM_CREATE消息中調用SetTimer(hwnd,1,1000,NULL);如何用戶覺得下落時間太慢,也可以自己設定間隔時間。然後就可以在WM_TIMER中通過改變圖形的縱座標來實現方塊下移。
若用戶按:
上鍵:有規律的變換方向,即根據用戶初始化時的方向依次變換。
下鍵:加速下移,通過增加縱座標來實現。
左鍵:向左移動一個位置,通過減少橫座標來實現。
右鍵:向右移動一個位置,通過增加橫座標來實現。
這些遊戲按鍵我們可以在WM_KEYDOWN消息中實現,當窗口函數獲得WM_KEYDOWN消息時,它的第三個參數wParam保存的將是按鍵的詳細內容。我們可以通過一個switch……case來查找我們想要的消息。
這四個按鍵對應的消息分別是:VK_UP(上鍵),VK_DOWN(下鍵),VK_LEFT(左鍵),VK_RIGHT(右鍵)。
5.  判斷範圍
每次用戶按下鍵後都要判斷是否超出了範圍,若超出了範圍,則對用戶的按鍵不響應。
判斷方法:兩個條件:1)根據用戶當前的座標計算出該形狀的四個方塊的左上角座標,然後判斷這些座標是否超出了遊戲區範圍。2)判斷該方塊要移動到的區域是否已經有方塊存在了。如果上面兩個條件中有一個成立,那麼用戶的按鍵將不予響應。
6.  保存遊戲區狀態
我們如何知道當前位置是否有方塊存在呢,這就需要我們保存遊戲區當前的狀態。一方面是爲了第5步的判斷用,另一方面是爲了窗口刷新時加載已存在的方塊。
我們可以定義一個結構體,裏面有兩個變量,一個表示狀態,另一個表示形狀。另外還需要定義一個結構體變量,這個變量我們定義成一個整型的二維數組,這個二維數組的橫縱座標當然應該是遊戲區的行數和列數啦。如:
struct CurrentTericsStates
{
    Int states;
    Int shape;
}CurrentTericsStatesInfo[10][20];
何時用來保存當前的狀態呢?
當然是當方塊落到遊戲區的底部或是遇到其他方塊不能再往下移動時就需要保存當前方塊的信息了。
7.  圖形顯示問題
當圖形自動下移或者我們移動圖形時,會發現原來的圖形還存在,該如何解決這個問題呢?我想了兩種方法:
1)              我們需要用兩個POINT型變量來保存當前圖形和上一個圖形的形狀、方向、坐
標。然後在每次移動時用背景色的畫筆重畫上一個圖形,這樣上一個圖形就被覆蓋了,我們就看不到了。最後再把當前的圖形畫上就可以了。
2)              利用擦除背景法,即我們每次在移動一個圖形後,將整個遊戲區用背景色的畫
刷再刷一遍,這樣所有圖形都沒有了。我們只需將遊戲區,原有圖形和當前圖形都畫上就可以了。
8.  如何消去一行
當遊戲區中的某一行都填滿了方塊後,我們該如何消去這一行呢?這時我們就需要用到前面定義的結構體變量了。利用查找法,查看數組中是否有一行都爲1,如果都爲1的話,就說明該行已滿,那麼就消去該行。如何消去呢?其實,我們就是用上一行來填充這一行,也就是用上一行的狀態來代替該行的狀態,這樣該行就被消去了。另外我們還需要兩個全局變量countscore,每當消去一行,count就加1,並計算出相應的分數,例如每消去一行就加10分等等。最後我使用了一個彈出對話框來輸出所得的分數。
9.         如何判斷遊戲結束呢?
這個問題看起來有點難,其實我們只需要判斷遊戲區最上邊一行的狀態就可以了,如果最上邊一行中有狀態爲1的方塊,就說明有方塊已經到達了遊戲區頂部,那麼遊戲也就結束了。
到這裏,一個俄羅斯方塊的大體思路已經出來了,具體的代碼和一些細節會在以後的文章中提到。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章