|
還記得第一次玩九鎖連環(huán)的時(shí)候,是公司的范姐買了一堆開發(fā)智力的玩具,當(dāng)時(shí)覺得九鎖連環(huán)很高級(jí)的樣子,于是就試拿來玩了。說實(shí)話,真的是第一次拿到手玩,以前沒接觸過。
那天下午思考著它的規(guī)律,終于打它解開了。
后來想想,既然是那么有規(guī)律,可以通過編程,來演示和記錄每一步是怎么操作的,后面想學(xué)習(xí)的人也可以按著每一步來操作學(xué)會(huì)它。
于是,今晚突然心血來潮,寫了個(gè)程序來演示怎么解開九鎖連環(huán)。由于只是心血來潮,只有數(shù)據(jù)和圖片,改天有空再編寫做個(gè)FLASH動(dòng)畫來更形象演示怎么每一步解開的。同時(shí)也會(huì)C的源碼貼上來,讓有興趣的人一起來交流交流,有做程序手機(jī)程序的朋友,也可以把算法移植過去,做個(gè)手機(jī)演示程序也挺好的。當(dāng)然,如果這個(gè)只是針對(duì)9鎖的,理論上,你可以通過改程序,把這個(gè)做成N鎖連環(huán),就只要改個(gè)數(shù)據(jù)改個(gè)長度就可以,因?yàn)樗惴ㄓ玫竭f歸,不管多少連環(huán),反正就是一直遞歸下去,直到你電腦CPU掛了都可以了。
先上點(diǎn)圖片。
這個(gè)圖標(biāo)就是通過C程序,把每一個(gè)打印出來,保存到一個(gè)txt文檔里,再導(dǎo)入到excel里去的。其中1就是鎖著的,0表示鎖下來的。


可以看到,解開九鎖連環(huán)一共需要341步。當(dāng)然,解下一個(gè)環(huán)或扣回一個(gè)環(huán)都算一步。同時(shí),大家也看到,我在程序里或表格里,都注明了哪一步是扣或解開哪一個(gè)環(huán)。
好了,慢慢理解這個(gè)規(guī)律了。下面就是上程序了,這個(gè)程序是純粹的C語言,暫時(shí)沒有優(yōu)化,不可,至少可以執(zhí)行,還有我寫程序時(shí)的注視,如果有興趣的朋友再進(jìn)一步交流了。等以后把java的,processing動(dòng)畫,flash也一直移植過去,做成演示動(dòng)畫就更形象了。
//以下變是程序了,可以直接復(fù)制拷貝編譯
#include "stdio.h"
#define LOCK_NUMBER 4
unsigned char data[LOCK_NUMBER];
unsigned int unlock(int number);//解鎖
unsigned int lock(int number);//扣鎖
void dis_step(int number);//看是解幾個(gè)鎖的
void dis_step_lock(int number);
int steps=0;
int file_open=0;
FILE *fp;
int main()
{
int i;
fp=fopen("九鎖連環(huán)解鎖過程.txt","w");
if(fp==NULL)
{
printf("無法打開");
}
//先初始化全部鎖上
for(i=0;i<LOCK_NUMBER;i++)
{
data=0x01;
}
//這里就是解鎖了
//
//開始解鎖
for(i=LOCK_NUMBER;i>=1;i--)
{
unlock(i);
}
//解鎖完成
printf("解鎖完成\r\n");
fclose(fp);
return 0;
}
unsigned int unlock(int number)//解鎖
{
int i=0;
while(data[number-1]==0x01)// 直到把這個(gè)鎖解了才退出
{
if(number>=3)
{
//先判斷前面n-2個(gè)是否都解開了
for(i=number-2;i>=1;i--)
{
if(data[i-1]!=0x00)
{
//如果遇到還沒有解開的, 逆回去先解開前n-1第一個(gè)還沒有解下來的
unlock(i);
}
}
if(i==0)
{
//說明前面n-2個(gè)都解下來了。
// 再判斷n-1個(gè)是否解下來
if(data[number-2]==0x01)
{
//如果這個(gè)沒有放下來
// 就可以把n這個(gè)鎖解下來了
data[number-1]=0;
dis_step(number);
}
else if(data[number-2]==0x00)
{
// 如果這個(gè)已經(jīng)放下來了,則需要先把這個(gè)扣上去,再能解下后面那個(gè)
lock(number-1);
}
}
}
else if(number==2)
{
if(data[0]==0x01)
{
data[1]=0;//直接把2解下來
dis_step(number);
}
else if(data[0]==0x00)
{
lock(1);
}
}
else if(number==1)
{
data[0]=0;//直接把1解下來
dis_step(number);
}
}
return 1;
}
unsigned int lock(int number)//對(duì)第n個(gè)上鎖
{
//
//原理,對(duì)第n個(gè)上鎖也是先判斷前面n-2個(gè)是否都解下來
// 如果前面第n-2個(gè)解下來: 如果第n-1個(gè)是扣上去的,則可以直接扣回去
//如果第n-1個(gè)是解下來的,則還需要把第n-1個(gè)扣回去
int i;
while(data[number-1]==0)//一定要鎖上才退出
{
if(number==1)
{
// 如果是第一個(gè),直接扣上去了
data[0]=1;
dis_step_lock(number);
}
else if(number==2)
{
// 如果是第二個(gè),則還需要判斷第一個(gè)是否扣回去
if(data[0]==0x00)
{
lock(1);
}
else if(data[0]==0x01)
{
data[1]=0x01;
dis_step_lock(number);
}
}
else if(number>=3)
{
for(i=number-2;i>=1;i--)
{
if(data[i-1]!=0x00)
{
//如果遇到還沒有解開的, 逆回去先解開前n-1第一個(gè)還沒有解下來的
unlock(i);
}
}
//說明前面n-2個(gè)都已經(jīng)解下來了
if(i==0)
{
//說明前面n-2個(gè)都解下來了。
// 再判斷n-1個(gè)是否解下來
if(data[number-2]==0x01)
{
//如果這個(gè)沒有放下來
// 就可以把n這個(gè)鎖扣去來了
data[number-1]=1;
dis_step_lock(number);
}
else if(data[number-2]==0x00)
{
// 如果這個(gè)已經(jīng)放下來了,則需要先把這個(gè)扣上去,才能扣下后面那個(gè)
lock(number-1);
}
}
}
}
return 1;
}
void dis_step(int number)
{
int i;
steps++;
printf("(unlock)%3d step: %3d ",number,steps);
fprintf(fp,"unlock %3d step: %3d ",number,steps);
for(i=0;i<LOCK_NUMBER;i++)
{
printf(" %d",data);
fprintf(fp," %d",data);
}
printf("\r\n");
fprintf(fp,"\r\n");
}
void dis_step_lock(int number)
{
int i;
steps++;
printf("( lock)%3d step: %3d ",number,steps);
fprintf(fp ," lock %3d step: %3d ",number,steps);
for(i=0;i<LOCK_NUMBER;i++)
{
printf(" %d",data);
fprintf(fp," %d",data);
}
printf("\r\n");
fprintf(fp,"\r\n");
}
|
|