找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6717|回復: 0
打印 上一主題 下一主題
收起左側(cè)

程序給你演示如何解開九鎖連環(huán)

[復制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:76190 發(fā)表于 2015-4-5 20:35 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式

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

       先上點圖片。
      這個圖標就是通過C程序,把每一個打印出來,保存到一個txt文檔里,再導入到excel里去的。其中1就是鎖著的,0表示鎖下來的。




可以看到,解開九鎖連環(huán)一共需要341步。當然,解下一個環(huán)或扣回一個環(huán)都算一步。同時,大家也看到,我在程序里或表格里,都注明了哪一步是扣或解開哪一個環(huán)。

好了,慢慢理解這個規(guī)律了。下面就是上程序了,這個程序是純粹的C語言,暫時沒有優(yōu)化,不可,至少可以執(zhí)行,還有我寫程序時的注視,如果有興趣的朋友再進一步交流了。等以后把java的,processing動畫,flash也一直移植過去,做成演示動畫就更形象了。

//以下變是程序了,可以直接復制拷貝編譯
#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);//看是解幾個鎖的
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)// 直到把這個鎖解了才退出
   {
       
                   if(number>=3)
                   {
                  //先判斷前面n-2個是否都解開了
                        for(i=number-2;i>=1;i--)
                        {
                                 if(data[i-1]!=0x00)
                                 {
                                  //如果遇到還沒有解開的, 逆回去先解開前n-1第一個還沒有解下來的
                                   unlock(i);
                                         
                                 }
                        }
                         if(i==0)
                         {
                                  //說明前面n-2個都解下來了。
                                  // 再判斷n-1個是否解下來
                                 if(data[number-2]==0x01)
                                 {
                                         //如果這個沒有放下來
                                         // 就可以把n這個鎖解下來了
                                         data[number-1]=0;
                                                   dis_step(number);
                                 }
                                 else if(data[number-2]==0x00)
                                 {
                                         // 如果這個已經(jīng)放下來了,則需要先把這個扣上去,再能解下后面那個
                                         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)//對第n個上鎖
{
        //
        //原理,對第n個上鎖也是先判斷前面n-2個是否都解下來
        // 如果前面第n-2個解下來:  如果第n-1個是扣上去的,則可以直接扣回去
                                   //如果第n-1個是解下來的,則還需要把第n-1個扣回去
        int i;

        while(data[number-1]==0)//一定要鎖上才退出
        {
    if(number==1)
        {

                 // 如果是第一個,直接扣上去了
                data[0]=1;
            dis_step_lock(number);

        }
        else if(number==2)
        {

                 //  如果是第二個,則還需要判斷第一個是否扣回去
             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第一個還沒有解下來的
                   unlock(i);
                 }                       


                }

                //說明前面n-2個都已經(jīng)解下來了
                if(i==0)
                {
               
                  //說明前面n-2個都解下來了。
                  // 再判斷n-1個是否解下來
                 if(data[number-2]==0x01)
                 {
                         //如果這個沒有放下來
                         // 就可以把n這個鎖扣去來了
                         data[number-1]=1;
                         dis_step_lock(number);

                 }
                 else if(data[number-2]==0x00)
                 {
             // 如果這個已經(jīng)放下來了,則需要先把這個扣上去,才能扣下后面那個
                         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");
}



分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表