マルチスレッド版数独自動生成ソフトC++コードを題材とする超初心者のためのVisual Studio C++講義
第11章 マルチスレッドプログラミング
第11話 第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[100][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;
hj = clock();
for (size_t i = 0; i < th; i++) {
継続[i] = 1;
cn[i] = 0;
}
2次座標生成();
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();
while (!_kbhit());//待機させるための命令
return(0);
}
void 変身の術関数(void* aa) {//マルチスレッド
size_t p = *(size_t*)aa;
a[p][y[0]][x[0]] = p + 1;
cout << "出席番号" << a[p][y[0]][x[0]] << " ";
継続[p] = 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;
}
}
}
Ⅲ 関数void f(int p,int s)を冒頭にあるとタイプ宣言をしておいて
本体void f(int p,int s)を作り
void f(int p,int s)に部屋番号1以降に生徒の出席番号を順に入れていってください。
魔方陣の条件を外して順列の条件だけを満たすようにしてください。
最初に部屋番号15に到達したスレッドがコンソール画面に順列を書き込み、
全スレッドを強制的に終了させて、ルートスレッドが「全過程終了」と表示させてください。
強制的に全スレッドを終了させるためには
int main()の上に
グローバル変数
size_t 強制終了 = 0;
を定義しておいて、部屋番号15に到達したスレッドが
強制終了 = 1;
と書き換えてことにして関数fのあちらこちらに
if(強制終了 == 1)break;
を入れておくとよいでしょう。

それでも同時にイクスカのスレッドが部屋番号15についてしまうので、コンソール画面はぐちゃぐちゃになります。
に挑戦してください。