連連看核心算法


在學習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];
        }

 

參考博客

參考博客

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM