C实现拼图逻辑的关键步骤
C实现拼图逻辑的关键步骤
写这篇文章的起因是因为,在CSDN查找了很久关于拼图随机后关于逆序对数判断是否有解的步骤,很多文章都是互相抄袭,知其然而不知其所以然,按照他们所说的逻辑去求逆序对数判断是否有解,基本无法实现真正的拼图随机有解。在深入学习逆序对数对于是否有解的真正逻辑后,想着说发出来给查询的人少走点弯路。(已经完成2x2、3x3、4x4的拼图逻辑)
第一步 降维
拼图游戏的列表类似于以下几种
0 1
2 3
0 1 2
3 4 5
6 7 8
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
声明对应的一维数组,存储即可
//难度等级声明
typedef enum{
DIFF_TWO = 4, //难度二
DIFF_THREE = 9, //难度三
DIFF_FOUR = 16, //难度四
}JIGSAW_PUZZLE_GAME_DIFF_T;
static uint8_t Puzzle_index_Diff2[DIFF_TWO];
static uint8_t Puzzle_index_Diff3[DIFF_THREE];
static uint8_t Puzzle_index_Diff4[DIFF_FOUR];
第二步 随机打乱
按照拼图交互,我这里采用的是最大数字放最后一位固定不参与随机打乱,显示时最大数字不显示,默认空白格。
//Diff是难度,参数为2、3、4
static void Random_handler(void)
{
for (uint8_t i = 0; i<(Diff*Diff-1);i++)
{
uint8_t num = i + rand() % ((Diff*Diff-1) - i); // 取随机数
uint8_t temp = Get_Puzzle_index(i);
Set_Index_handler(i,Get_Puzzle_index(num));
Set_Index_handler(num,temp);
}
}
第三步 计算逆序对数以判断当前随机数据是否有解
static void No_Solution_Judgment(void)
{
/*对于一个拼图序列
如果其逆序数(D)和最大数到空白格之间的步数(M)均为偶数(或奇数)
则此拼图是有解的*/
//对于本功能而言,最大数固定在最后一个位置空白格,步数为0即偶数,即逆序数为偶数有解
//逆序对计算要求数据必须都大于0
for(uint8_t i=0;i<=(Diff*Diff-1);i++)
{
Set_Index_handler(i,Get_Puzzle_index(i)+1);
}
//逆序对数量计算
uint8_t count=0;
//暴力破解法
for(uint8_t i=0;i<(Diff*Diff-2);i++)
{
for(uint8_t j=i+1;j<(Diff*Diff-1);j++)
{
if(Get_Puzzle_index(i)>Get_Puzzle_index(j)) count++;
}
}
//逆序对数为奇数
if(count%2!=0)
{
/*将除了空白格之外的最后两个数互相调转位置,可以达到逆序对数+1或-1的效果*/
uint8_t temp = Get_Puzzle_index(Diff*Diff-3);
Set_Index_handler(Diff*Diff-3,Get_Puzzle_index(Diff*Diff-2));
Set_Index_handler(Diff*Diff-2,temp);
wf_printf_array_jp();
}
//还原数据
for(uint8_t i=0;i<=(Diff*Diff-1);i++)
{
Set_Index_handler(i,Get_Puzzle_index(i)-1);
}
}