マルチスレッド版数独自動生成ソフトC++コードを題材とする超初心者のためのVisual Studio C++講義
第8章 ポインタの学習
第8話 明るい紫部分のa[i][j]から1次元ポインタへの変換

//hの任務は明るい紫部分を線対称移動させることである
void h(int a[n][n]) {
//明るい紫の部分の第1行から第4行までの左右交換開始
for (int i = 0; i < n / 2; i++) {
int x = a[i][(3 + i) % (n / 2)];
int y = a[i][n - 1 - ((3 + i) % (n / 2))];
交換係社員(&x, &y);
a[i] [(3 + i) % (n / 2)] = x;
a[i][n - 1 - ((3 + i) % (n / 2))] = y;
}
//明るい紫の部分の第1行から第4行までの左右交換終了
//明るい紫の部分の第5行から第8行までの交換開始
for (int i = 0; i < n / 2; i++) {
int x = a[n - i - 1][(3 + i) % (n / 2)];
int y = a[n - i - 1][n - 1 - ((3 + i) % (n / 2))];
交換係社員(&x, &y);
a[n - i - 1] [(3 + i) % (n / 2)] = x;
a[n - i - 1][n - 1 - ((3 + i) % (n / 2))] = y;
}
//明るい紫の部分の第5行から第8行までの交換終了
}
さて、最後の解説です。
説明する側の私も聞く側の皆さんも要領がわかってきたのではないでしょうか。
a[i][(3 + i) % (n / 2)]
からです。

a[i][(3 + i) % (n / 2)] → *(a + n * i + (3 + i ) % (n / 2))
または
a[i][(3 + i) % (n / 2)] → *(a + n * i +((3 + i ) % (n / 2)))
次は
a[i][n - 1 - ((3 + i) % (n / 2))]
を料理します。

a[i][n - 1 - ((3 + i) % (n / 2))] → *(a + n * i + n - 1 - ((3 + i ) % (n / 2)))
または
a[i][n - 1 - ((3 + i) % (n / 2))] → *(a + n * i + n - 1 - (3 +
i ) % (n / 2))
a[i][n - 1 - ((3 + i) % (n / 2))] の方もa[i][n - 1 - (3 + i) % (n / 2)]でもよいことになります。
3番目に進みましょう
a[n - i - 1][(3 + i) % (n / 2)]

a[n - i - 1][(3 + i) % (n / 2)] → *(a + n * (n - i - 1) + (3 +
i) % (n / 2))
または、
a[n - i - 1][(3 + i) % (n / 2)] → *(a + n * (n - i - 1) + ((3 + i) % (n / 2)))
いよいよ最後です。
a[n - i - 1][n - 1 - ((3 + i) % (n / 2))]

a[n - i - 1][n - 1 - ((3 + i) % (n / 2))] → *(a + n * (n - i -
1) + n - 1 -((3 + i) % (n / 2)))
または
a[n - i - 1][n - 1 - ((3 + i) % (n / 2))] → *(a + n * (n - i -
1) + n - 1 -(3 + i) % (n / 2))
もちろん、
a[n - i - 1][n - 1 - ((3 + i) % (n / 2))] の方もa[n - i - 1][n - 1 - (3 + i) % (n / 2)]でもよいことになります。
さて、長い解説はようやく終わりました。
次の課題です。
第4話コード
#include<iostream>//インクルードファイルiostreamの読み込み
#include<conio.h>//while(!_kbhit());を使うためのお呪い
#include<string> //文字列変数を使えるようにするために組み込む
#include <iomanip> //setprecisionを使えるように組み込む
#include <cmath>//powなどを使うときに必要
#include <ctime>//time()(←現時刻発生する関数)を使うために必要
using namespace std;//coutを使うときに必要なお呪い
const int n = 8;//具体的な数字ではなく、 n を使うと汎用性のあるプログラムになる!
void 社員1();//ポインタを扱う社員の一人
int main() {//私は社長だ。
社員1();
while (!_kbhit());//待機させるための命令
return 0;//int main() を終わるためのお呪い
}
//ポインタを扱う社員の一人
void 社員1() {
int* a = (int*)calloc(n * n, sizeof(int));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
*(a + n * i + j) = n * i + j + 1;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (*(a + n * i + j) < 10)cout << " ";
cout << *(a + n * i + j) << " ";
}
cout << endl;
}
}
で定義されたポインタを送る方法があります。
#include<iostream>//インクルードファイルiostreamの読み込み
#include<conio.h>//while(!_kbhit());を使うためのお呪い
#include<string> //文字列変数を使えるようにするために組み込む
#include <iomanip> //setprecisionを使えるように組み込む
#include <cmath>//powなどを使うときに必要
#include <ctime>//time()(←現時刻発生する関数)を使うために必要
using namespace std;//coutを使うときに必要なお呪い
const int n = 8;//具体的な数字ではなく、 n を使うと汎用性のあるプログラムになる!
void 社員1(int(*a)[n]);//ポインタを扱う社員の一人
int main() {//私は社長だ。
int a[n][n]; // 8 行分のポインタ配列
社員1(a);
while (!_kbhit());//待機させるための命令
return 0;//int main() を終わるためのお呪い
}
//ポインタを扱う社員の一人
void 社員1(int(*a)[n]) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
a[i][j] = n * i + j + 1;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (a[i][j] < 10)cout << " ";
cout << a[i][j] << " ";
}
cout << endl;
}
}
第7章第13話などで配列を送っていて、
それで充分だと思うでしょうが、
他のサイトを読んだり、本を読んだりしたときに背景知知っておく理解が進み自分の幅が広がります。
1次元ポインタで皆さんの頭を悩ませたかと思いますが、
復習だと思ってできるだけ第7章第13和のコードをご覧にならずに、
ご自分で考えてください。
基本私は、自分のコードでも丸写しすることはありません。
最初から組み直して来ました。
なぜ、そんなことするのでしょうか。
理解が深まり、また全く異なる発想が浮かぶことがあるからです。
自分のコードさえコピペしたり丸写しはしないが、私の哲学なのです。
もし、ほとんど何も見ずに8次魔方陣を作成できるようならば、
すでにあなたは初心者ではなく中級のレベルに達していると私が保証します。
ですが、ある程度考えてわかないときは第8章第9話へをクリックしてください。
悔しいと思った方は一度コードを消して最初からやり直せばよいのです。