第17講 関数の再帰的呼び出しによる3次・4次魔方陣ソフトの改良
第3話 偶数版枠番号付けの解説その1
        void g2(char n){
          char i,m;
          m=n/2;
          for(i=0;i<n*n;i++){
            if(i<n){
              x[i]=i;
              y[i]=i;
            }
            else if(i<2*n){
              x[i]=2*n-i-1;
              y[i]=i-n;
            }
            else if(i<(m+1)*n){
              x[i]=(i-2*n)%(n-2);
              y[i]=(i-2*n)/(n-2);
              if(x[i]>=y[i])x[i]++;
              if(x[i]>=n-y[i]-1)x[i]++;
            }
            else{
              x[i]=(i-2*n)%(n-2);
              y[i]=(i-2*n)/(n-2);
              if(x[i]>=n-y[i]-1)x[i]++;
              if(x[i]>=y[i])x[i]++;
            }
          }

の解説を続けましょう。残っているのは、
            else if(i<(m+1)*n){
              x[i]=(i-2*n)%(n-2);
              y[i]=(i-2*n)/(n-2);
              if(x[i]>=y[i])x[i]++;
              if(x[i]>=n-y[i]-1)x[i]++;
            }
            else{
              x[i]=(i-2*n)%(n-2);
              y[i]=(i-2*n)/(n-2);
              if(x[i]>=n-y[i]-1)x[i]++;
              if(x[i]>=y[i])x[i]++;
            }

のみです。まず、前半
            else if(i<(m+1)*n){
              x[i]=(i-2*n)%(n-2);
              y[i]=(i-2*n)/(n-2);
              if(x[i]>=y[i])x[i]++;
              if(x[i]>=n-y[i]-1)x[i]++;
            }
から解説していきましょう。
i<(m+1)*nでないわけですから、iは3*4以上すなわち12以上です。

10 11
12 13
14 15

 

  












赤の番号はx[i]、濃紺の番号はy[i]、ピンクの番号は枠番号gに対応)
トレースしてみましょう。
i=12のとき、
 x[12]=(12-2*4)%(4-2)=4%2=0
 y[12]=(12-2*4)/(4-2)=4/2=2
 x[12]=0≧4-y[12]-1=1は成り立ちませんので、x[i]++;は実行されません。
 x[12]=0≧y[12]=2は成り立ちませんから同じくx[i]++;は実行されず、結局x[12]=0です。
i=13のとき、
 x[13]=(13-2*4)%(4-2)=5%2=1
 y[13]=(13-2*4)/(4-2)=5/2=2
 x[13]=1≧4-y[13]-1=1は成り立ちますので、x[i]++;は実行されx[13]=2
 x[13]=2≧y[13]=2は成り立ちますから同じくx[i]++;は実行され、結局x[13]=3です。
i=14のとき、
 x[14]=(14-2*4)%(4-2)=6%2=0
 y[14]=(14-2*4)/(4-2)=6/2=3
 x[14]=0≧4-y[14]-1=0は成り立ちますので、x[i]++;は実行されx[14]=1
 x[14]=1≧y[14]=3は成り立ちまえんからx[i]++;は実行されず、結局x[14]=1です。
i=15のとき、
 x[15]=(15-2*4)%(4-2)=7%2=1
 y[15]=(15-2*4)/(4-2)=7/2=3
 x[15]=1≧4-y[15]-1=0は成り立ちますので、x[i]++;は実行されx[15]=2
 x[15]=2≧y[15]=3は成り立ちまえんからx[i]++;は実行されず、結局x[15]=2です。


結局すべて思惑通り、動いていきす。
なぜでしょうか?
ポイントは2つあります。
Tx[i]=(i-2*n)%(n-2)y[i]=(i-2*n)/(n-2)は、どうしてこの形をしているのか、
Uif(x[i]>=y[i])x[i]++;if(x[i]>=n-y[i]-1)x[i]++;の意味は何か、
の2つです。
Tから説明しましょう。
 i-2*nはすでにg=7までで

10 11
12 13
14 15

 

  












赤の番号はx[i]、濃紺の番号はy[i]、ピンクの番号は枠番号gに対応)
 対角線のところが埋まっています。i-2*nだとi=9のときちょうど0になります。
 つまり、番号9を振り出しに戻しているのがi-2*nなのです

 

  












赤の番号はx[i]、濃紺の番号はy[i]、ピンクの番号は枠番号gに対応)

 (n-2)は4列から対角線の2列の除いた2列に相当します。
 y[i]の方はわかりやすいと思います。残りの0から7を2で割っているわけですから、
 順に0,0,1,1,2,2,3,3でうまく行番号と対応しています。
 0を含めた8個の数字を列数2で割っているのですから

 
8÷2=4行に対応しているのがお分かりかと思います。
(行番号は0から始まるので4行の場合3で終わる。)
そして、x[i]=(i-2*n)%(n-2)の計算では、
右表の通り0から7に対して順に、0,1,0,1,0,1,0,1
と対応していきます。

以上でTの説明は終わりです。
まだまだ謎が残っているでしょうが、
一部は氷解したのではありませんか。
これでUの謎さえ解ければすべてが氷解します。



iがgに相当するのでi-2*nをもとのiに戻しておけば

10 11
12 13
14 15

 















第11講第6話へ
 第12講第1話へ  第17講第2話へ 第17講第4話へ


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