• cocos2d 消除类游戏简单的算法 (一)


    1. 游戏视频演示



    2.三消游戏我的理解


    上面视频中的游戏。我做了2个星期时间,仅仅能算个简单Demo,还有bug。特效也差点儿没有。感觉三消游戏主要靠磨。越磨越精品。

    市场上三消游戏已经超级多了。主流的是地图型的。差点儿是无尽模式。各种消除特效。各种各样的过关方式,玩起来还是不错的,就是遇到比較难的关卡,要多试几次,运气很好的时候就过了,不然卡死。

    这个游戏真正扩展的地方就是过关模式,还须要整个特殊的地图编辑器。配合策划,不断升级游戏。

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


    3.1 生成随机地图算法





    有各种各样的地图。这里拿最简单的矩形来说。需求:
    1.这个算法要生成一个随机的地图,不能有3个横着同样或者3个竖着同样。

    2.这个地图用户移动一步能进行消除(不能是个死地图)

    初看到这个需求感觉还是蛮难的。后来想了下第2个需求应该先别管,假设是死地图。再又一次生成一张地图就能够了。測试了下,生成死地图的概率很低。

    算法实现的描写叙述:
    假设地图的(0,0)在左上角。

    很easyx从上面的最左边開始往右生成,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中随机取一个了。


    以下是伪代码(是不能执行的真代码):
    enum MatchItemType{
       kRedItem = 0,         //0
       kGreenItem,           //1
       kBlueItem,            //2
       kWhiteItem,           //3
       kOrangeItem           //4
    };
    
    MatchItemType getOneRandomTypeExceptParameter(const MatchItemType& type){
        MatchItemType allType[5] = {kRedItem, kGreenItem, kBlueItem, kWhiteItem, kOrangeItem};
        std::vector restType;
        for(int i = 0; i < 5; ++i){
            if(allType[i] != type){
                restType.push_back(allType[i]);
            }
        }
        int restSize = restType.size();
        int randomIndex = rand() % restSize;
        
        return restType[randomIndex];
    }
    
    
    Array2D<MatchItemType> getOneRandomMapArray(){
        Array2D<MatchItemType> map = Array2D<MatchItemType>(7, 7);
        bool findThreeSameInX = false;
        bool findThreeSameInY = false;
        
        for(int y = 0; y < 7; ++y){
            for(int x = 0; x < 7; ++x){
                 MatchItemType randomType = (MatchItemType)(rand() % 5);
                
                if(x >= 2){
                    //左边两个是同色
    	        if( map.Get(x - 1, y) == map.Get(x - 2, y)){
                        //need find a new type
                        findThreeSameInX = true;
                    }else{
                        findThreeSameInX = false;
                    }
                }else{
                    findThreeSameInX = false;
                }
                if(y >= 2){
                    //上面两个是同色
                    if(map.Get(x, y - 1) == map.Get(x, y -2)){
                        //need find a new type;
                        findThreeSameInY = true;
                    }else{
                        findThreeSameInY = false;
                    }
                }else{
                    findThreeSameInY = false;
                }
                if(findThreeSameInX == false && findThreeSameInY == false){
                   //do nothing
                }else if(findThreeSameInX == true && findThreeSameInY == false){
                    randomType = getOneRandomTypeExceptParameter(map.Get(x - 1, y));
                }else if(findThreeSameInX == false && findThreeSameInY == true){
                    randomType = getOneRandomTypeExceptParameter(map.Get(x, y - 1));
                }else{
                    randomType = getOneRandomTypeExceptParameter(map.Get(x - 1, y),
                                                                 map.Get(x, y - 1));
                }
                
                map.Set(x, y, randomType);
            }
        }
    
        return map;
    }
    



    3.2 推断地图是否是死地图


    假设整个地图,用户移动不论什么一步也不能有消除,就是死地图了,要又一次生成地图了。

    //case 1
    /////[x]//////[x]////////
    //[x][o][x][x][o][x]/////
    /////[x]//////[x]////////
    /////////////////////////
    
    //case 2
    ////////[x]//////////////
    /////[x][o][x]///////////
    ////////[x]//////////////
    ////////[x]//////////////
    /////[x][o][x]///////////
    ////////[x]//////////////

    这里用凝视画了简单的两种情况,注意x的位置。

    case1 是横着有两个同色的情况,移动一步能消除仅仅有6种可能,左边3种,右边3种。以下是竖着有两个同色的情况。移动一步能消除也是6种情况。上面3种。以下3种。

    知道了这个,代码就easy了。记得找到一个就直接return。

    vector<MatchItem*> getThreeMatchItemCanRemoveByOneStep(const Array2D<MatchItem*> & map){
        vector<MatchItem*> result;
        
        int maxX = 7;
        int maxY = 7;
        
        
        for(int y = 0; y < maxY; ++y){
            for(int x = 0; x < maxX; ++x){
                if(x + 1 < maxX){
                    //case 1
                    if(map.Get(x, y)->getType() == map.Get(x + 1, y)->getType()){
                        MatchItemType currentType = map.Get(x, y)->getType();
                        //check 6 item, one move one step can combine three same item
                        if(x - 2 >= 0){
                            if(map.Get(x - 2, y)->getType() == currentType){
                                //find one
                                result.push_back(map.Get(x, y));
                                result.push_back(map.Get(x + 1, y));
                                result.push_back(map.Get(x - 2, y));
                                return result;
                            }
                        }
                        if(x - 1 >= 0 && y - 1 >= 0){
                            if(map.Get(x - 1, y - 1)->getType() == currentType){
                                //find one
                                result.push_back(map.Get(x, y));
                                result.push_back(map.Get(x + 1, y));
                                result.push_back(map.Get(x - 1, y - 1));
                                return result;
                            }
                        }
                        if(x + 2 < maxX && y - 1 >= 0){
                            if(map.Get(x + 2, y - 1)->getType() == currentType){
                                //find one
                                result.push_back(map.Get(x, y));
                                result.push_back(map.Get(x + 1, y));
                                result.push_back(map.Get(x + 2, y - 1));
                                return result;
                            }
                        }
                        if(x + 3 < maxX){
                            if(map.Get(x + 3, y)->getType() == currentType){
                                //find one
                                result.push_back(map.Get(x, y));
                                result.push_back(map.Get(x + 1, y));
                                result.push_back(map.Get(x + 3, y));
                                return result;
                            }
                        }
                        if(x + 2 < maxX && y + 1 < maxY){
                            if(map.Get(x + 2, y + 1)->getType() == currentType){
                                //find one
                                result.push_back(map.Get(x, y));
                                result.push_back(map.Get(x + 1, y));
                                result.push_back(map.Get(x + 2, y + 1));
                                return result;
                            }
                        }
                        if(x - 1 >= 0 && y + 1 < maxY){
                            if(map.Get(x - 1, y + 1)->getType() == currentType){
                                //find one
                                result.push_back(map.Get(x, y));
                                result.push_back(map.Get(x + 1, y));
                                result.push_back(map.Get(x - 1, y + 1));
                                return result;
                            }
                        }
                    }
    
                }
                if(y + 1 < maxY){
                    MatchItemType currentType = map.Get(x, y)->getType();
                    //case 2
                    if(map.Get(x, y)->getType() == map.Get(x, y + 1)->getType()){
                        if(y - 2 >= 0){
                            if(map.Get(x, y - 2)->getType() == currentType){
                                //find one
                                result.push_back(map.Get(x, y));
                                result.push_back(map.Get(x, y + 1));
                                result.push_back(map.Get(x, y - 2));
                                return result;
                            }
                        }
                        if(x + 1 < maxX && y - 1 >= 0){
                            if(map.Get(x + 1, y - 1)->getType() == currentType){
                                //find one
                                result.push_back(map.Get(x, y));
                                result.push_back(map.Get(x, y + 1));
                                result.push_back(map.Get(x + 1, y - 1));
                                return result;
                            }
                        }
                        if(x + 1 < maxX && y + 2 < maxY){
                            if(map.Get(x + 1, y + 2)->getType() == currentType){
                                //find one
                                result.push_back(map.Get(x, y));
                                result.push_back(map.Get(x, y + 1));
                                result.push_back(map.Get(x + 1, y + 2));
                                return result;
                            }
                        }
                        if(y + 3 < GameGlobal::xMapCount){
                            if(map.Get(x, y + 3)->getType() == currentType){
                                //find one
                                result.push_back(map.Get(x, y));
                                result.push_back(map.Get(x, y + 1));
                                result.push_back(map.Get(x, y + 3));
                                return result;
                            }
                        }
                        if(x - 1 >= 0 && y + 2 < maxY){
                            if(map.Get(x - 1, y + 2)->getType() == currentType){
                                //find one
                                result.push_back(map.Get(x, y));
                                result.push_back(map.Get(x, y + 1));
                                result.push_back(map.Get(x - 1, y + 2));
                                return result;
                            }
                        }
                        if(x - 1 >= 0 && y - 1 >= 0){
                            if(map.Get(x - 1, y + 1)->getType() == currentType){
                                //find one
                                result.push_back(map.Get(x, y));
                                result.push_back(map.Get(x, y + 1));
                                result.push_back(map.Get(x - 1, y - 1));
                                return result;
                            }
                        }
                        
                    }
                
                }
                
            }
        }
        
        return result;
    }
    

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


    算法先到这里... 兴许有时间再更新...

    提交给苹果,审核竟然能通过

    第一个是IPhone 下载地址。第二个是android的。点击跳转链接。或者扫描二维码。

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


    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    随机森林算法参数调优
    BAYES和朴素BAYES
    阿里云 金融接口 token PHP
    PHP mysql 按时间分组 表格table 跨度 rowspan
    MySql按周,按月,按日分组统计数据
    PHP 获取今日、昨日、本周、上周、本月的等等常用的起始时间戳和结束时间戳的时间处理类
    thinkphp5 tp5 会话控制 session 登录 退出 检查检验登录 判断是否应该跳转到上次url
    微信 模板消息
    php 腾讯 地图 api 计算 坐标 两点 距离 微信 网页 WebService API
    php添加http头禁止浏览器缓存
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4869845.html
Copyright © 2020-2023  润新知