第17講 関数の再帰的呼び出しによる3次・4次魔方陣ソフトの改良
第6話 奇数版枠番号付けの解説その1

残りは奇数の場合の番号付けg1です。
        void g1(char n){
          char i,j,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-1){
              x[i]=2*n-i-1;
              y[i]=i-n;
              if(x[i]<=y[i]){
                x[i]--;
                y[i]++;
              }
            }
            else if(i<2*n+(n*n-3*n)/2){
              x[i]=(i-2*n+1)%(n-2);
              y[i]=(i-2*n+1)/(n-2);
              if(x[i]>=y[i])x[i]++;
              if(x[i]>=n-y[i]-1)x[i]++;
            }
            else if(i<3*n-1+(n*n-3*n)/2){
              x[i]=i-2*n-(n*n-3*n)/2;
              y[i]=m;
              if(x[i]>=y[i])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]++;
            }
          }
いきなりこちらから解説したら、超難解な解説になってでしょう。
いまだに難しいとはいえ、手順を踏んだ今絶対に理解できない程、難しいわけではないということは理解して頂けるでしょうか。
偶数版との決定的な違いは

0 1 2 3
0 0 8 9 4
1 10 1 5 11
2 12 6 2 13
3 7 14 15 3


0 1 2 3 4
0 0 9 10 11 5
1 12 1 13 6 14
2 15 16 2 17 18
3 19 7 20 3 21
4 8 22 23 24 4

(赤の番号はx、濃紺の番号はy、ピンクの番号はgに対応)

□2□

の存在です。ここで対角線が交差しています。
これが存在しているため、
偶数版と2点の違いが派生します。


1点目の違いとは、このセルの存在は逆対角線以降のセル番号を
それぞれ1つずらし小さくします。
else if(i<2*n-1)となっている所以が分かります。



2点目の違いは、

0 1 2 3 4
0 0 9 10 11 5
1 12 1 13 6 14
2 15 16 2 17 18
3 19 7 20 3 21
4 8 22 23 24 4


□2□

の行だけが他の行に比べて入れるセルが一つ多い点です。
他の行はn-2=3個であるの対して、
この行だけはn-1=4個です。
偶数次の場合はすべて行に入るセル数はn-2(個)ですのに対して、
奇数次の場合は、真ん中の行だけn-1(個)なのです。






この2点の違いのためg1はg2より複雑な処理を必要とします。
ただし、g2を下敷きにしてそれを変更することによって奇数次番号付けができます。
次の二つの部分は

0 0 9 10 11 5
1 12 □1□ 13 6 14







3 19 7 20 3 21
4 8 22 23 24 4








基本的に偶数次の場合と同じです。行に入る個数はn-2(個)ですし、
対角線または逆対角線に掛かるかまたぐとき一つ右にずれる点は同じだからです。
ですから、
            else if(i<2*n+(n*n-3*n)/2){
              x[i]=(i-2*n+1)%(n-2);
              y[i]=(i-2*n+1)/(n-2);
              if(x[i]>=y[i])x[i]++;
              if(x[i]>=n-y[i]-1)x[i]++;
            }
            else if(
i<3*n-1+(n*n-3*n)/2){
              x[i]=i-2*n-(n*n-3*n)/2;
              y[i]=m;
              if(x[i]>=y[i])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]++;
            }

の部分はほぼ同じコーティングになっているのです。
ではなぜ、i<2*n+(n*n-3*n)/2やi<3*n-1+(n*n-3*n)/2のように複雑な形をしているのでしょうか。


第11講第6話へ
 第12講第1話へ  第17講第5話へ 第17講第7話へ


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