MFC实现俄罗斯方块二

本文介绍了如何使用MFC实现俄罗斯方块的物体生成算法,通过特定的行列值限制生成物体,并确保不会产生重叠。然后详细讨论了物体的变形过程,通过以中心方块为基准进行90度旋转来实现。文章提供了相应的代码示例,解释了变形过程中需要注意的边界条件和失败时的处理策略。
摘要由CSDN通过智能技术生成

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 欢迎加入

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值