告诉大家。cocos2d 简单消除游戏算法 (一)

1. 游戏视频演示



2.三消游戏我的理解


上面视频中的游戏,我做了2个星期时间,只能算个简单Demo,还有bug,特效也几乎没有。感觉三消游戏主要靠磨,越磨越精品。市场上三消游戏已经超级多了。主流的是地图型的,几乎是无尽模式,各种消除特效,各种各样的过关方式,玩起来还是不错的,就是遇到比较难的关卡,要多试几次,运气非常好的时候就过了,不然卡死。
这个游戏真正扩展的地方就是过关模式,还需要整个特殊的地图编辑器,配合策划,不断升级游戏。

3.消除涉及到的简单算法


3.1 生成随机地图算法





有各种各样的地图,这里拿最简单的矩形来说。需求:
1.这个算法要生成一个随机的地图,不能有3个横着相同或者3个竖着相同。
2.这个地图用户移动一步能进行消除(不能是个死地图)

初看到这个需求感觉还是蛮难的,后来想了下第2个需求应该先别管,如果是死地图,再重新生成一张地图就可以了。测试了下,生成死地图的概率非常低。

算法实现的描述:
假设地图的(0,0)在左上角。
非常简单x从上面的最左边开始往右生成,y从最上面直到底部。每次先判断下它的左边两个是否已经同色,还有上面两个是否已经同色,如果同色了,要去掉这个颜色。
假设已经生成的地图是:
2, 3, 3, 4, 1, 3, 2
1, 2, 3, 4, 4, 3, 3
1, 2, 4, 2, 2, X
因为X的左边两个都是2,所以X不能再是2了,它的上面两个都是3,所以X不能再是3了。所以X的结果只能是0,1,4中随机取一个了。

下面是伪代码(是不能运行的真代码):
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. enum MatchItemType{  
  2.    kRedItem = 0,         //0  
  3.    kGreenItem,           //1  
  4.    kBlueItem,            //2  
  5.    kWhiteItem,           //3  
  6.    kOrangeItem           //4  
  7. };  
  8.   
  9. MatchItemType getOneRandomTypeExceptParameter(const MatchItemType& type){  
  10.     MatchItemType allType[5] = {kRedItem, kGreenItem, kBlueItem, kWhiteItem, kOrangeItem};  
  11.     std::vector<matchitemtype> restType;  
  12.     for(int i = 0; i < 5; ++i){  
  13.         if(allType[i] != type){  
  14.             restType.push_back(allType[i]);  
  15.         }  
  16.     }  
  17.     int restSize = restType.size();  
  18.     int randomIndex = rand() % restSize;  
  19.       
  20.     return restType[randomIndex];  
  21. }  
  22.   
  23.   
  24. Array2D<MatchItemType> getOneRandomMapArray(){  
  25.     Array2D<MatchItemType> map = Array2D<MatchItemType>(7, 7);  
  26.     bool findThreeSameInX = false;  
  27.     bool findThreeSameInY = false;  
  28.       
  29.     for(int y = 0; y < 7; ++y){  
  30.         for(int x = 0; x < 7; ++x){  
  31.              MatchItemType randomType = (MatchItemType)(rand() % 5);  
  32.               
  33.             if(x >= 2){  
  34.                 //左边两个是同色  
  35.             if( map.Get(x - 1, y) == map.Get(x - 2, y)){  
  36.                     //need find a new type  
  37.                     findThreeSameInX = true;  
  38.                 }else{  
  39.                     findThreeSameInX = false;  
  40.                 }  
  41.             }else{  
  42.                 findThreeSameInX = false;  
  43.             }  
  44.             if(y >= 2){  
  45.                 //上面两个是同色  
  46.                 if(map.Get(x, y - 1) == map.Get(x, y -2)){  
  47.                     //need find a new type;  
  48.                     findThreeSameInY = true;  
  49.                 }else{  
  50.                     findThreeSameInY = false;  
  51.                 }  
  52.             }else{  
  53.                 findThreeSameInY = false;  
  54.             }  
  55.             if(findThreeSameInX == false && findThreeSameInY == false){  
  56.                //do nothing  
  57.             }else if(findThreeSameInX == true && findThreeSameInY == false){  
  58.                 randomType = getOneRandomTypeExceptParameter(map.Get(x - 1, y));  
  59.             }else if(findThreeSameInX == false && findThreeSameInY == true){  
  60.                 randomType = getOneRandomTypeExceptParameter(map.Get(x, y - 1));  
  61.             }else{  
  62.                 randomType = getOneRandomTypeExceptParameter(map.Get(x - 1, y),  
  63.                                                              map.Get(x, y - 1));  
  64.             }  
  65.               
  66.             map.Set(x, y, randomType);  
  67.         }  
  68.     }  
  69.   
  70.     return map;  
  71. }  
  72. </matchitemtype>  



