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

第13話 
細胞合成の解説その2

コード再掲
         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;
           }
         }
       }
     } 

0 * *
* 0 *
* * 0

対角線が埋まった段階で、対角線の合計が同じになっているか調べます。

1 2 * * * *
3 4 * * * *
* * 1 2 * *
* * 3 4 * *
* * * * 1 2
* * * * 3 4

           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];
               }
             }  
3次元ループとなっていますが、iiiが0から23の細胞番号に相当し、

   0 1 
1 2
3 4

jは行、kは列に対応します。
尚、iをiiiにしているのは番号を0,1,2,3,・・・,23と始まりが0からではなく、
8,9,10,・・・,23,0,1,2,3,4,5,6,7のように始まりをランダムにするためです。
始まりが違っても結局はすべての細胞24個について調べることになることがお分かりでしょうか。







             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;
             }
は対角線の合計がnの5倍になっているかを調べるためのものです。n=3すなわち6次の場合は15ですね。
もし、なっていない場合は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;
                   }
                 }
               }
             }
の役割はお分かりでしょうか。

0 3 17
* 0 *
0 * 0
1 2 1 4 3 4
3 4 2 3 1 2
* * 1 2 * *
* * 3 4 * *
1 2 * * 1 2
3 4 * * 3 4

尚、
                 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;
                   }
                 }
となっている理由は、オレンジの1行目と2行目の合計の両方をチェックしなければならないからです。
j=0のときが、1行目の合計チェックです。
1行目でもし条件をクリアしないとfor(j=0;j<2;j++)は繰り返す必要がないので、break; が入れてあります。
1行目については3列目ではなく2列目に細胞が埋まった段階で行の合計を調べなければなりません。
なぜなら、このプログラムでは対角線→逆対角線→行の順で数字を入れていっているので、
1行目の2列目に細胞が埋め込まれた段階で、1行目には細胞がすべて埋め込まれているからです。
             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;
                 }
               }
             }
           }
についても

0 3 17
0 0 *
0 * 0
1 2 1 4 3 4
3 4 2 3 1 2
1 2 1 2 * *
3 4 3 4 * *
1 2 * * 1 2
3 4 * * 3 4

同様で1列目については2行目に入れられた段階で、1列目にはすべて細胞が埋め込まれているので、
この段階で列合計のチェックをしなければならないのです。
以下
         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;
               }
             }
           }
         }
については、

* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *

最後の列または最後の列のときのみに合計をチェックすればよいのです。

* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *

ひとつ手前の列または行ではまだその列ないしは行のすべてに細胞が埋め込まれていないからです。
ここが1列目(または1行目)と他の列(または他の行)の違いです。

* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *

1行目または1列目は最後から2番目が埋まった段階ですべて細胞が埋まっているのが上の表からお分かりでしょう。



第12話へ
第14話へ

戻る

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