MFC實現俄羅斯方塊二

1>生成物體
         大家想的都過於複雜了.生成物體只是爲幾個小方塊生成幾個 行列值,當然這個行列值不是隨意的.而是有限制的.假如我們讓第一個方塊的行列值爲 <-1,4> 然後依據這個方塊在它的上下左右四個方向隨機生成第二個方塊,然後再根據第二個生成第三....根據第三個生成第四個.每個方塊都是上一個方塊的上下左右四個方向中非上一個方塊的地方,那這個生成的物體正是我們要的!!!不信在紙上畫一下! 根據這個思路進行改變.可以生成任何你要的形狀!!  但是這樣生成的卻沒有 T 形狀的...(下面給出的是可以生成這個形狀的代碼)

知道了上一個方塊的位置,我們只要一個相對於上一個方塊位置的偏移就好了
(0,1) ---- 右
(-1,0) ---- 上
(1,0) ---- 下
(0,-1) -- 左
我們隨機在這四個偏移量中拿出一個,生成下一個物體,但是又不能和上一個物體重疊 ,其實這次生成的偏移量不等於上一次生成偏移量的取反就滿足要求.(在紙上畫一下.任何時候你在紙上畫畫都能很快想明白一些問題,有時會得到不同的靈感)

 

  1. // 隨機的產生物體
  2. void CRBlock::GenerateObject(struct tagObject &obj)
  3. {
  4.     obj.object[0].row = obj.object[3].row = -1;
  5.     obj.object[0].col = obj.object[3].col = 4;
  6.     int x = -2,y = -2; // x,y 爲偏移量
  7.     for (int c = 1; c <= 2; c++)
  8.     {
  9.         MakeRandomOffset(x,y);  // 每次產生的位移不能是上一個方塊的位置
  10.         obj.object[c].row = obj.object[c-1].row + x;
  11.         obj.object[c].col = obj.object[c-1].col + y;
  12.         x=-x,y=-y;  // 上次生成的偏移量的取反
  13.     }
  14.     UpdateLimit(obj);
  15.     MakeRandomOffset(x,y);
  16. /// 這個只是爲了要得到一個 T 形狀的物體而做的.否則把下面的代碼寫到上面的循環中就完成任務了
  17.     if (obj.r-obj.l == 2 || obj.b-obj.t == 2)    
  18.     {
  19.         obj.object[c].row = obj.object[1].row + x;
  20.         obj.object[c].col = obj.object[1].col + y;
  21.     }
  22.     else
  23.     {
  24.         obj.object[c].row = obj.object[2].row + x;
  25.         obj.object[c].col = obj.object[2].col + y;
  26.     }
  27.     obj.color = RANDOM_COLOR;
  28.     UpdateLimit(obj);
  29. }
  30. // 隨即產生一個偏移量.這個偏移量不能是 參數x和y相同的
  31. // 隨即值只有4種可取,即是x和y的絕對值不相同的.(0,0) (+-1,+-1) 的偏移都是不合法的.
  32. void CRBlock::MakeRandomOffset(int &offsetX, int &offsetY)
  33. {
  34.     static const int offset[] = {-1,0,  1,0,    0,-1,   0,1}; 
  35.     int oldX = offsetX;
  36.     int oldY = offsetY;
  37.     do 
  38.     {
  39.         int _i = (rand()%4)*2;
  40.         offsetX = offset[_i];
  41.         offsetY = offset[_i+1];
  42.     } while (offsetX == oldX && offsetY == offsetY);
  43. }
  44. 上面有一個函數還沒有定義 下面就是:
  45. // 更新物體的上下左右邊界
  46. // 左和上取最小
  47. // 右和下取最大
  48. void CRBlock::UpdateLimit(struct tagObject &obj)
  49. {
  50.     obj.l = obj.object[0].col;
  51.     obj.r = obj.object[0].col;
  52.     obj.t = obj.object[0].row;
  53.     obj.b = obj.object[0].row;
  54.     for (int i = 1; i <= 3; i++)
  55.     {
  56.         if (obj.l > obj.object[i].col)
  57.         {
  58.             obj.l = obj.object[i].col;
  59.         }
  60.         if (obj.r < obj.object[i].col)
  61.         {
  62.             obj.r = obj.object[i].col;
  63.         }
  64.         if (obj.t > obj.object[i].row)
  65.         {
  66.             obj.t = obj.object[i].row;
  67.         }
  68.         if (obj.b < obj.object[i].row)
  69.         {
  70.             obj.b = obj.object[i].row;
  71.         }
  72.     }
  73. }

假如你不想要這樣的形狀,你可以調整生成的四個小方塊的相對位置.就這樣簡單幾步你就可以生成任何你想要的形狀.

爽否?

 

