zoukankan      html  css  js  c++  java
  • 连连看核心算法

    在学习ios开发的过程中,用一般的方式用oc写了一个练练看的小游戏,没有用到cocos2d编程.自己做的思路如下:

    程序的关键在于判断用户连续点击的两个图案能否消除。两个图片可以消除的条件有两个: 

    (1) 图案相同 

    (2) 图案间连线的转角数不得超过2

    所以连通的算法分为:

    (1) 直连型 (2) 一个拐角连通 (3) 两个拐角连通

    将图片所在的view看为一个棋盘,然后根据棋盘的行列进行相关的判断.

    首先探讨下直连型:分为水平直连(横坐标相等)和竖直直连(纵坐标相等),且两者之间没有其他的图案.

    可以看出A -- B横纵向连通,oc代码如下:(dict是根据图案的坐标,判断该位置是否有图案,有的话值为1,否则为0)

     /** 1.直连型 */
     - (BOOL)verticalWith:(CGPoint)pointA point:(CGPoint)pointB{
          
          int rowA = [[NSString stringWithFormat:@"%f",pointA.x] intValue];
          int colA = [[NSString stringWithFormat:@"%f",pointA.y] intValue];
          
          int rowB = [[NSString stringWithFormat:@"%f",pointB.x] intValue];
          int colB = [[NSString stringWithFormat:@"%f",pointB.y] intValue];
          
         //1.直连型
         if (rowA == rowB){//同一行
             int minCol = colA < colB ? colA : colB;//最小列号
             int maxCol = colA > colB ? colA : colB;//最大列号
             
             for (int j = minCol+1; j<maxCol; j++) {
                 CGPoint point = CGPointMake(rowA, j);
                 NSString *key = NSStringFromCGPoint(point);
                 if ([self.dict[key] intValue] != 0) {//两个图案之间存在其他的图案
                     return NO;
                 }
             }
             return YES;
             
         }else if(colA == colB){//同一列
             int minRow = rowA < rowB ? rowA : rowB;//最小行号
             int maxRow = rowA > rowB ? rowA : rowB;//最大行号
             for (int i = minRow+1; i<maxRow; i++) {
                 CGPoint point = CGPointMake(i, colA);
                 NSString *key = NSStringFromCGPoint(point);
                 if ([self.dict[key] intValue] != 0) {//两个图案之间存在其他的图案
                     return NO;
                }
             }
            return YES;
         } else{
             return NO;
         }
     }

    2. 一折连通:其实相当于两个图片划出一个矩形,这两个图片是一对对角顶点,另外两个顶点如果可以同时和这两个棋子直连,那就说明可以"一折连通"。

    找出C,D两点,然后判断C,D处是否有图案,若存在图案直接返回no.如果其中一个没有,判断与A,B是否连通

    /** 2.一折型 */
    - (BOOL)oneCorner:(CGPoint)pointA button:(CGPoint)pointB{
        
        //找出拐角点的坐标
        CGPoint pointC = CGPointMake(pointA.x, pointB.y);
        
        CGPoint pointD = CGPointMake(pointB.x, pointA.y);
    
        //判断C点是否有元素
        if ([self.dict[NSStringFromCGPoint(pointC)] intValue] == 0) {
            
            return [self verticalWith:pointA point:pointC] && [self verticalWith:pointC point:pointB];
        }
        //判断D点是否有元素
        if ([self.dict[NSStringFromCGPoint(pointD)] intValue] == 0) {
            
            return [self verticalWith:pointA point:pointD] && [self verticalWith:pointD point:pointB];
        }
        
        //其他情况
        return NO;
    }

    3 两折连通:判断图案A与图案B能否经过有两个转角的路径连通,实质上可以转化为判断能否找到一个点C,这个C点与A可以直线连通,且C与B可以通过有一个转角的路径连通。若能找到这样一个C点,那么A与B就可以经过有两个转角的路径连通 。 

      判断是否经两个转角连通的算法需要做两个方向上的扫描:水平扫描和垂直扫描。 

      水平扫描。如下图所示,为了判断A,B能否通过2个转角连通,则从A开始在水平方向上向左右扫描,并判断经过的点能否与B点经过1个转角连通。显然C点能与B点经1个转角连通,故A,B能经2个转角连通。

    垂直扫描。如下图所示,为了判断A,B能否通过2个转角连通,则从A开始在垂直方向上下扫描,并判断经过的点能否与B点经过1个转角连通。显然C点能与B点经1个转角连通,故A,B能经2个转角连通。

    oc代码:

    /** 3.两折型 */
    /* 判断A和B是否两折连通
     * (1) 水平方向: 从A水平方向左右扫描,并判断经过的点能否与B通过1折连通;
     * (2) 垂直方向: 从A垂直方向上下扫描,并判断经过的点能否与B通过1折连通;
     */
    - (BOOL)twoCorner:(CGPoint)pointA button:(CGPoint)pointB maxRow:(int)maxRow maxCol:(int)maxCol{
        //得到A点的所在行列
        int rowA = [[NSString stringWithFormat:@"%f",pointA.x] intValue];
        int colA = [[NSString stringWithFormat:@"%f",pointA.y] intValue];
        
        //初始化C点
        CGPoint pointC = CGPointMake(0, 0);
        
        // 1. 水平方向(列)
        // 1.1 左
        if (colA != 0){//A点不在最左边
            for (int i = colA - 1; i >= 0; i--) {
                pointC = CGPointMake(rowA, i);
                //判断C点是否为空
                if ([self.dict[NSStringFromCGPoint(pointC)] intValue] == 0) {
                    if ([self oneCorner:pointC button:pointB]){
                        return YES;
                    }
                }else{//不为空的话,直接跳出
                    break;
                }
            }
        }
    
        // 1.2 右
        if (colA != maxCol - 1){//A点不在最右边
            for (int i = colA + 1; i < maxCol; i++) {
                pointC = CGPointMake(rowA, i);
                //判断C点是否为空
                if ([self.dict[NSStringFromCGPoint(pointC)] intValue] == 0) {
                    if ([self oneCorner:pointC button:pointB]){
                        return YES;
                    }
                }else{//不为空的话,直接跳出
                    break;
                }
            }
        }
        
        // 2. 垂直方向(行)
        // 2.1 上
        if (rowA != 0){//A点不在最上边
            for (int i = rowA - 1; i >= 0; i--) {
                pointC = CGPointMake(i, colA);
                //判断C点是否为空
                if ([self.dict[NSStringFromCGPoint(pointC)] intValue] == 0) {
                    if ([self oneCorner:pointC button:pointB]){
                        return YES;
                    }
                }else{//不为空的话,直接跳出
                    break;
                }
            }
        }
        
        // 2.2 下
        if (rowA != maxRow - 1){//A点不在最下边
            for (int i = rowA + 1; i < maxRow; i++) {
                pointC = CGPointMake(i, colA);
                //判断C点是否为空
                if ([self.dict[NSStringFromCGPoint(pointC)] intValue] == 0) {
                    if ([self oneCorner:pointC button:pointB]){
                        return YES;
                    }
                }else{//不为空的话,直接跳出
                    break;
                }
            }
        }
    
        //其他情况
        return NO;
    }

    总的调用函数来调用:

      /** 1.直连型 */
            if ([self verticalWith:pointA point:pointB]) {//是否存在直线,存在返回yes
                //连接成功
                return YES;
            }
            
            /** 2.一折型 */
            if([self oneCorner:pointA button:pointB]){
                return YES;
            }else{
                /** 3.两折型 */
                return [self twoCorner:pointA button:pointB maxRow:rowCount maxCol:columnCount];
            }

    参考博客

    参考博客

    不积跬步,无以至千里;不积小流,无以成江海。
  • 相关阅读:
    vim操作
    brew安装
    pycharm工程包导入问题
    mongodb的更新语句
    mongodb的增加和删除
    Mongodb中 数据库和集合的创建与删除
    mongodb服务器启动
    mac 根目录下新建文件夹并赋予权限
    常用的python标准库
    mac显示隐藏文件夹和文件
  • 原文地址:https://www.cnblogs.com/xiaocai-ios/p/5406515.html
Copyright © 2011-2022 走看看