连连看核心算法

在学习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];
        }

 

参考博客

参考博客

 

posted @ 2016-04-19 00:16  zsper  阅读(3776)  评论(0编辑  收藏  举报