第12講 プロシージャの再帰的使用によって魔方陣を自動生成する
第7話 複雑なセル番号付けはいかにしたら可能か。
n=3のとき
0 | 5 | 3 |
6 | 1 | 7 |
4 | 8 | 2 |
n=4のとき
0 | 8 | 9 | 4 |
10 | 1 | 5 | 11 |
12 | 6 | 2 | 13 |
7 | 14 | 15 | 3 |
n=5のとき
0 | 9 | 10 | 11 | 5 |
12 | 1 | 13 | 6 | 14 |
15 | 16 | 2 | 17 | 18 |
19 | 7 | 20 | 3 | 21 |
8 | 22 | 23 | 24 | 4 |
n=6のとき
0 | 12 | 13 | 14 | 15 | 6 |
16 | 1 | 17 | 18 | 7 | 19 |
20 | 21 | 2 | 8 | 22 | 23 |
24 | 25 | 9 | 3 | 26 | 27 |
28 | 10 | 29 | 30 | 4 | 31 |
11 | 32 | 33 | 34 | 35 | 5 |
n=7のとき
0 | 13 | 14 | 15 | 16 | 17 | 7 |
18 | 1 | 19 | 20 | 21 | 8 | 22 |
23 | 24 | 2 | 25 | 9 | 26 | 27 |
28 | 29 | 30 | 3 | 31 | 32 | 33 |
34 | 35 | 10 | 36 | 4 | 37 | 38 |
39 | 11 | 40 | 41 | 42 | 5 | 43 |
12 | 44 | 45 | 46 | 47 | 48 | 6 |
偶数次のときと奇数次の場合では、番号付けの規則が違います。
その理由は、奇数次の場合対角線が交差するからです。
0 | 13 | 14 | 15 | 16 | 17 | 7 |
18 | 1 | 19 | 20 | 21 | 8 | 22 |
23 | 24 | 2 | 25 | 9 | 26 | 27 |
28 | 29 | 30 | 3 | 31 | 32 | 33 |
34 | 35 | 10 | 36 | 4 | 37 | 38 |
39 | 11 | 40 | 41 | 42 | 5 | 43 |
12 | 44 | 45 | 46 | 47 | 48 | 6 |
対角線以外でも数字の重複をいかに防ぐかが、
この番号割り振りの最大の攻防点になります。
そして、番号と座標をいかに対応させるかも、
非常に困難な課題です。
番号と座標を対応させるために
仮屋崎さんは
配列a(10, 10)とiz(100)とjz(100)の3つを用意します。
a(i, j)に番号を割り振ってから、
座標iz(100)とjz(100)との逆対応を考えるという手法をとる訳です。
(今回のプログラムは、
理論的には何時の魔方陣でも可能ですが、
実際的なところは4次が限界です。
ですから、配列の要素数は
a(3, 3)とiz(15)とjz(15)でも良い訳ですが、
一応将来のことを考えて10次まで作成可能なように、
配列の要素数を多めに取ってある訳です。
改良を加えていくと、
100次でも200次でも可能になります。
ですが、それは根本的な改良を加えてからの話です。
ですから、10次までの前提で話を進めます。)
数字の重複を防ぐために、
仮屋崎さんは次のような工夫をされます。
最初に
For文を使いすべてのa(i, j)に対してあり得ない番号
128などを割り振ります。
10次までの前提ですから、
あり得る数字は100までです。
そして、以下の手順でa(i, j)に番号を割り振っていきます。
① 右下がり対角線
② 左下がり対角線
③ 残りのセル
あり得ない番号128(Byte型の最大数)を割り振るのは、
②③のためです。
つまり、重複して番号を割り振らないためです。
どうするかお分かりですか。
ヒントはIf文を使います。
②③についてはカウンター(数を数える変数)を用意しておいて、
nに初期化しておきます。
初期化とは最初に設定しておきたい数字を代入することです。
つまり、カウンターの最初の値をnにしておくのです。
0 | 13 | 14 | 15 | 16 | 17 | 7 |
18 | 1 | 19 | 20 | 21 | 8 | 22 |
23 | 24 | 2 | 25 | 9 | 26 | 27 |
28 | 29 | 30 | 3 | 31 | 32 | 33 |
34 | 35 | 10 | 36 | 4 | 37 | 38 |
39 | 11 | 40 | 41 | 42 | 5 | 43 |
12 | 44 | 45 | 46 | 47 | 48 | 6 |
(7次の場合)
その理由は、左下がり対角線の始まりがnであるからです。
a(i, j)の番号割り振りができたら、
a(i, j)とiz(g)、jz(g)との逆対応を考えます。
といっても初心者の人にとっては難しすぎますから、
iz(a(i, j)) = i
jz(a(i, j)) = j
の部分を示しておきましょう。
さて、以上の考え方を聞いてもさっぱりわからない
という方がたくさんいらっしゃると思いますが、
一応、最低でも30分は試行錯誤をされてから、
どうしてもわからないときだけ、
次話をお読みください。
プログラミングをするには、
ときには何時間も考えなければならないときもあるものです。
粘り強く挑戦して頂きたいと思います。
初心者のためのc++ vc++ c言語 入門 基礎から応用までへ
初心者のための excel 2007 2010 2013 vba マクロ 入門 基礎から応用まで
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
vb講義トップへ
VB講義基礎へ
専門用語なしのC++入門へ
専門用語なしのJava入門へ
専門用語なしのVBA入門
数独のページ
魔方陣のページ
数学研究室に戻る
本サイトトップへ