第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以上です。
0 | 1 | 2 | 3 | |
0 | 0 | 8 | 9 | 4 |
1 | 10 | 1 | 5 | 11 |
2 | 12 | 6 | 2 | 13 |
3 | 7 | 14 | 15 | 3 |
(赤の番号は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までで
0 | 1 | 2 | 3 | |
0 | 0 | 8 | 9 | 4 |
1 | 10 | 1 | 5 | 11 |
2 | 12 | 6 | 2 | 13 |
3 | 7 | 14 | 15 | 3 |
(赤の番号はx[i]、濃紺の番号はy[i]、ピンクの番号は枠番号gに対応)
対角線のところが埋まっています。i-2*nだとi=9のときちょうど0になります。
つまり、番号9を振り出しに戻しているのがi-2*nなのです。
0 | 1 | 2 | 3 | |
0 | 0 | 0 | 1 | 4 |
1 | 2 | 1 | 5 | 3 |
2 | 4 | 6 | 2 | 5 |
3 | 7 | 6 | 7 | 3 |
(赤の番号は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で割っているのですから
0 | 1 | |
0 | 0 | 1 |
1 | 2 | 3 |
2 | 4 | 5 |
3 | 6 | 7 |
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に戻しておけば
0 | 1 | |
0 | 8 | 9 |
1 | 10 | 11 |
2 | 12 | 13 |
3 | 14 | 15 |
第11講第6話へ 第12講第1話へ 第17講第2話へ 第17講第4話へ
VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual
Basic入門基礎講座