方块总动员消图算法(Objective-c)

之前贴过一个连连看两图连通的检测算法,今天再贴一个方块总动员消图算法,坐标系如下图:

方块总动员消图算法(Objective-c)_第1张图片

方块总动员玩法很简单,点到同类型方块的十字交叉点便可消除,这里我用Objective-c实现了一个,由于之前连连看,我没有把游戏的初始化代码贴出来,其实这两者初始化有点类似我就在这里加上,代码如下:

//初始化函数
-(void) intiGameConfig
{
    BLANK_STATE=-1;//表示空白状态
    W=30;//图片边长
    m_nCol=10;//列数
    m_nRow=12;//行数
    m_count=m_nCol*m_nRow;//总图数
    picNum=8;//图种类数
    havaPicNum=80;//有图数
    emptyPic=m_count-havaPicNum;//空白数
    SameNum=havaPicNum/picNum;//每种图有10张
    picStartNo=1;//图片起始编号
    
	//图片数组,列*行,长度为120,0-9第一行,10-19第二行,
    m_map=(int *)malloc(sizeof(int)*m_nCol*m_nRow);
	//初始化地图,将地图中所有方块区域位置置为空方块状态
    for(int i=0;i<m_count;i++)
    {
        m_map[i]=BLANK_STATE;
    }
    //将所有的图片种类放进一个临时的地图tmpMap中
    NSMutableArray *temp_map=[[NSMutableArray alloc] init];
    //填充图名字
    for (int i=picStartNo; i<picNum+picStartNo; i++) {
        for (int j=0; j<SameNum; j++) {
            [temp_map addObject:[NSNumber numberWithInt:i]];
        }
    }
    //填充空白
    for (int i=0; i<emptyPic; i++) {
        [temp_map addObject:[NSNumber numberWithInt:-1]];
    }
    
    //每次从上面的临时地图tmp_Map中取走(获取后并在临时地图删除)
    int nIndex=-1;
    for (int i=0; i<m_count; i++) {
        nIndex=arc4random()%[temp_map count];
        //CCLOG(@"arc4random:%i",nIndex);
        m_map[i]=[[temp_map objectAtIndex:nIndex] intValue];
        //CCLOG(@"m_map[i]:%i",m_map[i]);
        [temp_map removeObjectAtIndex:nIndex];
    }
    
    [temp_map release];
    temp_map=nil;
    
	//根据m_map生成精灵贴图
    [self creatGame];
    
    
    queneT=(int *)malloc(sizeof(int)*5);//保存待移除的坐标,下标为0表示个数
    q_count=0;//下标为0表示待移除个数
    queneT[q_count]=0;//待移除个数为0
    pathArr=(int *)malloc(sizeof(int)*4);//保存上、下、左、右图片类型
    position=(int *)malloc(sizeof(int)*4);//保存上、下、左、右坐标tag
    p_up=0;//下标0表示上
    p_down=1;//下标1表示下
    p_left=2;//下标2表示左
    p_right=3;//下标3表示右
}

//创建精灵贴图函数
-(void) creatGame
{
    //触摸数组,用于触摸检测
	movableSprites = [[NSMutableArray alloc] init];
	//根据m_map生成精灵贴图,其中Piece为CCSprite子类
    for (int i=0; i<m_count; i++) {
        //
        if (m_map[i]==BLANK_STATE) {
            //
            Piece *p=[Piece nodeWidthFileName:@"Num13.png" flag:i];
            p.tag=i;
            p.Status=0;//反面
            //p.anchorPoint=ccp(0, 0);
            p.position=ccp(10+15+(i%m_nCol)*W,90+15+(i/m_nCol)*W);
            p.visible=NO;//不可见
			//将Piece加到触摸数组中,用于触摸检测
            [movableSprites addObject:p];
            [self addChild:p z:-1];
        }
        else
        {
            Piece *p=[Piece nodeWidthFileName:[NSString stringWithFormat:@"Num%i.png",m_map[i]] flag:i];
            p.tag=i;
            p.Status=1;//正面
            //p.anchorPoint=ccp(0, 0);
            p.position=ccp(10+15+(i%m_nCol)*W,90+15+(i/m_nCol)*W);
			//将Piece加到触摸数组中,用于触摸检测
            [movableSprites addObject:p];
            [self addChild:p z:-1];
            
        }
    }
}

上面有个Piece,其实它是我写的一个CCSprite子类,方便以后拓展用,如下:

#import <Foundation/Foundation.h>
#import "cocos2d.h"

@interface Piece : CCSprite {
    int Flag;//标记数组中位置
    int Status;//状态 -1被反面
    int X;//坐标x
    int Y;//坐标y
}

