第13講 3次魔方陣の自動生成 
第12話 栄冠は君へ!

こうして、ループ
                      for(i6=1;i6<10;i6++){
                        a[1][2]=i6;
                        if(a[1][2]!=a[0][0] && a[1][2]!=a[0][1] && a[1][2]!=a[0][2] && a[1][2]!=a[1][0] && a[1][2]!=a[1][1]){
                          if(a[1][0]+a[1][1]+a[1][2]==15){
                                ・
                                ・
                                ・
                        }
                      }

の3度の目の挑戦が成功を収め、

栄冠まで後3歩となり、終局は間近しの感があるかもしれませんが、
実は、かなり険しい道程を辿らなければなりません。
いかに険しいか、セルの数字の動きだけをしばらく追ってみましょう。





1列目の合計と逆対角線の合計が15になりません。

これを見ると栄冠がいかに遠いかがわかります。
ですから、今までと同じようにトレースしていくと第13講は後何十話も必要になり、
私が立てている1講10話以内のをめあすとするから大きく逸脱することになってしまいます。
それで途中を省略させていただいて(当然かなりの省略になります。どうかご自分で動きを追ってみてください。)、
ファイナルステージから、トレースを再開します。

すなわち、
                                        for(i9=1;i9<10;i9++){
                                          a[2][2]=i9;
                                          if(a[2][2]!=a[0][0] && a[2][2]!=a[0][1] && a[2][2]!=a[0][2] && a[2][2]!=a[1][0] && a[2][2]!=a[1][1] && a[2][2]!=a[1][2] && a[2][2]!=a[2][0] && a[2][2]!=a[2][1]){
                                            if(a[2][0]+a[2][1]+a[2][2]==15 && a[0][2]+a[1][2]+a[2][2]==15 && a[0][0]+a[1][1]+a[2][2]==15 ){
                                              f(a);
                                              cn++;
                                            }
                                          }
                                        }

の何度目(私の脳髄では数えられません)の第1巡目から話題を再開します。

重複検査
if(a[2][2]!=a[0][0] && a[2][2]!=a[0][1] && a[2][2]!=a[0][2] && a[2][2]!=a[1][0] && a[2][2]!=a[1][1] &&
a[2][2]!=a[1][2] && a[2][2]!=a[2][0] && a[2][2]!=a[2][1]){
に抵触

重複検査
if(
a[2][2]!=a[0][0] && a[2][2]!=a[0][1] && a[2][2]!=a[0][2] && a[2][2]!=a[1][0] && a[2][2]!=a[1][1] && a[2][2]!=a[1][2] && a[2][2]!=a[2][0] && a[2][2]!=a[2][1]){
に抵触

重複検査
if(a[2][2]!=a[0][0] && a[2][2]!=a[0][1] && a[2][2]!=a[0][2] && a[2][2]!=a[1][0] && a[2][2]!=a[1][1] && a[2][2]!=a[1][2] && a[2][2]!=a[2][0] &&
a[2][2]!=a[2][1]){
に抵触

重複検査
if(a[2][2]!=a[0][0] && a[2][2]!=a[0][1] && a[2][2]!=a[0][2] && a[2][2]!=a[1][0] && a[2][2]!=a[1][1] && a[2][2]!=a[1][2] && a[2][2]!=a[2][0] &&
a[2][2]!=a[2][1]){
に合格ですが、合計検査if(a[2][0]+a[2][1]+a[2][2]==15 && a[0][2]+a[1][2]+a[2][2]==15 && a[0][0]+a[1][1]+a[2][2]==15 ){に不合格

重複検査
if(a[2][2]!=a[0][0] && a[2][2]!=a[0][1] && a[2][2]!=a[0][2] && a[2][2]!=a[1][0] &&
a[2][2]!=a[1][1] && a[2][2]!=a[1][2] && a[2][2]!=a[2][0] && a[2][2]!=a[2][1]){
に抵触

重複検査
if(a[2][2]!=a[0][0] && a[2][2]!=a[0][1] &&
a[2][2]!=a[0][2] && a[2][2]!=a[1][0] && a[2][2]!=a[1][1] && a[2][2]!=a[1][2] && a[2][2]!=a[2][0] && a[2][2]!=a[2][1]){
に抵触

重複検査
if(a[2][2]!=a[0][0] &&
a[2][2]!=a[0][1] && a[2][2]!=a[0][2] && a[2][2]!=a[1][0] && a[2][2]!=a[1][1] && a[2][2]!=a[1][2] && a[2][2]!=a[2][0] && a[2][2]!=a[2][1]){
に抵触

両検査
if(a[2][2]!=a[0][0] && a[2][2]!=a[0][1] && a[2][2]!=a[0][2] && a[2][2]!=a[1][0] && a[2][2]!=a[1][1] && a[2][2]!=a[1][2] && a[2][2]!=a[2][0] && a[2][2]!=a[2][1]){
if(a[2][0]+a[2][1]+a[2][2]==15 && a[0][2]+a[1][2]+a[2][2]==15 && a[0][0]+a[1][1]+a[2][2]==15 ){

にようやく合格です。
栄冠をついに勝ち取りました。
そして、はじめてf(a);によって関数fが呼び出されます。
void f(int **a);{
  int i,j;
  for(i=0;i<3;i++){
    for(j=0;j<3;j++){
      cout<<a[i][j]<<" ";
    }
    cout<<endl;
  }
  cout<<endl;
}

によって、1個目の3次魔方陣がコンソール画面にアウトプットされるわけです。
入門
とても長いトレースになりました。

どうもご苦労さまでした。
トレースはまだまだ延々と続くわけですが、省略させていただきます。
はじめは、この後for文で4次魔方陣も制作するつもりでしたが、
私も当然挑戦する気力もありませんし、皆さんもウンザリですよね。
ですから、以上で第13講を終了とさせて頂き、
いよいよ関数の再帰的呼び出しに入りたいと思います。
関数の再帰的呼び出しによれば、理論的には100次魔方陣であろうと、1000次魔方陣であろうと可能です。
しかも、プログラムの書き直しなしにです。
つまり、普遍的なプログラムにすることが可能です。
for文の場合は個々にプログラムしなければならないのとは対照的です。

普遍的とは、どんな場合にも通用するということ、つまり汎用的であると言うことです。
基本的にプログラムは、汎用性の広いものを目標にすべきです。
汎用性が広く、簡単であるということでいかに関数の再帰的呼び出しが便利であるかわかります。




第11話へ 第14講第1話へ

戻る

C言語講義第1部へ
VB講義へ
VB講義基礎へ

vc++講義へ第1部へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)