之前贴过一个连连看两图连通的检测算法,今天再贴一个方块总动员消图算法,坐标系如下图:
方块总动员玩法很简单,点到同类型方块的十字交叉点便可消除,这里我用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;
}
以上代码肯定有不足之处,欢迎拍砖交流!