三>變形
         上面是喫豆芽,下面就是啃骨頭了.這是本程序的第二個難點
         真的那麼難麼?你認爲變形會如何解決?
         說出來真讓人失望.但又不得不說.這個骨頭如此的脆弱,以至於當初摩拳擦掌準備下一翻苦功夫,栽幾個大跟頭的決心後備都用不上了,像是 下了老勁而一拳打在了棉花上.用錢鍾書在<圍城>裏形容李梓梅見到"情敵"方鴻漸的時候的話說:這是快意的失望!(最近在看<圍城>,錢鍾書真是人才.寫的書太好了.)

 假如我們先找出這四個小方塊最中間的一個,讓它保持位置不變.而讓其餘的三個方塊圍着他向右做90度的旋轉.是不是就是變形了?
         估計有人在這個時候該罵 "他媽的" 了...我當時就是.在紙上座標啊.角啊,餘弦啊,比劃了半天.結果就是這樣就變形了. 真 "他媽的".但是我想用三角函數和角 在一個 x軸向右爲正方向,y軸向下爲正方向的座標象限內(二維數組的邏輯)進行變形.就只是套用幾個三角函數的公式就能完成了.這樣程序將會簡潔許多了.誰數學好,可以做一下,做好別忘了告訴我啊.(恨當初不該花那麼多的時間跑出去玩通宵,數學沒學好,真是後悔的我腸子都青了.童鞋們引以爲戒).現在是0點48分.每這個時候大腦都會脫離我的精神獨立控制四肢,因此廢話多了些.說話意識流了點兒.不要介意.--!!
 下面是變形的代碼:

變形的過程中要注意的事情是:變形後不能覆蓋住原來已經存在的方塊位置.不能超出遊戲區域邊界.
因此一旦變形失敗就重建到原來的狀態.

  1. // 方塊變形
  2. // 變形的實現步驟:
  3. //  找出4個方塊的中心方塊..
  4. // 其他3個方塊圍繞這個方塊向右旋轉90度. 
  5. // 其他3個方塊相對於這個中心方塊的位置只可能時 8中情況,
  6. //  即是它的八個方向(包括對角線上的和水平垂直)
  7. // 這個算法對物體變形的同時可能會造成物體左移,因此規定連續兩次變形就右移一列
  8. void CRBlock::Transform()
  9. {
  10.     // 假如變形後失敗,則重建到原來狀態
  11.     struct tagObject objTemp = Object;
  12.     // 以(row,col)爲中心旋轉
  13.     int l = Object.l;
  14.     int ri = Object.r;
  15.     int t = Object.t;
  16.     int b = Object.b;
  17.     if (ri-l == b-t) // 正方形方塊不變形,這個判斷依據是,只有正方形的長和寬是相等的
  18.     {
  19.         return;
  20.     }
  21.     const int r = (t + b)/2;
  22.     const int c = (l + ri)/2;
  23.     // 變形實現,對4個小方塊依次判斷重新設定位置
  24.     for (int i = 0; i < 4; i++)
  25.     {
  26.         
  27.         int &row = Object.object[i].row;
  28.         int &col = Object.object[i].col;
  29.         if ( row== r && col == c)  // 中心方塊不旋轉
  30.             continue;
  31.         int offsetX = col - c;
  32.         int offsetY = row - r;
  33.         // 分八種情況分別變化
  34.         if (offsetX > 0)  // 在中心方塊右邊
  35.         {
  36.             if (offsetY == 0) // 正右方
  37.             { // 到正下方
  38.                 row = r + offsetX;
  39.                 col = c;
  40.             }
  41.             else if (offsetY > 0) // 在右下方
  42.             {  // 到左下方
  43.                 col = c - offsetX;
  44.             }
  45.             else // 右上方
  46.             { // 到右下方
  47.                 // 列不變
  48.                 row = r - offsetY;
  49.             }
  50.         }
  51.         else if (offsetX == 0) // 和中心點在同一列,offsetY有正負號,恰好可以寫成一個式子
  52.         {
  53.             row = r;
  54.             col = c - offsetY;
  55.         }
  56.         else  // 在中心方塊左邊
  57.         {
  58.             if (offsetY > 0) // 左下
  59.             {// 到左上
  60.                 //列不變
  61.                 row = r - offsetY;
  62.             }
  63.             else if (offsetY == 0)// 正左方
  64.             {// 到正上方
  65.                 row = r + offsetX;
  66.                 col = c;
  67.             }
  68.             else // 左上
  69.             {// 到右上
  70.                 // 行不變
  71.                 col = c - offsetX;
  72.             }
  73.         }
  74.         if (col < 0 || col >= 10 || (row > 0 && block[row][col].bSet))  // 變形失敗
  75.         {
  76.             Object = objTemp;
  77.             return;
  78.         }
  79.     }
  80.     UpdateLimit(Object);  // 更新方塊的邊界    
  81.     if (m_nTimesTransform == 2) // 連續變形了兩次
  82.     {
  83.         Move(RIGHT); // 右移一個單位
  84.         m_nTimesTransform = 0;
  85.     }
  86. }

下次就是控制了.

c,c++,mfc 編程羣: 58698324 歡迎加入

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