マルチスレッド版数独自動生成ソフトC++コードを題材とする超初心者のためのVisual Studio C++講義
第13章 様々な魔方陣の作成および自動生成
第11話 マルチスレッドによる魔方陣1個生成普遍版の解答例

を実現させるプログラム例
#pragma warning(disable: 4996)//第2編のために必要
#include<iostream>//インクルードファイルiostreamの読み込み
#include<conio.h>//while(!_kbhit());を使うためのお呪い
#include<string> //文字列変数を使えるようにするために組み込む
#include <iomanip> //setprecisionを使えるように組み込む
#include <cmath>//powなどを使うときに必要
#include <ctime>//time()(←現時刻発生する関数)を使うために必要
using namespace std;//coutを使うときに必要なお呪い
#include <process.h>//_beginthreadを使うために必要
void 変身の術関数(void* aa);//スレッドを派生させる関数
const size_t n = 6;
const size_t th = n * n;
void f(int p, int s);//魔方陣生成関数
void 2次座標生成();
size_t 継続 = 1;
size_t m[n][n];//魔方陣を収納する4次元配列
size_t a[th][n][n];//魔方陣を形成するための作業用3次元配列
size_t cn = 0;//生成された魔方陣の総数をカウントする変数
size_t y[th];//縦座標
size_t x[th];//横座標
size_t b[n][n];//y座標・x座標形成のための2次元配列
size_t mg = n * (th + 1) / 2;//魔方陣の対角線または行または列の合計
size_t h1[th];
int main() {
clock_t hj, ow;
2次座標生成();
cout << "マルチスレッド版" << n << "次魔方陣検証開始" << endl << endl;
hj = clock();
for (size_t i = 0; i < th; i++) {
h1[i] = i + 1;
}
size_t ii[th];
for (size_t i = 0; i < th; i++) {
ii[i] = i;
_beginthread(変身の術関数, 0, &ii[i]); //新しいスレッドを起動して、そのスレッド上で関数問題生成関数を働かせなさいの命令
}
while (継続) {
}
ow = clock();
int tk[th];
for (size_t i = 0; i < th; i++)tk[i] = 0;
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
tk[m[i][j] - 1] = 1;
if (m[i][j] < 10) {
cout << " " << m[i][j] << " ";
}
else {
cout << m[i][j] << " ";
}
}
cout << endl;
}
cout << endl;
cout << n << "次魔方陣生成時間は" << (double)(ow - hj) / CLOCKS_PER_SEC << "秒です。" << endl;
size_t h = 1;
for (size_t i = 0; i < th; i++) {
if (tk[i] == 0) {
h = 0;
break;
}
}
cout << endl;
if (h == 1)cout << "重複も漏れもありません。"; else cout << "異常あり";
cout << endl;
while (!_kbhit());//待機させるための命令
return(0);
}
void 変身の術関数(void* aa) {//マルチスレッド
size_t p = *(size_t*)aa;
a[p][y[0]][x[0]] = h1[0];
f(p, 1);
}
void f(int p, int s) {//魔方陣生成関数
for (size_t i = 0; i < th; i++) {
if (継続 == 0)return;
size_t h = 1;
for (size_t j = 0; j < s; j++) {
if (a[p][y[j]][x[j]] == h1[i]) {
h = 0;
break;
}
}
if (h == 1) {
a[p][y[s]][x[s]] = h1[i];
}
if (継続 == 0)return;
if (h == 1) {
if (y[s] == n - 1 && x[s] == n - 1) {
size_t 合計 = 0;
for (size_t j = 0; j < n; j++) {
合計 += a[p][j][j];
}
if (合計 != mg)h = 0;
}
}
if (継続 == 0)return;
if (h == 1) {
if (y[s] == n - 1 && x[s] == 0) {
size_t 合計 = 0;
for (size_t j = 0; j < n; j++) {
合計 += a[p][j][n - 1 - j];
}
if (合計 != mg)h = 0;
}
}
if (継続 == 0)return;
if (h == 1) {
if (y[s] == 0 && x[s] == n - 2) {
size_t 合計 = 0;
for (size_t j = 0; j < n; j++) {
合計 += a[p][y[s]][j];
}
if (合計 != mg)h = 0;
}
}
if (継続 == 0)return;
if (h == 1) {
if (y[s] > 0 && y[s] < n - 1 && x[s] == n - 1) {
size_t 合計 = 0;
for (size_t j = 0; j < n; j++) {
合計 += a[p][y[s]][j];
}
if (合計 != mg)h = 0;
}
}
if (継続 == 0)return;
if (h == 1) {
if (y[s] == n - 2 && x[s] == 0) {
size_t 合計 = 0;
for (size_t j = 0; j < n; j++) {
合計 += a[p][j][x[s]];
}
if (合計 != mg)h = 0;
}
}
if (継続 == 0)return;
if (h == 1) {
if (y[s] == n - 1 && x[s] > 0 && x[s] < n - 1) {
size_t 合計 = 0;
for (size_t j = 0; j < n; j++) {
合計 += a[p][j][x[s]];
}
if (合計 != mg)h = 0;
}
}
if (継続 == 0)return;
if (h == 1) {
if (y[s] == n - 1 && x[s] == n - 2) {
size_t 合計 = 0;
for (size_t j = 0; j < n; j++) {
合計 += a[p][y[s]][j];
}
if (合計 != mg)h = 0;
}
}
if (継続 == 0)return;
if (h == 1) {
if (s + 1 < th) {
f(p, s + 1);
}
else {
for (size_t j = 0; j < th; j++) {
m[y[j]][x[j]] = a[p][y[j]][x[j]];
}
cn++;
継続 = 0;
if (cn == 1) {
a[p][y[s]][x[s]] = 0;
return;
}
}
}
if (cn == 1) {
a[p][y[s]][x[s]] = 0;
return;
}
a[p][y[s]][x[s]] = 0;
}
}
void 2次座標生成() {//y横座標とx縦座標生成
int i, j, c;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
b[i][j] = -1;
}
}
for (i = 0; i < n; i++) {
b[i][i] = i;
}
c = n - 1;
for (i = 0; i < n; i++) {
if (b[i][n - 1 - i] == -1) {
c++;
b[i][n - 1 - i] = c;
}
}
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
if (b[i][j] == -1) {
c++;
b[i][j] = c;
}
}
}
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
x[b[i][j]] = j;
y[b[i][j]] = i;
}
}
}
解説
改良点のポイントは
size_t 継続 = 1
size_t cn =
0;//生成された魔方陣の総数をカウントする変数;
if (継続 == 0)return;
cn++;
継続 = 0;
などです。
1個生成でもかなり速いですが、
私が構造解析型と名付けた改良を行うと3倍から5倍の速さを実現できます。
次話において構造解析型の説明をします。