マルチスレッド版数独自動生成ソフトC++コードを題材とする超初心者のためのVisual Studio C++講義
第11章 マルチスレッドプログラミング

第12話 第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;//異世界番号をpに変更

    a[p][y[0]][x[0]] = p + 1;//部屋番号0の部屋に入れる生徒の出席番号は p + 1 に固定されている。

    cout << "出席番号" << a[p][y[0]][x[0]] << " ";//部屋番号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;

        }

    }

}



Ⅳ Ⅲで入れた強制終了に関する項目はいったん外してください。

魔方陣の条件を付け加えましょう。

 ⅰ 対角線が埋まったら対角線合計を計算して魔方陣の合計に一致しなければ h = 0; とすることによってそれ以降の処理を止めて

   関数fの最初のfor文が進むようにしましょう。
   
 ⅱ 行が埋まったら行合計を計算して魔方陣の合計に一致しなければ h = 0; とすることによってそれ以降の処理を止めて

   関数fの最初のfor文が進むようにしましょう。

  ⅲ 列が埋まったら列合計を計算して魔方陣の合計に一致しなければ h = 0; とすることによってそれ以降の処理を止めて

   関数fの最初のfor文が進むようにしましょう。

さらに、魔方陣が各スレッド100個できた段階で戻ることにしましょう。

if (cn[p] == 100) {

    a[p][y[s]][x[s]] = 0;

    return;

}
を適宜加えればよいのです。

その他

        a[p][y[s]][x[s]] = 0;

も適切な箇所に入れてください。

戻るときに

if (h == 1) {

    a[p][y[s]][x[s]] = i + 1;

}

で入れた値を0に戻す必要があるからです。



の条件を加えましょう。




第11章第11話へ 第11章13話へ

本講義トップへ