3.2 判断地图是否是死地图


如果整个地图,用户移动任何一步也不能有消除,就是死地图了,要重新生成地图了。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //case 1  
  2. /[x]//[x]  
  3. //[x][o][x][x][o][x]/  
  4. /[x]//[x]  
  5. /  
  6.   
  7. //case 2  
  8. [x]//  
  9. /[x][o][x]///  
  10. [x]//  
  11. [x]//  
  12. /[x][o][x]///  
  13. [x]//  

这里用注释画了简单的两种情况,注意x的位置。case1 是横着有两个同色的情况,移动一步能消除只有6种可能,左边3种,右边3种。下面是竖着有两个同色的情况,移动一步能消除也是6种情况。上面3种,下面3种。知道了这个,代码就容易了。记得找到一个就直接return。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. vector<MatchItem*> getThreeMatchItemCanRemoveByOneStep(const Array2D<MatchItem*> & map){  
  2.     vector<MatchItem*> result;  
  3.       
  4.     int maxX = 7;  
  5.     int maxY = 7;  
  6.       
  7.       
  8.     for(int y = 0; y < maxY; ++y){  
  9.         for(int x = 0; x < maxX; ++x){  
  10.             if(x + 1 < maxX){  
  11.                 //case 1  
  12.                 if(map.Get(x, y)->getType() == map.Get(x + 1, y)->getType()){  
  13.                     MatchItemType currentType = map.Get(x, y)->getType();  
  14.                     //check 6 item, one move one step can combine three same item  
  15.                     if(x - 2 >= 0){  
  16.                         if(map.Get(x - 2, y)->getType() == currentType){  
  17.                             //find one  
  18.                             result.push_back(map.Get(x, y));  
  19.                             result.push_back(map.Get(x + 1, y));  
  20.                             result.push_back(map.Get(x - 2, y));  
  21.                             return result;  
  22.                         }  
  23.                     }  
  24.                     if(x - 1 >= 0 && y - 1 >= 0){  
  25.                         if(map.Get(x - 1, y - 1)->getType() == currentType){  
  26.                             //find one  
  27.                             result.push_back(map.Get(x, y));  
  28.                             result.push_back(map.Get(x + 1, y));  
  29.                             result.push_back(map.Get(x - 1, y - 1));  
  30.                             return result;  
  31.                         }  
  32.                     }  
  33.                     if(x + 2 < maxX && y - 1 >= 0){  
  34.                         if(map.Get(x + 2, y - 1)->getType() == currentType){  
  35.                             //find one  
  36.                             result.push_back(map.Get(x, y));  
  37.                             result.push_back(map.Get(x + 1, y));  
  38.                             result.push_back(map.Get(x + 2, y - 1));  
  39.                             return result;  
  40.                         }  
  41.                     }  
  42.                     if(x + 3 < maxX){  
  43.                         if(map.Get(x + 3, y)->getType() == currentType){  
  44.                             //find one  
  45.                             result.push_back(map.Get(x, y));  
  46.                             result.push_back(map.Get(x + 1, y));  
  47.                             result.push_back(map.Get(x + 3, y));  
  48.                             return result;  
  49.                         }  
  50.                     }  
  51.                     if(x + 2 < maxX && y + 1 < maxY){  
  52.                         if(map.Get(x + 2, y + 1)->getType() == currentType){  
  53.                             //find one  
  54.                             result.push_back(map.Get(x, y));  
  55.                             result.push_back(map.Get(x + 1, y));  
  56.                             result.push_back(map.Get(x + 2, y + 1));  
  57.                             return result;  
  58.                         }  
  59.                     }  
  60.                     if(x - 1 >= 0 && y + 1 < maxY){  
  61.                         if(map.Get(x - 1, y + 1)->getType() == currentType){  
  62.                             //find one  
  63.                             result.push_back(map.Get(x, y));  
  64.                             result.push_back(map.Get(x + 1, y));  
  65.                             result.push_back(map.Get(x - 1, y + 1));  
  66.                             return result;  
  67.                         }  
  68.                     }  
  69.                 }  
  70.   
  71.             }  
  72.             if(y + 1 < maxY){  
  73.                 MatchItemType currentType = map.Get(x, y)->getType();  
  74.                 //case 2  
  75.                 if(map.Get(x, y)->getType() == map.Get(x, y + 1)->getType()){  
  76.                     if(y - 2 >= 0){  
  77.                         if(map.Get(x, y - 2)->getType() == currentType){  
  78.                             //find one  
  79.                             result.push_back(map.Get(x, y));  
  80.                             result.push_back(map.Get(x, y + 1));  
  81.                             result.push_back(map.Get(x, y - 2));  
  82.                             return result;  
  83.                         }  
  84.                     }  
  85.                     if(x + 1 < maxX && y - 1 >= 0){  
  86.                         if(map.Get(x + 1, y - 1)->getType() == currentType){  
  87.                             //find one  
  88.                             result.push_back(map.Get(x, y));  
  89.                             result.push_back(map.Get(x, y + 1));  
  90.                             result.push_back(map.Get(x + 1, y - 1));  
  91.                             return result;  
  92.                         }  
  93.                     }  
  94.                     if(x + 1 < maxX && y + 2 < maxY){  
  95.                         if(map.Get(x + 1, y + 2)->getType() == currentType){  
  96.                             //find one  
  97.                             result.push_back(map.Get(x, y));  
  98.                             result.push_back(map.Get(x, y + 1));  
  99.                             result.push_back(map.Get(x + 1, y + 2));  
  100.                             return result;  
  101.                         }  
  102.                     }  
  103.                     if(y + 3 < GameGlobal::xMapCount){  
  104.                         if(map.Get(x, y + 3)->getType() == currentType){  
  105.                             //find one  
  106.                             result.push_back(map.Get(x, y));  
  107.                             result.push_back(map.Get(x, y + 1));  
  108.                             result.push_back(map.Get(x, y + 3));  
  109.                             return result;  
  110.                         }  
  111.                     }  
  112.                     if(x - 1 >= 0 && y + 2 < maxY){  
  113.                         if(map.Get(x - 1, y + 2)->getType() == currentType){  
  114.                             //find one  
  115.                             result.push_back(map.Get(x, y));  
  116.                             result.push_back(map.Get(x, y + 1));  
  117.                             result.push_back(map.Get(x - 1, y + 2));  
  118.                             return result;  
  119.                         }  
  120.                     }  
  121.                     if(x - 1 >= 0 && y - 1 >= 0){  
  122.                         if(map.Get(x - 1, y + 1)->getType() == currentType){  
  123.                             //find one  
  124.                             result.push_back(map.Get(x, y));  
  125.                             result.push_back(map.Get(x, y + 1));  
  126.                             result.push_back(map.Get(x - 1, y - 1));  
  127.                             return result;  
  128.                         }  
  129.                     }  
  130.                       
  131.                 }  
  132.               
  133.             }  
  134.               
  135.         }  
  136.     }  
  137.       
  138.     return result;  
  139. }  

看起来是有点复杂,穷举了12种情况,这个算法应该速度很快的。还有个地方要用到这个算法,就是在消除游戏中,用户很久时间没有进行消除了,要给提示。就用这个算法找到哪3个可以移动一步进行消除。


算法先到这里... 后续有时间再更新...

http://www.waitingfy.com/archives/1335

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值