【原创】|日历拼图游戏的解决方案(C语言-进阶应用)-详解连载1_zhuyi8120的博客-CSDN博客
【原创】|日历拼图游戏的解决方案(C语言-进阶应用)-详解连载3_zhuyi8120的博客-CSDN博客
【原创】|日历拼图游戏的解决方案(C语言-进阶应用)-详解连载4_zhuyi8120的博客-CSDN博客
【原创】|源码全文-日历拼图游戏的解决方案(C语言-进阶应用)-详解连载5_zhuyi8120的博客-CSDN博客
今天的计算和拼图如下:
C语言实现1:初始化
初始化看上去还是比较简单的。按照上面所分析的,我们先把4个有8种变体的方块放在前面,有4种变体的方块放在中间,有2种变体的方块放到最后,并且按这样的顺序命名。
图8:8种方块的命名
代码如下:
char cA[8][4][4]={{{'A','A','A','-'},{'-','A','A','-'},{'-','-','-','-'},{'-','-','-','-'}},{{'B','B','B','B'},{'-','-','-','B'},{'-','-','-','-'},{'-','-','-','-'}},{{'C','C','C','C'},{'-','-','C','-'},{'-','-','-','-'},{'-','-','-','-'}},{{'D','-','-','-'},{'D','D','-','-'},{'-','D','-','-'},{'-','D','-','-'}},{{'E','E','-','-'},{'-','E','-','-'},{'-','E','E','-'},{'-','-','-','-'}},{{'F','F','F','-'},{'F','-','F','-'},{'-','-','-','-'},{'-','-','-','-'}},{{'G','G','G','-'},{'G','-','-','-'},{'G','-','-','-'},{'-','-','-','-'}},{{'H','H','H','-'},{'H','H','H','-'},{'-','-','-','-'},{'-','-','-','-'}}};
代码段1:初始化8个方块代码
注:限于篇幅,并且让读者也有参与这个过程,代码并没有把全部代码都显示出来。需要读者在阅读之后自己补充完整。
C语言实现2:生成8种变体
我们先来分析8种变体之间数组的相互关系。
先来看顺时针旋转90度的情况(如下图):
图9:顺时针旋转90度的图示
由上图,我们可以推论出变换的式子为(i,j)→(3-j,i)。有兴趣读者也可以验证一下,这个式子是否满足其他几行的变换。
代码如下(非最优化,在所有规律都试过之后,会有更合适的方式):
//顺时针旋转90度//非最优化代码示范for(i=0;i<8;i++){for(j=0;j<4;j++){for(k=0;k<4;k++){b[6][i][j][k]=cA[i][3-k][j];}//k}//j}//i
代码段2:顺时针旋转90度
这时候,为了便于区分原始方块数组和变体方块数组,我们需要另外再建一个数组来存放这些变体(也可以用同一个数组,以节省内存使用,但对于本文的读者来说,建议分开操作,以便于不发生混淆)。
再来看顺时针180度旋转的情况:
图10:顺时针旋转180度的图示
代码段以上述类似。因非最优化代码,本处不再赘述。
笔者在用类似的方式做完各种之后,发现已经分不出来这8种是不是出现重复或者是否准确。于是,就把这8条式子列在了一起,然后,发现有重复的。然后,也发现了在数学上的简单规律。
有兴趣的读者可以暂停一下,自己先尝试一下,体验一下自己在复杂的情况下发现简单规律的快乐。
以下是根据找到的规律。一次性把8个变体全部创建出来的代码。
///creat 8 martinchar b[8][8][4][4];int iMax=3;for(i=0;i<8;i++){for(j=0;j<4;j++){//printf("tag[%d][%d]:",i,j);for(k=0;k<4;k++){//printf("cA[%d][%d][%d]=%c\n",i,j,k,cA[i][j][k]);b[0][i][j][k]=cA[i][j][k];b[1][i][j][k]=cA[i][j][iMax-k];b[2][i][j][k]=cA[i][iMax-j][k];b[3][i][j][k]=cA[i][iMax-j][iMax-k];b[4][i][j][k]=cA[i][k][j];b[5][i][j][k]=cA[i][k][iMax-j];b[6][i][j][k]=cA[i][iMax-k][j];b[7][i][j][k]=cA[i][iMax-k][iMax-j];}//k}//j}//i
代码段3:创建8个变体的普通代码
这还不算是最优化的代码,但暂时这样放着。因为后面还会针对不同方块实际有多少个变体来进一步优化,减少计算量(可以缩小为1/16)。
C语言实现3:规整化
按之前的第7个分析,变体不出现在左上角,会出现难以进行插入比较的困难。因此需要将靠左的空列和靠上的空行都清除掉。我们来分析一下如何确定。
图11:规整化图示
在数组里面, 移动方块是很容易的,稍微有点难度的是怎么判断要移动多少格。
我们可以采用计数的方式,具体是这样:
对于列来说,用for循环计算每一列有多少个空格,等于4个空格的,就确认是空列,移动的列数加1,如果不是等于4的,就不是空列,不需要移动。(行的情况类似,不赘述。)
但还要注意的一点,A方块翻面后,再旋转180度之后(图12),也一样有空列。
图12:虽然有空列,但不需要处理的情形
但很明显,对于这个空列来说,这并不需要移动。所以,简单的按空行/列就移动,这是不可取的。还要有技巧。
具体实现的代码如下:
做规整计算for(ib=0;ib<8;ib++){ for(i=0;i<8;i++){for(j=0;j<4;j++){xem[j]=0;for(k=0;k<4;k++){if(b[ib][i][j][k]=='-'){xem[j]++;}//if}}/test xem//xmv=0;if(xem[0]==4){xmv++;if(xem[1]==4){xmv++;if(xem[2]==4){xmv++;}}}//if//move-1for(j=0;j<(4-xmv);j++){//printf("cA[%d]:\n",i);for(k=0;k<4;k++){b[ib][i][j][k]=b[ib][i][j+xmv][k];}//for k}//for j//move-2:fill the emptyfor(j=4-xmv;j<4;j++){//printf("cA[%d]:\n",i);for(k=0;k<4;k++){b[ib][i][j][k]='-';}//for k}//for j//printend 1/the 2for(k=0;k<4;k++){yem[k]=0;for(j=0;j<4;j++){if(b[ib][i][j][k]=='-'){yem[k]++;}//if}//printf("yem[%d]:%d\n",k,yem[k]);}/test yem//ymv=0;if(yem[0]==4){ymv++;if(yem[1]==4){ymv++;if(yem[2]==4){ymv++;}}}//if//move-1for(k=0;k<(4-ymv);k++){//printf("cA[%d]:\n",i);for(j=0;j<4;j++){b[ib][i][j][k]=b[ib][i][j][k+ymv];}//for k}//for j//move-2:fill the emptyfor(k=4-ymv;k<4;k++){//printf("cA[%d]:\n",i);for(j=0;j<4;j++){b[ib][i][j][k]='-';}//for k}//for jend of order}//i}//ibprintf("the second part is over!they are ordered.\n");
代码段4:规整化计算
(注:从分析到代码实现中间有点小的脱节,这是故意为之,目的是让读者自己去思考一下,然后,再看代码是如何实现的。)