【原创-更新完毕】|日历拼图游戏的解决方案(C语言-进阶应用)-详解连载4

【原创】|日历拼图游戏的解决方案(C语言-进阶应用)-详解连载1_zhuyi8120的博客-CSDN博客

【原创】|日历拼图游戏的解决方案(C语言-进阶应用)-详解连载2_zhuyi8120的博客-CSDN博客

【原创】|日历拼图游戏的解决方案(C语言-进阶应用)-详解连载3_zhuyi8120的博客-CSDN博客

【原创】|源码全文-日历拼图游戏的解决方案(C语言-进阶应用)-详解连载5_zhuyi8120的博客-CSDN博客

上面是之前的内容,这些连载是一个整体。

今天(12月9日)的拼图

今天(12月9日)的计算

C语言实现6:比对方块和底盘

1、单次比对

单次比对方块和底盘是比较容易的。方法是:先定位好起始的比对点,一般是从(0,0)开始,然后在方块的长和宽方向顺次比较,如果遇到了方块和底盘都不是‘-’的情形,就用一个变量(counti)记录下来(counti++),然后,再通过比较这个变量(counti==0)来判断在这个定位点能否插入方块。

如果这个变量为0,即表示可以插入(counti==0为真),就记录下插入的方块的点和数据。

如果不能(counti>0),就转到下一个起始点,比如,从(0,0)转到(0,1)。

这项功能可以简单的用for循环完成的。

读者可以想一下,还有没有其他方法实现这样的特点。

2、在方块的搜索范围内的所有比对

图13:蓝色为可以插入A方块原始状态(不含其他变体)的所有起始点 

在图12我们已经展示过搜索范围,即使已经有可以插入的点了,我们还是要继续完成搜索范围的所有可以插入的点,对于所有可以插入的点都记录下来。之所以要这样做,是为了解决整个问题的。因为在底盘插入了一些方块后,并不一定就可以插入后面的方块,当出现无法插入后面的方块时,就要回退到上一个方块,让上一个方块调整位置。上一个方块要调整到哪一个位置,这时候,如果又让这个方块在搜索范围内重新搜索一次,一是浪费运算时间,二是我们无法判断已经尝试过的是哪些起始点。

所以,我们要一次性在搜索范围内记录好所有可以插入的点,并记录下来,然后,再依次逐个去尝试。

比如,插入第一个方块A时,在原始状态(不包括变体)在总共可以有图示的这些点。

然后,除了原始状态外,还需要把其他变体的可以插入的点也记录下来。因为我们面对的不是不同变体,而是一个方块。所以,同一个方块的不同变体,都是要记录在一起去逐个尝试的。

这点非常重要,因为笔者没注意到这点,前期尝试时,总是失败,分析了好久,才知道问题点在这里。

相关的代码前期如下:

