マルチスレッド版数独自動生成ソフトC++コードを題材とする超初心者のためのVisual Studio C++講義
第13章 様々な魔方陣の作成および自動生成
第6話 最初に1行にランダムに入れて2ずらしと3ずらしをして、2つの種の数字もランダムにずらす
1行目に並べる数字を種1においても種2においてもランダムに並べてください。
つまり、改良するのは
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
t1[i][j] = (j + 3 * i) % n;
t2[i][j] = (j + 2 * i) % n;
}
}
の部分です。1行目にランダムな数字を入れて種1は2つずらし種2は3つずらしを行うのです。
毎回結果を変えるために
size_t シード値 = (unsigned)time(NULL);
int main() {//私は社長だ。
srand(シード値);
赤の2行を付け加えてください。

を実現するプログラム例
#include<iostream>//インクルードファイルiostreamの読み込み
#include<conio.h>//while(!_kbhit());を使うためのお呪い
#include<string> //文字列変数を使えるようにするために組み込む
#include <iomanip> //setprecisionを使えるように組み込む
#include <cmath>//powなどを使うときに必要
#include <ctime>//time()(←現時刻発生する関数)を使うために必要
using namespace std;//coutを使うときに必要なお呪い
void 魔方陣作成関数();
const size_t n = 5;
size_t mg = n * (n * n + 1) / 2;
size_t シード値 = (unsigned)time(NULL);
int main() {//私は社長だ。
srand(シード値);
魔方陣作成関数();
cout << endl;
cout << "プロジェクト終了" << endl;
while (!_kbhit());//待機させるための命令
return 0;//int main() を終わるためのお呪い
}
void 魔方陣作成関数() {
size_t t1[n][n], t2[n][n];//魔方陣の種を収納する2次元配列
size_t m[n][n];//5次魔方陣を収納する2次元配列
cout << "種1" << endl;
for (size_t i = 0; i < n; i++) {
if (i == 0)t1[0][i] = rand() % n;
if (i > 0) {
while (1) {
t1[0][i] = rand() % n;
size_t h = 1;
for (size_t j = 0; j < i; j++) {
if (t1[0][i] == t1[0][j]) {
h = 0;
break;
}
}
if (h == 1)break;
}
}
}
for (size_t i = 1; i < n; i++) {
for (size_t j = 0; j < n; j++) {
t1[i][j] = t1[0][(j + 2 * i) % n];
}
}
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
cout << " " << t1[i][j] << " ";
}
cout << endl;
}
cout << endl;
cout << "種2" << endl;
for (size_t i = 0; i < n; i++) {
if (i == 0)t2[0][i] = rand() % n;
if (i > 0) {
while (1) {
t2[0][i] = rand() % n;
size_t h = 1;
for (size_t j = 0; j < i; j++) {
if (t2[0][i] == t2[0][j]) {
h = 0;
break;
}
}
if (h == 1)break;
}
}
}
for (size_t i = 1; i < n; i++) {
for (size_t j = 0; j < n; j++) {
t2[i][j] = t2[0][(j + 3 * i) % n];
}
}
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
cout << " " << t2[i][j] << " ";
}
cout << endl;
}
//5次魔方陣作成
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
m[i][j] = n * t1[i][j] + t2[i][j] + 1;
}
}
//5次魔方陣表示
cout << endl;
cout << "魔方陣表示" << endl;
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
if (m[i][j] < 10) {
cout << " " << m[i][j] << " ";
}
else {
cout << m[i][j] << " ";
}
}
cout << endl;
}
size_t c = 1;
for (size_t i = 0; i < n; i++) {
size_t gk = 0;
for (size_t j = 0; j < n; j++) {
gk += m[(j + i) % n][j];
}
if (gk != mg) {
c = 0;
break;
}
}
if (c == 1) {
for (size_t i = 0; i < n; i++) {
size_t gk = 0;
for (size_t j = 0; j < n; j++) {
gk += m[(j + n - i) % n][n - 1 - j];
}
if (gk != mg) {
c = 0;
break;
}
}
}
if (c == 1) {
for (size_t i = 0; i < n; i++) {
size_t gk = 0;
for (size_t j = 0; j < n; j++) {
gk += m[i][j];
}
if (gk != mg) {
c = 0;
break;
}
}
}
if (c == 1) {
for (size_t i = 0; i < n; i++) {
size_t gk = 0;
for (size_t j = 0; j < n; j++) {
gk += m[j][i];
}
if (gk != mg) {
c = 0;
break;
}
}
}
if (c == 1)cout << "完全魔方陣です。" << endl; else cout << "完全魔方陣ではありません。" << endl;
cout << endl;
size_t a = rand() % n;
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
t1[i][j] = (t1[i][j] + a) % n;
}
}
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
m[i][j] = n * t1[i][j] + t2[i][j] + 1;
}
}
cout << "数字をずらした種1と方陣表示" << endl;
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
cout << " " << t1[i][j] << " ";
}
cout << endl;
}
cout << endl;
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
if (m[i][j] < 10) {
cout << " " << m[i][j] << " ";
}
else {
cout << m[i][j] << " ";
}
}
cout << endl;
}
c = 1;
for (size_t i = 0; i < n; i++) {
size_t gk = 0;
for (size_t j = 0; j < n; j++) {
gk += m[(j + i) % n][j];
}
if (gk != mg) {
c = 0;
break;
}
}
if (c == 1) {
for (size_t i = 0; i < n; i++) {
size_t gk = 0;
for (size_t j = 0; j < n; j++) {
gk += m[(j + n - i) % n][n - 1 - j];
}
if (gk != mg) {
c = 0;
break;
}
}
}
if (c == 1) {
for (size_t i = 0; i < n; i++) {
size_t gk = 0;
for (size_t j = 0; j < n; j++) {
gk += m[i][j];
}
if (gk != mg) {
c = 0;
break;
}
}
}
if (c == 1) {
for (size_t i = 0; i < n; i++) {
size_t gk = 0;
for (size_t j = 0; j < n; j++) {
gk += m[j][i];
}
if (gk != mg) {
c = 0;
break;
}
}
}
if (c == 1)cout << "完全魔方陣です。" << endl; else cout << "完全魔方陣ではありません。" << endl;
cout << endl;
size_t b = rand() % n;
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
t2[i][j] = (t2[i][j] + b) % n;
}
}
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
m[i][j] = n * t1[i][j] + t2[i][j] + 1;
}
}
cout << "数字をずらした種2と方陣表示" << endl;
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
cout << " " << t2[i][j] << " ";
}
cout << endl;
}
cout << endl;
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
if (m[i][j] < 10) {
cout << " " << m[i][j] << " ";
}
else {
cout << m[i][j] << " ";
}
}
cout << endl;
}
c = 1;
for (size_t i = 0; i < n; i++) {
size_t gk = 0;
for (size_t j = 0; j < n; j++) {
gk += m[(j + i) % n][j];
}
if (gk != mg) {
c = 0;
break;
}
}
if (c == 1) {
for (size_t i = 0; i < n; i++) {
size_t gk = 0;
for (size_t j = 0; j < n; j++) {
gk += m[(j + n - i) % n][n - 1 - j];
}
if (gk != mg) {
c = 0;
break;
}
}
}
if (c == 1) {
for (size_t i = 0; i < n; i++) {
size_t gk = 0;
for (size_t j = 0; j < n; j++) {
gk += m[i][j];
}
if (gk != mg) {
c = 0;
break;
}
}
}
if (c == 1) {
for (size_t i = 0; i < n; i++) {
size_t gk = 0;
for (size_t j = 0; j < n; j++) {
gk += m[j][i];
}
if (gk != mg) {
c = 0;
break;
}
}
}
if (c == 1)cout << "完全魔方陣です。" << endl; else cout << "完全魔方陣ではありません。" << endl;
cout << "以上の結果は種1については" << a << "ずらし、種2については" << b << "ずらした場合です。" << endl;
}
前回に素数次魔方陣の最後の課題と言ってしまいましたが、
もう一つだけ加えることをお許しください。
今回のコードを改良して7次の完全魔方陣を作成してください。

第1話の謎にまだ答えていませんが、第7話でお答えします。
第8話では魔方陣の種について解説します。
第13章第5話へ 第13章7話へ
本講義トップへ