マルチスレッド版数独自動生成ソフトC++コードを題材とする超初心者のためのVisual Studio C++講義
第10章 関数の再帰的使用によって魔方陣を自動生成する

第4話 仮屋崎さんの天才的方法(1次元を2次元座標と関連付ける一般的方法)の紹介





0 8 9 4
10 1 5 11
12 6 2 13
7 14 15 3



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



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



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 16 17 18 19 20 21 8
22 1 23 24 25 26 9 27
28 29 2 30 31 10 32 33
34 35 36 3 11 37 38 39
40 41 42 12 4 43 44 45
46 47 13 48 49 5 50 51
52 14 53 54 55 56 6 57
15 58 59 60 61 62 63 7

を実現するコード例

#include<iostream>//インクルードファイルiostreamの読み込み

#include<conio.h>//while(!_kbhit());を使うためのお呪い

#include<string> //文字列変数を使えるようにするために組み込む

#include <iomanip> //setprecisionを使えるように組み込む

#include <cmath>//powなどを使うときに必要

#include <ctime>//time()(←現時刻発生する関数)を使うために必要

using namespace std;//coutを使うときに必要なお呪い

const int n = 8;//具体的な数字を使うのではなく、 n を使うと汎用性のあるプログラムになる!

void f(int s);//順列生成関数←引数名をgからsに変更(2026年3月19日)

void 2次座標生成();

void 番号づけ確認();

int a[n][n]; //将来n次魔方陣まで生成できるようにn * nに変更

int c[n][n];//2次元配列

int y[n];//縦座標

int x[n];//横座標

int cn = 0; //anに変更 変更理由はnuberの頭文字nは整数を表す場合が多いからです。

int mg;//魔方陣の対角線等の合計

int main() {   

    2次座標生成();//y横座標とx縦座標生成

    番号づけ確認();//部屋番号と座標の関連づけが成功しているか確認!

    mg = n * (n * n + 1) / 2;

    //f(0);

    //cout << endl << "生成された" << n << "次魔方陣総数は" << cn << "個です。" << endl;//2026年3月19日訂正

    while (!_kbhit());//待機させるための命令

    return(0);

}

void f(int s) {

   

 

}

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;

        }

    }

}

void 番号づけ確認() {

    int i, j;

    for (i = 0; i < n; i++) {

        for (j = 0; j < n; j++) {

            if (a[i][j] < 10)cout << " " << a[i][j] << " ";

            if (a[i][j] >= 10)cout << a[i][j] << " ";

        }

        cout << endl;

    }

    cout << endl;

}

 



おそらく多くの人がさっぱりわからないよ、

と悲鳴をあげていると思います。

でも大丈夫ですよ。

次話以降で詳しく解説していきます。

前に言った言葉を繰り返します。

1人たりとも取りこぼしません。


第10章第3話へ 第10章第5話へ

本講義トップへ