マルチスレッド版数独自動生成ソフトC++コードを題材とする超初心者のためのVisual Studio C++講義
第10章 関数の再帰的使用によって魔方陣を自動生成する
第6話 仮屋崎さんの天才的方法解説の解説その1=第1の要点


void 2次座標生成() {//y横座標とx縦座標生成
int i, j, c;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
a[i][j] = -1;
}
}
for (i = 0; i < n; i++) {
a[i][i] = i;
}
c = n - 1;
for (i = 0; i < n; i++) {
if (a[i][n - 1 - i] == -1) {
c++;
a[i][n - 1 - i] = c;
}
}
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
if (a[i][j] == -1) {
c++;
a[i][j] = c;
}
}
}
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
x[a[i][j]] = j;
y[a[i][j]] = i;
}
}
}
さて、次話を元に戻しましょう。
偶数次では対角線と逆対角線が中央で交差するのに対して、
奇数次では中央で交差するのに、
なぜ一括して扱えるのか、という問題に戻ります。
話の味噌は
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
a[i][j] = -1;
}
}
にあります。
実はこの6行の役割はただ一点にあります。
偶数次・・・中央で交差しない
奇数次・・・中央で交差する
に対応するという一点です。
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
a[i][j]
= -1;
}
}
for (i = 0; i < n; i++) {
a[i][i] = i;
}
c = n - 1;
for (i = 0; i < n; i++) {
if (a[i][n - 1 - i] == -1) {
c++;
a[i][n
- 1 - i] = c;
}
}
2が7に上書きされない理由は何ですか。
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
a[i][j]
= -1;
}
}
によって

となります。
そして、
for (i = 0; i < n; i++) {
a[i][i] = i;
}
によって

となります。
c = n - 1;
for (i = 0; i < n; i++) {
if (a[i][n - 1 - i] == -1) {
c++;
a[i][n
- 1 - i] = c;
}
}
によって

という局面を迎えます。
if (a[i][n - 1 - i] == -1) {
c++;
a[i][n
- 1 - i] = c;
}
赤に注目です。-1ときだけc++;を実行して代入せよとなっています。
ところが、中央には2が入っているので
if (a[i][n - 1 - i] == -1) {
c++;
a[i][n
- 1 - i] = c;
}
は実行されません。
というわけで2が7に上書きされずに、番号づけは最後までうまくいくわけです。

以上が仮屋崎さんのコードを理解するために必要なことの第1の要点です。