cocos2d-x3.6 连连看连通算法

我的博客:http://blog.csdn.net/dawn_moon

上一章讲了连连看游戏的主要逻辑,连通算法并有讲如何实现。

这个连连看没有使用广度优先搜索算法,采用的是一种比较有技巧的算法,参见前面章节。

大致分为几个部分:

  1. 直连通
  2. 两个点X轴扩展后可以直连通
  3. 两个点Y轴扩展后可以直连通

看下连接函数


bool GameScene::link(cocos2d::Vec2 v1, cocos2d::Vec2 v2)
{
    if (v1.equals(v2)) {
        return false;
    }
    // 路径点集,是一个vector
    mPath.clear();

    // 判断点击的两个点是不是图案一致
    if (mMap[(int)v1.x][(int)v1.y] == mMap[(int)v2.x][(int)v2.y]) {
        // 直连
        if (linkD(v1, v2)) {
            mPath.push_back(v1);
            mPath.push_back(v2);
            return true;
        }

        // 一个拐角,对角可直连
        auto p = Vec2(v1.x, v2.y);
        if (mMap[(int)p.x][(int)p.y] == 0) {
            if (linkD(v1, p) && linkD(p, v2)) {
                mPath.push_back(v1);
                mPath.push_back(p);
                mPath.push_back(v2);
                return true;
            }
        }

        // 一个拐角,对角可直连
        p = Vec2(v2.x, v1.y);
        if (mMap[(int)p.x][(int)p.y] == 0) {
            if (linkD(v1, p) && linkD(p, v2)) {
                mPath.push_back(v1);
                mPath.push_back(p);
                mPath.push_back(v2);
                return true;
            }
        }

        // X扩展,判断是否有可直连的点
        expandX(v1, p1E);
        expandX(v2, p2E);

        for (auto pt1 : p1E) {
            for (auto pt2 : p2E) {
                if (pt1.x == pt2.x) {
                    if (linkD(pt1, pt2)) {
                        mPath.push_back(v1);
                        mPath.push_back(pt1);
                        mPath.push_back(pt2);
                        mPath.push_back(v2);
                        return true;
                    }
                }
            }
        }

        // Y扩展,判断是否有可直连的点
        expandY(v1, p1E);
        expandY(v2, p2E);
        for (auto pt1 : p1E) {
            for (auto pt2 : p2E) {
                if (pt1.y == pt2.y) {
                    if (linkD(pt1, pt2)) {
                        mPath.push_back(v1);
                        mPath.push_back(pt1);
                        mPath.push_back(pt2);
                        mPath.push_back(v2);
                        return true;
                    }
                }
            }
        }

        return false;
    }

    return false;
}

连通函数的基础是直连通,两个点,最后都要转化成是否可直连,来看这个函数:

bool GameScene::linkD(Vec2 v1, Vec2 v2)
{
    // X坐标一致,逐个扫描Y坐标,中间如果都是通路,那么可以直连
    if (v1.x == v2.x) {
        int y1 = MIN(v1.y, v2.y);
        int y2 = MAX(v2.y, v2.y);
        bool flag = true;
        for (int y = y1 + 1; y < y2; y++) {
            if (mMap[(int)v1.x][y] != 0) {
                flag = false;
                break;
            }
        }

        if (flag) {
            return true;
        }
    }

    // Y坐标一致,逐个扫描X坐标,中间如果都是通路,那么可以直连
    if (v1.y == v2.y) {
        int x1 = MIN(v1.x, v2.x);
        int x2 = MAX(v1.x, v2.x);
        bool flag = true;
        for (int x = x1 + 1; x < x2; x++) {
            if (mMap[x][(int)v1.y] != 0) {
                flag = false;
                break;
            }
        }
        if (flag) {
            return true;
        }
    }

    return false;
}

注意这里的坐标都是地图坐标,就是第几格第几格这样的整数。

再来看下扩展函数:

void GameScene::expandX(Vec2 v, std::vector<Vec2> &vector)
{
    // 注意第二个参数vector是传的引用
    vector.clear();

    // X轴扩展到边界,如果都是空的就将扩展的点放入容器
    for (int x = (int)v.x + 1; x < xCount; x++) {
        if (mMap[x][(int)v.y] != 0) {
            break;
        }
        vector.push_back(Vec2(x, (int)v.y));
    }

    // Y周扩展到边界,如果都是空的就将扩展的点放入容器
    for (int x = (int)v.x - 1; x >= 0; x--) {
        if (mMap[x][(int)v.y] != 0) {
            break;
        }
        vector.push_back(Vec2(x, (int)v.y));
    }
}

void GameScene::expandY(Vec2 v, std::vector<Vec2> &vector)
{
    vector.clear();

    for (int y = (int)v.y + 1; y < yCount; y++) {
        if (mMap[(int)v.x][y] != 0) {
            break;
        }
        vector.push_back(Vec2((int)v.x, y));
    }

    for (int y = (int)v.y - 1; y >= 0 ; y--) {
        if (mMap[(int)v.x][y] != 0) {
            break;
        }
        vector.push_back(Vec2((int)v.x, y));
    }
}

注意这两个函数的第二个参数是传引用,为什么要这样做。

因为我不想用函数返回一个容器的副本来用,这两个函数都是返回void,传引用直接操作变量本身,不需要返回值。

