マルチスレッド版数独自動生成ソフトC++コードを題材とする超初心者のためのVisual Studio C++講義
第13章 様々な魔方陣の作成および自動生成
第5話 5次魔方陣の数字をランダムにずらすとどうなるか
第5話の課題
①完全魔方陣だけの検証だけにして斜め合計・行合計・列合計は表示させない。
②
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
t1[i][j] = (t1[i][j] + 1) % n;
}
}
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < n; j++) {
t2[i][j] = (t2[i][j] + 2) % n;
}
}
赤の部分を任意の整数に変更してしてください。本来は整数であれば何でもよのですが、5未満の任意の整数a、bに変更してください。
③最後にaとbも表示させてください。

を実現するコード例
#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;
int main() {//私は社長だ。
魔方陣作成関数();
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次元配列
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;
}
}
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;
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;
}
//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 << " " << 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 << "以上の結果は種1については" << a << "ずらし、種2については" << b << "ずらした場合です。" << endl;
}
素数次魔方陣というテーマの最後の課題です。
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行を付け加えてください。
