第16講 魔方陣汎用的生成プログラムへの挑戦
第10話 魔方陣汎用的自動生成プログラム解説その6
コード再掲
    f(0);
  }
  public static void f(int g){
    if(cn>20)return;
    int i,j,k,h;
    for(i=1;i<n*n+1;i++){
      h=1;
      m[y[g]][x[g]]=i;
      for(j=0;j<g;j++){
        if(m[y[g]][x[g]]==m[y[j]][x[j]]){
          h=0;
        }
      }
      for(j=0;j<g;j++){
        if(m[y[g]][x[g]]==m[y[j]][x[j]]){
          h=0;
        }
      }
      if(h==1){
        if(x[g]==n-1){
          w=0;
          for(j=0;j<n;j++){
            w+=m[y[g]][j];
          }
          if(w!=n*(n*n+1)/2)h=0;
        }
      }
      if(h==1){
        if(y[g]==n-1){
          w=0;
          for(j=0;j<n;j++){
            w+=m[j][x[g]];
          }
          if(w!=n*(n*n+1)/2)h=0;
        }
      }
      if(h==1){
        if(y[g]==n-1 && x[g]==0){
          w=0;
          for(j=0;j<n;j++){
            w+=m[j][n-1-j];
          }
          if(w!=n*(n*n+1)/2)h=0;
        }
      }
      if(h==1){
        if(y[g]==n-1 && x[g]==n-1){
          w=0;
          for(j=0;j<n;j++){
            w+=m[j][j];
          }
          if(w!=n*(n*n+1)/2)h=0;
        }
      }
      if(h==1){
        if(g+1<n*n){
          f(g+1);
          if(cn>20)return;
        }
        else{
          cn++;
          for(j=0;j<n;j++){
            for(k=0;k<n;k++){
              if(m[j][k]<10){
                System.out.print(" "+m[j][k]+" ");
              }
              else{
                System.out.print(m[j][k]+" ");
              }
            }
            System.out.println();
          }
          System.out.println();
          if(cn>20)return;
        }
      }
    }
  }
}

   0 1  2
0
1
2

以下同様にして

   0 1  2
0
1
2


   0 1  2
0
1
2


   0 1  2
0
1
2


   0 1  2
0
1
2


   0 1  2
0
1
2


   0 1  2
0
1
2














行(横)合計検査
      if(h==1){
        if(x[g]==n-1){
          w=0;
          for(j=0;j<n;j++){
            w+=m[y[g]][j];
          }
          if(w!=n*(n*n+1)/2)h=0;
        }
      }
を一度たりともクリアできず、次元番号2の世界=外側から3番目の人形は任務を終了して、
外側から2番目の人形の世界に戻るわけです。
関数の自己再帰は、2重の意味が前に申し上げたこと覚えていらっしゃるでしょうか。
ひとつは、より内なる自分への旅という意味の自分への再帰ですし、より深い自分自身から自分への帰還という意味の再帰です。
おそらく普通には、呼び出された関数から呼び出した関数への還帰という2番目の意味で言われるのでしょうが、
私は、より深い自分への旅立ち、より内側の人形への旅も自己再帰であると解釈したいと思います。
本当の自分をいろいろな覆いで覆っている内に、本当の自分がわからなくなっている、
そこで、自分を覆っている殻・衣・役割を脱ぎ捨てて、やっと見失っていた本来の自分に返るという意味で自己再帰と呼びたいわけです。

ごめんなさい。また、脱線してしまいました。
話を戻しましょう。

外側から3番目の人形の任務が終了して、外側から2番目の人形に戻ります。

   0 1  2
0
1
2

そして、外側から2番目の人形の
    for(i=1;i<n*n+1;i++){
      h=1;
      m[y[g]][x[g]]=i;
3巡目のループで

   0 1  2
0
1
2

これは重複検査をクリアして、再びセル番号2の世界=外側から3番目の人形へとワープします。

   0 1  2
0
1
2

そして、外側から3番目のループ
    for(i=1;i<n*n+1;i++){
      h=1;
      m[y[g]][x[g]]=i;
によって、

   0 1  2
0
1
2

となりますが、重複検査に抵触して即

   0 1  2
0
1
2

となりますが、行(横)合計検査が鬼門でクリアできません。

   0 1  2
0
1
2

重複テストにひっかかり、すぎに

   0 1  2
0
1
2

になりますが、横合計はまだ8にすぎません。以下

   0 1  2
0
1
2


   0 1  2
0
1
2


   0 1  2
0
1
2


   0 1  2
0
1
2



   0 1  2
0
1
2



   0 1  2
0
1
2














と動いていきますが、ついぞ横合計検査をクリアできずに、3番目人形の2度目の任務は完了して、
再び2番目の人形へと帰還します。

   0 1  2
0
1
2






第9話へ 第11話へ

戻る

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

初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第1部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第2部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第3部