连通函数会判断两个点是否连通,如果连通,讲连通的点放入容器,后续会用这个容器里的点来绘制连通路线。

下一节讲如何画线。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-07 10:16:13

cocos2d-x3.6 连连看连通算法的相关文章

连连看核心算法

在学习ios开发的过程中,用一般的方式用oc写了一个练练看的小游戏,没有用到cocos2d编程.自己做的思路如下: 程序的关键在于判断用户连续点击的两个图案能否消除.两个图片可以消除的条件有两个: (1) 图案相同 (2) 图案间连线的转角数不得超过2 所以连通的算法分为: (1) 直连型 (2) 一个拐角连通 (3) 两个拐角连通 将图片所在的view看为一个棋盘,然后根据棋盘的行列进行相关的判断. 首先探讨下直连型:分为水平直连(横坐标相等)和竖直直连(纵坐标相等),且两者之间没有其他的图案

关于《连连看》的算法研究和演示Demo

连连看曾经是一款非常受欢迎的游戏,同时它也是一款比较古老的游戏.看到这里你千万不要认为本篇文章打算讨论<连连看>的历史以及它取得的丰功伟绩.恰恰相反,在这篇文章中我们打算讨论该游戏背后的实现思想,包括它定义的游戏规则,以及游戏的实现算法.作为应用,我们还将利用Java代码实现一个通用的<连连看>算法,并使用Java Swing框架创建一个演示实例. 1<连连看>的游戏规则是如何定义的? 连连看的游戏界面和游戏规则都非常简单.游戏界面可以简单看作一个具有M×N个单元格的棋

Java版连连看

连连看大家应该都玩过,不多说直接上一个做好的界面截图吧,所有的功能都在上面的,要做的就只是如何去实现它们了. 差不多就是这个样子.先说一下大致的思路吧.首先编写基本的界面:把什么按钮啊,表格啊什么的都画上去.然后就是编写事件处理类,因为操作使用鼠标,所以加上鼠标监听.然后获取点击的坐标,根据坐标得出图片在数组中的位置.接着创建一个类,实现连连看消除的算法.这样就基本上可以开始游戏了.然后实现排行榜按钮和存档按钮的基本功能.最后加上一个线程类,用于处理倒计时.下面的介绍也基于这个顺序. 界面实现:

匈牙利算法(二分图)

                                                                                                            ---------------------------------------------------------------------题材大多来自网络,本篇由神犇整理 基本概念—二分图 二分图:是图论中的一种特殊模型.若能将无向图G=(V,E)的顶点V划分为两个交集为空的顶点集,

MVC 编程笔记2

转载自http://blog.csdn.net/kenkao/article/details/50291991 作者:吴秦 出处:http://www.cnblogs.com/skynet/ 本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接). 参考资料 [1]     PureMVC官方网站:www.puremvc.org [2]     Wikipedia:http://zh.wikipedia.org/zh-cn/MVC [3]

连通性问题

参考:Robert Sedgewick,<算法:C语言实现>第1章 问题描述 假设给定整数对的一个序列,其中每个整数表示某类型的一个对象,我们想要说明整数对p-q表示“p连接到q”.假设“连通”关系是可传递的:也就是说如果p和q之间连通,q和r之间连通,那么p和r也是连通的.我们的目标是写一个过滤集合中的无关对的程序.程序的输入为整数对p-q,如果已经看到的数对中并不隐含这p连通到q,那么就输出该对.如果前面输入大数对中隐含着p连通到q,那么程序应该忽略p-q,并应该继续输入下一对.如图1-1

opencv FloodFill(漫水填充)和物体选取

简介 本篇主要是介绍opencv的FloodFill(漫水填充)和基于它实现的物体选取. FloodFill使用 FloodFill函数 C++: int floodFill(InputOutputArray image, InputOutputArray mask, Point seedPoint, Scalar newVal, Rect* rect=0, Scalar loDiff=Scalar(), Scalar upDiff=Scalar(), int flags=4 ); InputO

作业七:每日立会(7)

参加会议人员:全组六人 到今天为止团队任务已经经过整整一周了,我们今天立会讨论了关于今后任务的主要内容,前一周我们主要完成了主要界面的设计以及一系列资料的收集与整理,现在主要的任务是进行功能的设计,同时我们也要利用收集的资料来完善和改进团队设计. 同时还存在着一些问题,素材处理的问题,连连看的算法的设置,为了提高游戏的可玩性我们还想添加一些有特殊功能的连连看方式,但是影响不大总体而言我们还是按照规划好的进度开始实施! 心得:在这一周的团队合作过程中我们学到了很多,不仅是为人处事上懂了很多,同时也

分享几个cocos2dx的小游戏

先上几个自己写的,因为最近要用cocos2dx,所以就边学边开发几个小游戏玩玩,有捕鱼,连连看,还有打地鼠!都不算完整的项目,不过拿来学习还是可以的,或者在基础上再二次开发,扩展自己! 1:捕鱼的 先来几张效果图: 就是这样一个项目,不到鱼儿之后,放到左下角的鱼缸里,就可以获得分数,可以做成捕蜻蜓或者类似于捕鱼达人那种! 下载地址:http://pan.baidu.com/s/1i3lDyM5 2:打地鼠 先来几张效果图: 这个游戏就比较简单,当时还是没有做太多的优化,就简单做了一个demo,有