@property (nonatomic,assign) int Flag;
@property (nonatomic,assign) int Status;
@property (nonatomic,assign) int X;
@property (nonatomic,assign) int Y;

+(id)nodeWidthFileName:(NSString *)fileName flag:(int)flag;
-(id)initWithFileName:(NSString *)fileName flag:(int)flag;
@end

#import "Piece.h"


@implementation Piece

@synthesize Flag;
@synthesize Status;
@synthesize X;
@synthesize Y;

+(id)nodeWidthFileName:(NSString *)fileName flag:(int)flag
{
    return [[[Piece alloc] initWithFileName:fileName flag:flag] autorelease];
}

-(id)initWithFileName:(NSString *)fileName flag:(int)flag
{
    self=[super initWithSpriteFrameName:fileName];
    if (self) {
        self.Flag=flag;
    }
    
    return self;
}
@end 

消图的算法如下:

//检测到触摸的精灵(精灵状态为BLANK_STATE)
-(void) touchSprite:(int)tag
{
    CCLOG(@"tag:%i value:%i",tag,m_map[tag]);
    [self scan:tag];
    [self checkT];
}

-(void) scan:(int) tag
{
    int x=tag/m_nCol;//获取触摸行
    int y=tag%m_nCol;//获取触摸列
    int i=0;
    //上
    for (i=x+1; i<m_nRow; i++) {
        if (m_map[i*m_nCol+y]!=BLANK_STATE) {
            //找到上点
            pathArr[p_up]=m_map[i*m_nCol+y];//图片类别
            position[p_up]=i*m_nCol+y;//在m_map中的坐标
            break;
        }
    }
    //没有找着上点
    if (i==m_nRow) {
        pathArr[p_up]=BLANK_STATE;
        position[p_up]=BLANK_STATE;
    }
    
    //下
    for (i=x-1; i>=0; i--) {
        if (m_map[i*m_nCol+y]!=BLANK_STATE) {
            //找到下点
            pathArr[p_down]=m_map[i*m_nCol+y];
            position[p_down]=i*m_nCol+y;
            break;
        }
    }
    //没有找着下点
    if (i==-1) {
        pathArr[p_down]=BLANK_STATE;
        position[p_down]=BLANK_STATE;
    }
    
    //左
    for (i=y-1; i>=0; i--) {
        if (m_map[x*m_nCol+i]!=BLANK_STATE) {
            //找到左点
            pathArr[p_left]=m_map[x*m_nCol+i];
            position[p_left]=x*m_nCol+i;
            break;
        }
    }
    //没有找着左点
    if (i==-1) {
        pathArr[p_left]=BLANK_STATE;
        position[p_left]=BLANK_STATE;
    }
    
    //右
    for (i=y+1; i<m_nCol; i++) {
        if (m_map[x*m_nCol+i]!=BLANK_STATE) {
            //找到右点
            pathArr[p_right]=m_map[x*m_nCol+i];
            position[p_right]=x*m_nCol+i;
            break;
        }
    }
    //没有找着右点
    if (i==m_nCol) {
        pathArr[p_right]=BLANK_STATE;
        position[p_right]=BLANK_STATE;
    }
    
    /*
    for (i=0; i<4; i++) {
        CCLOG(@"pathArr[%i]:%i",i,pathArr[i]);
        CCLOG(@"position[%i]:%i",i,position[i]);
    }
    */
}

-(void) checkT
{
    int i;
    int j;
    for (i=0; i<4; i++) {
        queneT[q_count]=0;
        if (pathArr[i]==BLANK_STATE) {
            //跳过空白或者已经被移除
            continue;
        }
        else
        {
            for (j=i+1; j<4; j++) {
                if (pathArr[i]==pathArr[j]) {
                    queneT[q_count]++;
                    queneT[queneT[q_count]]=position[j];
                    pathArr[j]=BLANK_STATE;
                }
            }
            if (queneT[q_count]>0) {
                //移除
                queneT[q_count]++;
                queneT[queneT[q_count]]=position[i];
                pathArr[i]=BLANK_STATE;
                //移除
                [self toHidePiece];
            }
            
        }
    }
}
//隐藏消去的精灵
-(void) toHidePiece
{
    //int j=queneT[q_count];
    for (int i=1; i<=queneT[q_count]; i++) {
        Piece *p1=(Piece*)[self getChildByTag:queneT[i]];
        //隐藏图片
        [p1 setVisible:NO];
        p1.Status=0;
        m_map[queneT[i]]=BLANK_STATE;
    }
    queneT[q_count]=0;
}

以上代码肯定有不足之处,欢迎拍砖交流!


你可能感兴趣的:(游戏,算法,Random,UP,interface,IM)