第28講 細胞構成法による魔方陣の作成△

第14話 
細胞合成の解説その3

コード再掲
         void sbg(int g){
           if(ks==200)return;
           int i,j,k,h,w,ii,iii;
           ii=rand()%24;
           for(i=0;i<24;i++){
             iii=(ii+i)%24;
             for(j=0;j<2;j++){
               for(k=0;k<2;k++){
                 a3[2*y[g]+j][2*x[g]+k]=sbr[iii][j][k];
               }
             }  
             h=1;
             if(g==n-1){
               w=0;
               for(j=0;j<2*n;j++){
                 w+=a3[j][j];
               }
               if(w!=5*n)h=0;
             }
             if(h==1){
               if(g==2*n-2){
                 w=0;
                 for(j=0;j<2*n;j++){
                   w+=a3[j][2*n-1-j];
                 }
                 if(w!=5*n)h=0;
               }
             }
             if(h==1){
               if(y[g]==0 && x[g]==n-2){
                 for(j=0;j<2;j++){
                   w=0;
                   for(k=0;k<2*n;k++){
                     w+=a3[2*y[g]+j][k];
                   }
                   if(w!=5*n){
                     h=0;
                     break;
                   }
                 }
               }
             }
             if(h==1){
             if(x[g]==0 && y[g]==n-2){
               for(j=0;j<2;j++){
                 w=0;
                 for(k=0;k<2*n;k++){
                   w+=a3[k][2*x[g]+j];
                 }
                 if(w!=5*n){
                   h=0;
                   break;
                 }
               }
             }
           }
           if(h==1){
           if(g>2*n-2 && x[g]==n-1){
             for(j=0;j<2;j++){
               w=0;
               for(k=0;k<2*n;k++){
                 w+=a3[2*y[g]+j][k];
               }
               if(w!=5*n){
                 h=0;
                 break;
               }
             }
           }
         }
         if(h==1){
           if(g>2*n-2 && y[g]==n-1){
             for(j=0;j<2;j++){
               w=0;
               for(k=0;k<2*n;k++){
                 w+=a3[k][2*x[g]+j];
               }
               if(w!=5*n){
                 h=0;
                 break;
               }
             }
           }
         }
         if(h==1){
           if(g==n*n-2){
             for(j=0;j<2;j++){
               w=0;
               for(k=0;k<2*n;k++){
                 w+=a3[k][2*x[g]+j];
               }
               if(w!=5*n){
                 h=0;
                 break;
               }   
             }
           }
         }
         if(h==1){
           if(g==n*n-1){
             for(j=0;j<2;j++){
               w=0;
               for(k=0;k<2*n;k++){
                 w+=a3[2*y[g]+j][k];
               }
               if(w!=5*n){
                 h=0;
                 break;
               }
             }
           }
         }
         if(h==1){
           if(g+1<n*n){
             sbg(g+1);
           }
           else{
             array<String^>^ w=gcnew array<String^>(15);
             for(j=0;j<2*n;j++){
               for(k=0;k<2*n;k++){
                 w[k]=(a3[j][k]).ToString();
               }
               dataGridView1->Rows->Add(w);
             }
             for(j=0;j<14;j++)w[j]=L"";
             dataGridView1->Rows->Add(w);
             ks++;
             if(ks==200)return;
           }
         }
       }
     } 

対角線、逆対角線、1行目、1列目、2行目以降、2列目以降
(本当はさらに最終行と最終列のチェックもしなければなりません。
この段階では不備に気がつかず、すべての部品を組み立て細胞構成法を完成させる段階で不備を訂正しました。
これについては、細胞構成法の完成の解説で説明します。)
のすべてのチェックが終わってから、はじめて次のセルに進むことが出来ます。
それが、
         if(h==1){
           if(g+1<n*n){
             sbg(g+1);
           }

           else{
             array<String^>^ w=gcnew array<String^>(15);
             for(j=0;j<2*n;j++){
               for(k=0;k<2*n;k++){
                 w[k]=(a3[j][k]).ToString();
               }
               dataGridView1->Rows->Add(w);
             }
             for(j=0;j<14;j++)w[j]=L"";
             dataGridView1->Rows->Add(w);
             ks++;
             if(ks==200)return;
           }
         }

           if(g+1<n*n){
             sbg(g+1);
           }

です。これは関数の再帰的使用です。

0 5 3
6 1 7
4 8 2

自分が自分を呼び出しますが、呼び出す自分と呼び出される自分は世界の次元が違います。
例えば、セル番号0が呼び出す自分はセル番号1です。
再帰的使用では現在どの次元にいるのかを明確に把握していないと訳がわからなくなります。
入れ子式人形の比喩では、自分が自分を呼び出すときそれはより内側の自分です。
外側の入れ子式人形が内側の入れ子式人形を呼び出すのです。
           if(g+1<n*n){
             sbg(g+1);
           }

による呼び出しはいつまで行われるのでしょうか。
最後の人形=セル番号8を呼び出すまで行われます。
8はn*n-1です。もっとも内側の人形=セル番号8まで進むと、
もう呼び出す人形がいないので呼び出しは終わります。
もっとも内側に到達したとき、すなわちもっとも内なる自分に到達したとき、
遡及の旅は終わりを遂げるのです。
自分探しの旅は終わるのです。
自分のもっとも奥なる本質を見いだして。
遡及の終了は、細胞の合成の成功を意味します。
それで、DataGrridViewへのデータの表示が
             array<String^>^ w=gcnew array<String^>(15);
             for(j=0;j<2*n;j++){
               for(k=0;k<2*n;k++){
                 w[k]=(a3[j][k]).ToString();
               }
               dataGridView1->Rows->Add(w);
             }
             for(j=0;j<14;j++)w[j]=L"";
             dataGridView1->Rows->Add(w);
             ks++;
             if(ks==200)return;
によって行われ、細胞総数ksがカウントされます。
             for(j=0;j<2*n;j++){
               for(k=0;k<2*n;k++){
                 w[k]=(a3[j][k]).ToString();
               }
               dataGridView1->Rows->Add(w);
             }
と2次元ループになっている理由は、各セルあたり2行あるからです。
細胞は、2行2列でした。




第13話へ
第15話へ

戻る

VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座