连连看两图连通检测算法,折腾了一天总算弄出来了,首先必须要明白我这里的坐标系,如图:
连连看连通方式主要有三种,一种是直线连通,第二种是带一个直角的连通,第三种是带两个直角的连通,其中第三种连通可以化解为第二种连通检测,同理第二种连通可以化解为第一种连通检测,我这里主要讲检测算法,至于图的生成什么的就不多说了,算法用到一些变量说明如下:
//
int BLANK_STATE=-1;//代表空,表示此图已经被消掉
//int W=30;//表示图边长
int m_nCol=10;//表示列数
int m_nRow=12;//表示行数
Point z1;//第一个折点
Point z2;//第二个折点
int *m_map=(int *)malloc(sizeof(int)*m_nCol*m_nRow);
//图片数组,列*行,长度为120,0-9第一行,10-19第二行,
//里面用数字填充,如有12种图,那么就有0-11代表,BLANK_STATE表示此图已经被消掉
//....
//....
//打乱数组m_map
//根据m_map[i]数字内容获取不同图片,根据i按照上图示摆放好不同图片
//...
//...
//按到第一张图,记录下第一张图在数组m_map中的位置t1
//按到第一张图,记录下第二张图在数组m_map中的位置t2
//检测这两张图是否连通
//...
检测两个图是否连通算法如下:
-(BOOL) IsLink:(int)t1 t2:(int)t2 //参数分别为两个图在数组m_map中的位置
{
int x1=t1/m_nCol;//转换为坐标
int y1=t1%m_nCol;
int x2=t2/m_nCol;
int y2=t2%m_nCol;
//水平直连接
if (x1==x2) {
if ([self X_Link:x1 y1:y1 y2:y2]) {
LType=LineType;
CCLOG(@"水平直连接");
return YES;
}
}
//垂直直连接
else if (y1==y2) {
if ([self Y_Link:y1 x1:x1 x2:x2]) {
LType=LineType;
CCLOG(@"垂直直连接");
return YES;
}
}
//一个折点连接
if ([self OneCornerLink:x1 y1:y1 x2:x2 y2:y2]) {
LType=OneCornerType;
CCLOG(@"一个折点连接");
CCLOG(@"折点:x=%i y=%i",z1.v,z1.h);
return YES;
}
//两个折点连接
else if([self TwoCornerLink:x1 y1:y1 x2:x2 y2:y2])
{
LType=TwoCornerType;
CCLOG(@"两个折点连接");
CCLOG(@"折点1:x=%i y=%i",z1.v,z1.h);
CCLOG(@"折点2:x=%i y=%i",z2.v,z2.h);
return YES;
}
return NO;
}
//X直接连通即水平方向连通
-(BOOL) X_Link:(int)x y1:(int)y1 y2:(int)y2
{
if (y1>y2) {
int n=y1;
y1=y2;
y2=n;
}
for (int i=y1+1; i<=y2; i++) {
if (i==y2) {
return YES;
}
if (m_map[x*m_nCol+i]!=BLANK_STATE) {
break;
}
}
return NO;
}
//Y直接连通即垂直方向连通
-(BOOL) Y_Link:(int)y x1:(int)x1 x2:(int)x2
{
if (x1>x2) {
int n=x1;
x1=x2;
x2=n;
}
for (int i=x1+1; i<=x2; i++) {
if (i==x2) {
return YES;
}
if (m_map[i*m_nCol+y]!=BLANK_STATE) {
break;
}
}
return NO;
}
//一个直角接口连通
-(BOOL) OneCornerLink:(int) x1 y1:(int)y1 x2:(int)x2 y2:(int)y2
{
//确保(x1,y1)为矩形下边,(x2,y2)矩形上边,即x1<x2
if (x1>x2) {
int n=x1;
x1=x2;
x2=n;
n=y1;
y1=y2;
y2=n;
}
if (y1<y2) {//(x1,y1)为矩形左下角,(x2,y2)矩形右上角
//判断右下角(x1,y2)是否为空
if (m_map[x1*m_nCol+y2]==BLANK_STATE) {
//判断折点与两个目标点是否连通
if ([self X_Link:x1 y1:y1 y2:y2]&&[self Y_Link:y2 x1:x1 x2:x2]) {
//保存折点坐标
z1.v=x1;
z1.h=y2;
point1=x1*m_nCol+y2;
return YES;
}
}
//判断左上角(x2,y1)是否为空
if (m_map[x2*m_nCol+y1]==BLANK_STATE) {
//判断折点与两个目标点是否连通
if ([self X_Link:x2 y1:y1 y2:y2]&&[self Y_Link:y1 x1:x1 x2:x2]) {
//保存折点坐标
z1.v=x2;
z1.h=y1;
point1=x2*m_nCol+y1;
return YES;
}
}
return NO;
}
else //(x1,y1)为矩形右下角,(x2,y2)矩形左上角
{
//判断左下角(x1,y2)是否为空
if (m_map[x1*m_nCol+y2]==BLANK_STATE) {
//判断折点与两个目标点是否连通
if ([self X_Link:x1 y1:y1 y2:y2]&&[self Y_Link:y2 x1:x1 x2:x2]) {
//保存折点坐标
z1.v=x1;
z1.h=y2;
point1=x1*m_nCol+y2;
return YES;
}
}
//判断右上角(x2,y1)是否为空
if (m_map[x2*m_nCol+y1]==BLANK_STATE) {
//判断折点与两个目标点是否连通
if ([self X_Link:x2 y1:y1 y2:y2]&&[self Y_Link:y1 x1:x1 x2:x2]) {
//保存折点坐标
z1.v=x2;
z1.h=y1;
point1=x2*m_nCol+y1;
return YES;
}
}
return NO;
}
}
//两个直角连通
-(BOOL) TwoCornerLink:(int) x1 y1:(int)y1 x2:(int)x2 y2:(int)y2
{
//确保(x1,y1)为矩形下边,(x2,y2)矩形上边,即x1<x2
if (x1>x2) {
int n=x1;
x1=x2;
x2=n;
n=y1;
y1=y2;
y2=n;
}
int x,y;
//往上
for (x=x1+1; x<=m_nRow; x++) {
//
if (x==m_nRow) {
//
if ([self YThrough:x2+1 y:y2 bAdd:YES]) {
//两个折点都在选中方块上方,且都在图案区域外部
z1.v=m_nRow;
z1.h=y2;/??
z2.v=m_nRow;
z2.h=y1;
return YES;
}
else
{
break;
}
}
if (m_map[x*m_nCol+y1]!=BLANK_STATE) {
break;
}
if ([self OneCornerLink:x y1:y1 x2:x2 y2:y2]) {
z2.v=x;
z2.h=y1;
return YES;
}
}
//往下
for (x=x1-1; x>=-1; x--) {
if (x==-1) {
//
if ([self YThrough:x2-1 y:y2 bAdd:NO]) {
//两个折点都在选中方块下方,且都在图案区域外部
z1.v=-1;
z1.h=y2;/??
z2.v=-1;
z2.h=y1;
return YES;
}
else
{
break;
}
}
if (m_map[x*m_nCol+y1]!=BLANK_STATE) {
break;
}
if ([self OneCornerLink:x y1:y1 x2:x2 y2:y2]) {
z2.v=x;
z2.h=y1;
return YES;
}
}
//往左
for (y=y1-1; y>=-1; y--) {
//
if (y==-1) {
//两个折点都在选中方块左方,且都在图案区域外部
if ([self XThrough:x2 y:y2-1 bAdd:NO]) {
//两个折点都在选中方块左方,且都在图案区域外部
z1.v=x2;/??
z1.h=-1;
z2.v=x1;
z2.h=-1;
return YES;
}
else
{
break;
}
}
if (m_map[x1*m_nCol+y]!=BLANK_STATE) {
break;
}
if ([self OneCornerLink:x1 y1:y x2:x2 y2:y2]) {
//
z2.v=x1;
z2.h=y;
return YES;
}
}
//往右
for (y=y1+1; y<=m_nCol; y++) {
//
if (y==m_nCol) {
//
if ([self XThrough:x2 y:y2+1 bAdd:YES]) {
//两个折点都在选中方块右方,且都在图案区域外部
z1.v=x2;/??
z1.h=m_nCol;
z2.v=x1;
z2.h=m_nCol;
return YES;
}
else
{
break;
}
}
if (m_map[x1*m_nCol+y]!=BLANK_STATE) {
break;
}
if ([self OneCornerLink:x1 y1:y x2:x2 y2:y2]) {
//
z2.v=x1;
z2.h=y;
return YES;
}
}
return NO;
}
//水平连通判断,主要用于判断是否连通边界
-(BOOL) XThrough:(int)x y:(int)y bAdd:(BOOL)bAdd
{
if (bAdd) {
//水平往右是否连通
for (int i=y; i<m_nCol; i++) {
if (m_map[x*m_nCol+i]!=BLANK_STATE) {
return NO;
}
}
}
else
{
//水平往左是否连通
for (int i=0; i<=y; i++) {
if (m_map[x*m_nCol+i]!=BLANK_STATE) {
return NO;
}
}
}
return YES;
}
//垂直连通判断,主要用于判断是否连通边界
-(BOOL) YThrough:(int)x y:(int)y bAdd:(BOOL)bAdd
{
if (bAdd) {
//垂直往上是否连通
for (int i=x; i<m_nRow; i++) {
if (m_map[i*m_nCol+y]!=BLANK_STATE) {
return NO;
}
}
}
else
{
//垂直往下是否连通
for (int i=0; i<=x; i++) {
if (m_map[i*m_nCol+y]!=BLANK_STATE) {
return NO;
}
}
}
return YES;
}
不知道有没有其他更好的办法,欢饮拍砖交流!
转载自原文链接, 如需删除请联系管理员。
原文链接:连连看两图连通检测算法(Objective-c),转载请注明来源!