マルチスレッド版数独自動生成ソフトC++コードを題材とする超初心者のためのVisual Studio C++講義
第11章 マルチスレッドプログラミング
第15話 第9話Ⅵの答え合わせ = マルチスレッド版魔方陣自動生成の完成
#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 = 4;
const size_t th = n * n;
void f(int p, int s);//魔方陣生成関数
void 2次座標生成();
size_t 継続[th];
size_t m[7040][th][n][n];//魔方陣を収納する4次元配列
size_t a[th][n][n];//魔方陣を形成するための作業用3次元配列
size_t cn[th];//それぞれのスレッドにおける魔方陣をカウントする1次元配列
size_t y[th];//縦座標
size_t x[th];//横座標
size_t b[n][n];//y座標・x座標形成のための2次元配列
size_t mg = n * (th + 1) / 2;//魔方陣の対角線または行または列の合計
int main() {
clock_t hj, ow;
for (size_t i = 0; i < th; i++) {
継続[i] = 1;
cn[i] = 0;
}
2次座標生成();
cout << "マルチスレッド版" << n << "次魔方陣検証開始" << endl;
hj = clock();
size_t ii[th];
for (size_t i = 0; i < th; i++) {
ii[i] = i;
_beginthread(変身の術関数, 0, &ii[i]); //新しいスレッドを起動して、そのスレッド上で関数問題生成関数を働かせなさいの命令
}
while (1) {
size_t 合計 = 0;
for (size_t i = 0; i < th; i++)合計 += 継続[i];
if (合計 == 0)break;
}
ow = clock();
for (size_t i = 0; i < 100; i++) {
for (size_t j = 0; j < th; j++) {
for (size_t k = 0; k < n; k++) {
for (size_t l = 0; l < n; l++) {
if (m[i][j][k][l] < 10) {
cout << " " << m[i][j][k][l] << " ";
}
else {
cout << m[i][j][k][l] << " ";
}
}
cout << endl;
}
cout << endl;
}
cout << endl;
}
cout << n << "次魔方陣生成時間は" << (double)(ow - hj) / CLOCKS_PER_SEC << "秒です。" << endl;
size_t gk = 0;
for (size_t i = 0; i < th; i++) {
gk += cn[i];
}
cout << "生成された" << n << "次魔方陣個数は" << gk << "個です。" << endl;
cout << "マルチスレッド版" << n << "次魔方陣生成全過程修了" << endl;
while (!_kbhit());//待機させるための命令
return(0);
}
void 変身の術関数(void* aa) {//マルチスレッド
size_t p = *(size_t*)aa;
a[p][y[0]][x[0]] = p + 1;
f(p, 1);
継続[p] = 0;
}
void f(int p, int s) {//魔方陣生成関数
for (size_t i = 0; i < th; i++) {
size_t h = 1;
for (size_t j = 0; j < s; j++) {
if (a[p][y[j]][x[j]] == i + 1) {
h = 0;
break;
}
}
if (h == 1) {
a[p][y[s]][x[s]] = i + 1;
}
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 (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 (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 (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 (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 (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 (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 (h == 1) {
if (s + 1 < th) {
f(p, s + 1);
}
else {
for (size_t j = 0; j < th; j++) {
m[cn[p]][p][y[j]][x[j]] = a[p][y[j]][x[j]];
}
cn[p]++;
/*if (cn[p] == 100) {
a[p][y[s]][x[s]] = 0;
return;
}*/
}
}
/*if (cn[p] == 100) {
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;
}
}
}
実行結果

(
10 15 6 3
5 4 9 16
11 14 7 2
8 1 12 13
11 16 1 6
14 3 10 7
4 13 8 9
5 2 15 12
12 14 1 7
13 3 16 2
4 6 9 15
5 11 8 10
13 12 1 8
7 2 11 14
4 5 16 9
10 15 6 3
14 15 1 4
2 3 13 16
11 10 8 5
7 6 12 9
15 13 4 2
1 3 16 14
8 6 9 11
10 12 5 7
16 13 1 4
2 3 15 14
11 10 6 7
5 8 12 9
4次魔方陣生成時間は3.233秒です。
生成された4次魔方陣個数は7040個です。
マルチスレッド版4次魔方陣生成全過程修了
)
やっとマルチスレッド版魔方陣自動生成が完成しました。
完成を喜びたいところですが、
第11章最後の課題が残されています。
このコードを参考にして第10章第9話のシングルスレッド版魔方陣自動生成を改良して、
今完成させたばかりのマルチスレッド版が生成した
と同じ魔方陣を生成してシングルスレッド版とマルチスレッド版の速度比較をしてください。
同じ魔方陣を生成させるのは、
場所によって比較的速くできたり、遅くなったりするからです。
ですから、厳密な速度比較をするときには同じ魔方陣を生成させなければならないのです。