for(ib=0;ib<8;ib++){

	for (j=0;j<=8-xlng[0][ib];j++){
		for(k=0;k<=8-ylng[0][ib];k++){
			//test for fit
			counti=0;
			for(ii=0;ii<xlng[0][ib];ii++){
				for(jj=0;jj<ylng[0][ib];jj++) {
					if ((ctemp[j+ii][k+jj]!='-')&&(b[0][ib][ii][jj]!='-')){
						counti++;
					}// jj if
				}//for jj
			}//for ii
			//when it fit
			if(counti==0){
//未完...

代码段7:方块和底盘比对代码

搜索分析:

为了完成整个拼图,需要对所有可能的方式都进行尝试。

尝试的方式,在上文已有描述。

以下主要分析指针链的设置。

图14:指针链的整体设计

创建一个结构,里面带有至少3个指针,以实现上述的功能。

1、每一个方块,第一个符合比对条件的,同时设置为该方块的0号指针,并且把上一个方块的指针的next链接给它,它的pre连接上一个方块的指针。此时,它的right指针和next指针设置为空。对于初始时的指针,就把head(头指针)的next指向它,把它的pre指针指向头指针。

设置头指针是很重要的。虽然采用一些技巧可以使用(0,0)号来充当头指针,但不建议这样做。为了节省这点空间,而进行相对复杂的操作,这样可能会导致一些莫名其妙的结果,以后翻查会很麻烦。

在找到这个方块的第二个符合比对条件的,就设置为1号指针,1号指针的pre、right和next指针均为空,现在只有0号指针的right指针是指向它的,它没有任何指向。

再找到这个方块的第三个符合比对条件的,就设置为2号指针,和1号指针一样,pre、right、next指针均为空,也只有1号指针的right指针指向它。

这样,顺次把这个方块的所有可能都用right指针串起来。

最后一种可能的right指针都是空的了。

如果我们能够顺利的一直找到第8个方块的合适放置位置,我们的任务就完成了。

2、当其中一个方块(比如到了第1号方块)在上一个方块的一种可能(比如(1,0))的所有可能都尝试过而不能插入了,也就是这个方块的最后一种可能,这种可能的right指针已经指向NULL了,而它的所有比对的冲突都不为0(counti>0)。

 这时候,上一个方块(比如第0号方块)就要换下一个可能了,在指针上,是把上一个方块的next设置为现在这个指针的right指针(比如从(0,0)调整为(0,1)),然后,再进行下一轮对放置下一个方块的搜寻。指针的操作是这样的。

图15:指针链的调整

3、当某一个方块的所有可能都尝试过之后,上一层的所有可能都尝试过了,这时候,就要调整更上一层的指针了。但如何做这个判断和在代码上如何调整,就需要读者自己先去思考了。或者看下一篇。

上述第1步和第2步的相关的代码如下:

for(ib=0;ib<8;ib++){

	for (j=0;j<=8-xlng[0][ib];j++){
		for(k=0;k<=8-ylng[0][ib];k++){
			//test for fit
			counti=0;
			for(ii=0;ii<xlng[0][ib];ii++){
				for(jj=0;jj<ylng[0][ib];jj++) {
					if ((ctemp[j+ii][k+jj]!='-')&&(b[0][ib][ii][jj]!='-')){
						counti++;
					}// jj if
				}//for jj
			}//for ii
			//when it fit
			if(counti==0){
				if (vartime==0){
					p[0][vartime]->left=NULL;
					p[0][vartime]->right =NULL;
					p[0][vartime]->pre =head;
					head->next=p[0][0];
					p[0][vartime]->next=NULL;
				}
				else{
					p[0][vartime]=addpointer();
					p[0][vartime-1]->right =p[0][vartime];
					p[0][vartime]->left =p[0][vartime-1];
					p[0][vartime]->right=NULL;
					p[0][vartime]->next =NULL;
     			}
	     			p[0][vartime]->i=0;
					p[0][vartime]->ib=ib;
					p[0][vartime]->ixy=vartime;
					p[0][vartime]->x=j;
					p[0][vartime]->y=k;
				vartime++;
			}
		}
	}
}	
	tmp=addpointer();
	
	int ibtmp=0,itmp=0,ixytmp=0;
i=0;
ib=0;
long long countii=0;
while(irsl<1){
	countii++;
for(iii=0;iii<7;iii++){
	for(jjj=0;jjj<7;jjj++){
		ctemp[iii][jjj]='-';

	}
}

ctemp[0][6]='Z';
ctemp[1][6]='Z';
ctemp[6][3]='Z';
ctemp[6][4]='Z';
ctemp[6][5]='Z';
ctemp[6][6]='Z';
ctemp[1][5]='X';
ctemp[3][1]='X';

	tmp=head->next;
	//init the ctemp-martix
	while(tmp!=NULL){
		ib=tmp->ib;
		i=tmp->i;
		for(ii=0;ii<xlng[ib][i];ii++){
   			for(jj=0;jj<ylng[ib][i];jj++){
				if (b[ib][i][ii][jj]!='-'){	
					ctemp[tmp->x+ii][tmp->y+jj]=b[ib][i][ii][jj];
				}
			}//for jj
		}//for ii



		ibtmp=tmp->ib;
		itmp=tmp->i;
		ixytmp=tmp->ixy;
		tmp=tmp->next;
	}//first fill
	i=itmp+1;
//------------------
vartime=0;
int ibb=0;
if((i==4||i==5||i==6)){
	ibb=4;
}
if(i==7){
	ibb=2;
}
if(i<4){
	ibb=8;
}
for (ib=0;ib<ibb;ib++){
	
	for (j=0;j<=7-xlng[ib][i];j++){
		for(k=0;k<=7-ylng[ib][i];k++){
			counti=0;
			for(ii=0;ii<xlng[ib][i];ii++){
				if(j+ii>=7){counti++;}
					for(jj=0;jj<ylng[ib][i];jj++){
						
					//printf("ii=%d,jj=%d\n",ii,jj);
						if(k+jj>=7){counti++;}//if k+jj
						if ((ctemp[j+ii][k+jj]!='-')&&(b[ib][i][ii][jj]!='-')){
							counti++;
						}
						
				}//for jj
				
			}//for ii
			//when it fill
			if(counti==0){
				//printf("i=%d,ib=%d,x=%d,y=%d\n",i,ib,j,k);
				if (vartime==0){
					//printf("when vartime=0;ib=%d,i=%d,j=%d,k=%d\n",ib,i+1,j,k);
					p[i][vartime]=addpointer();
					p[i][vartime]->left=NULL;
					p[i][vartime]->right =NULL;
					p[i][vartime]->pre =p[itmp][ixytmp];
					//printf("p[itmp+1=%d][ib=%d][vartime=%d]->pre =p[itmp=%d][ibtmp=%d][ixytmp=%d]\n",itmp+1,ib,vartime,itmp,ibtmp,ixytmp);
					p[itmp][ixytmp]->next=p[i][vartime];
					p[i][vartime]->right =NULL;
					p[i][vartime]->next =NULL;
					//printf("p[%d][%d][%d]->right=%0x\n",ib,itmp+1,vartime,p[ib][itmp+1][vartime]->right);
				}
				else{
					//printf("when vartime>0;ib=%d,i=%d,j=%d,k=%d\n",ib,i,j,k);
					p[i][vartime]=addpointer();
					p[i][vartime-1]->right =p[i][vartime];
					p[i][vartime]->left =p[i][vartime-1];
					//printf("p[itmp+1=%d][ib=%d][vartime=%d]->pre =p[itmp+1=%d][ib=%d][vartime-1=%d]\n",itmp+1,ib,vartime,itmp+1,ib,vartime-1);
					p[i][vartime]->right=NULL;
					p[i][vartime]->next =NULL;

					
     			}
	     			p[i][vartime]->i=itmp+1;
					p[i][vartime]->ib=ib;
					p[i][vartime]->ixy=vartime;
					p[i][vartime]->x=j;
					p[i][vartime]->y=k;
					vartime++;
     			}
			}
		}
	}

 代码段8:指针的第1段和第2段调整

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值