第10講 関数の再帰的使用による魔方陣の自動生成
第6話 魔方陣の各値を入力する配列を2次元に変更
魔方陣の各値を入力する配列を2次元に変更したコード例
#include<stdio.h>
#include<time.h>
void f(int g);
int
mah[5][5];
int n, cn;
int main() {
  clock_t hj, ow;
  printf("これはすべてのn次魔方陣を求めるソフトです。\n");
  printf("何次の魔方陣を発生させるのかをnに入力し\n");
  printf("エンターするとn次魔方陣がすべて生成されます。\n");
  printf("n=");
  scanf("%d", &n);
  cn = 0;
  hj = clock();
  f(0);
  ow = clock();
  printf("数独(ナンプレ)生成にかかった時間は%f秒です。\n", (double)(ow - hj) / CLOCKS_PER_SEC);
  printf("生成された%d次魔方陣は%d個です。\n", n, cn);
  return(0);
}
void f(int g) {
  int i, j, k, h, hh, w, x, y;
  
y = g / n;
  x = g % n;

  for (i = 0; i<n*n; i++) {
    if (g == 0)mah[
y][x] = i + 1;
    h = 1;
    if (g>0) {
      for (j = 0; j<g; j++) {
        if (mah[
j / n][j % n] == i + 1) {
          h = 0;
          break;
        }
      }
      if (h == 1)mah[
y][x] = i + 1;
    }
    if (h == 1) {
      if (g + 1 < n*n) {
        f(g + 1);
      }
      else {
        hh = 1;
        for (j = 0; j < n; j++) {
          w = 0;
          for (k = 0; k < n; k++) {
            w += mah[j][k];
          }
          if (w != n*(n*n + 1) / 2) {
            hh = 0;
            break;
          }
        }
        if (hh == 1) {
          for (j = 0; j < n; j++) {
            w = 0;
            for (k = 0; k < n; k++) {
              w += mah[k][j];
            }
            if (w != n*(n*n + 1) / 2) {
              hh = 0;
              break;
            }
          }
        }
        if (hh == 1) {
          w = 0;
          for (j = 0; j < n; j++) {
            w += mah[j][j];
          }
          if (w != n*(n*n + 1) / 2) {
            hh = 0;
            break;
          }
        }
        if (hh == 1) {
          w = 0;
          for (j = 0; j < n; j++) {
            w += mah[j][n - 1 - j];
          }
          if (w != n*(n*n + 1) / 2) {
            hh = 0;
            break;
          }
        }
        if (hh == 1) {
          for (j = 0; j < n; j++) {
            for (k = 0; k < n; k++) {
              if(mah[j][k]<10)printf(" %d ", mah[j][k]); //二桁への対応
              if(mah[j][k]>=10)printf("%d ", mah[j][k]); //二桁への対応

            }
            printf("\n");
          }
          printf("\n");
          cn++;
        }
      }
    }
  }
}

実行結果例
これはすべてのn次魔方陣を求めるソフトです。
何次の魔方陣を発生させるのかをnに入力し
エンターするとn次魔方陣がすべて生成されます。
n=3
2 7 6
9 5 1
4 3 8

2 9 4
7 5 3
6 1 8

4 3 8
9 5 1
2 7 6

4 9 2
3 5 7
8 1 6

6 1 8
7 5 3
2 9 4

6 7 2
1 5 9
8 3 4

8 1 6
3 5 7
4 9 2

8 3 4
1 5 9
6 7 2

魔方陣生成にかかった時間は0.254秒です。生成された3次魔方陣8個です。

配列が1次元のときは
魔方陣生成にかかった時間は0.105秒です。生成された3次魔方陣8個です。

でしたから、かえって遅くなっていますが、
配列を2次元に変更したことによって、
4次魔方陣全生成が私の旧式のパソコンでさえ11分程度で出来るようになる途が開かれるのです。
もちろん、1次元配列のままでも可能ですが、
コードがかなり難しくなります。
今話や前話のままではおそらく10時間ぐらいはかかる全生成が11分程度になる改良とは、
なんだかわかりますか。ヒントを次話でお話します。

尚、
            w += mah[j][n - 1 - j];
もわかりにくいと思いますので、
トレースしておきましょう。

n = 3 を前提にトレースします。
j = 0 とき、
            w += mah[
0][3 - 1 - 0];
            w += mah[0][2];
j = 1 とき、
            w += mah[1][3 - 1 - 1];
            w += mah[1][1];
j = 2 とき、
            w += mah[2][3 - 1 - 2];
            w += mah[2][0];
ですから、

 
0 0 1 2
1 3 4 5
 2 6 7 8

(色を対応させています。ピンクy座標紺x座標、白赤はg)
今回も見事に逆対角線上を動いています。



第5話へ   第7話へ

002

初心者のための excel 2016 マクロ VBA 入門講義 基礎から応用まで
vc** c言語 c** 入門 初心者 基礎から応用まで
eclipse c** 入門
魔方陣 数独で学ぶ VBA 入門

数独のシンプルな解き方・簡単な解法の研究
VB講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C**入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)
初心者のための VC**による C言語 C++ 入門 基礎から応用まで第1部
eclipse java 入門
java 入門 サイト 基礎から応用まで
本サイトトップへ