数独自動生成ソフト開発で学ぶ超初心者のためのC++マルチスレッドプログラミング入門
第1講 序章(周辺の説明とプログラミング体験)
第12話 本講座の特徴のその2
初心者が入門サイトや入門書籍で躓いてしまう要因は、
カタカナ専門用語や関数や変数を英単語で表すことだけではありません。
もっと本質的な理由があります。
それは、コンピュータの動きがわからいという点です。
コンピュータの動きを追うことをトレースと言います。
他の入門サイトや入門書籍でもコンピュータの動きを追います。
ですが、それは最初の方だけでプログラムが難しくなってからは、
あまりトレースをしない、と私は考えています。
まだ、講座が本格的には始まっていませんので、
私のサイトがどのようにしてコンピュータの動きを追うのかを
詳しく説明することはできませんが、
雰囲気だけでも感じ取っていただければと思います。
以下中級者ためのVisual Studio Community 2022 C++による数独自動生成ソフトから引用しますが、
コードについて後ほど詳しく説明しますので、
コードは読まずに色のついている部分だけを見てください。
-----------------------------以下引用-----------------------------------------------------
void kyokusyokaiseki(int y, int x) {//局所解析 = 単セルリスト構造解析
for (int i = 0; i < n; i++)lst[y][x][i] = i + 1;//初期化{1,2,3,4,5,6,7,8,9}とする
mx[y][x] = 0;//{1,2,3,4,5,6,7,8,9}を{2,4}等にするために0に初期化 再カウントのため
for (int i = 0; i < n; i++) {//mondai[y][x]と同じ行にあるセルへの影響を調べる
if (i != x) {//自分自身は対象にしない
if (mondai[y][i] > 0) {
for (int j = 0; j < n; j++) {
if (lst[y][x][j] == mondai[y][i])lst[y][x][j] = 0;
//mondai[y][i]と一致する数字を0にすることによって候補から外す
}
}
}
}
for (int i = 0; i < n; i++) {//mondai[y][x]と同じ列にあるセルへの影響を調べる
if (i != y) {
if (mondai[i][x] > 0) {
for (int j = 0; j < n; j++) {
if (lst[y][x][j] == mondai[i][x])lst[y][x][j] = 0;
//mondai[i][x]と一致する数字を0にすることによって候補から外す
}
}
}
}
for (int i = 0; i < n; i++) {//mondai[y][x]と同じブロックにあるセルへの影響を調べる
if (3 * (y / 3) + (i / 3) != y && 3 * (x / 3) + (i % 3) !=
x) {
if (mondai[3 * (y / 3) + (i / 3)][3 * (x / 3) + (i % 3)] > 0)
{
for (int j = 0; j < n; j++) {
if (lst[y][x][j] == mondai[3 * (y / 3) + (i / 3)][3 * (x / 3)
+ (i % 3)])lst[y][x][j] = 0;
//mondai[3 * (y / 3) + (i / 3)][3 * (x / 3) + (i % 3)]と一致する数字を
//0にすることによって候補から外す
}
}
}
}
for (int i = 0; i < n; i++) {
if (lst[y][x][i] > 0) {
lst[y][x][mx[y][x]] = lst[y][x][i];//例えば、{0, 2, 0, 4, 0, 0, 0, 0, 0}を{2, 4}と詰めて0を含めない
mx[y][x]++;
}
}
}
i = 2 のとき (y = 0, x = 2)が前提
if (2 != 2) {//自分自身は対象にしない
が満たされず以降は実行されません。
i = 3 のとき (y = 0, x = 2)が前提
if (3 != 2) {//自分自身は対象にしない
は満たされますが、
if (mondai[0][3] > 0) { //0は座標(0, 1)のセルの内容の0 空欄は0であることに注意
if (0 > 0) { //0は座標(0, 1)の0
0 > 0が成立しないで以降は実行されずに{0,0,3,4,5,6,7,8,9}のまま
i = 4 のとき (y = 0, x = 2)が前提
j = 0のとき (y = 0, x = 2)の数字候補は{0,0,3,4,5,6,7,8,9}
if (lst[0][2][0] == mondai[0][4])lst[0][2][0] = 0;
if (0 == 5)lst[0][2][0] = 0;
//0は{0,0,3,4,5,6,7,8,9}の(0 + 1)番目,5は座標(0, 4)のセルの内容の5
0 == 5成立しないので以降実行されずに{0,0,3,4,5,6,7,8,9}のまま
j = 1のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,5,6,7,8,9}
if (lst[0][2][1] == mondai[0][4])lst[0][2][1] = 0;
if (0 == 5)lst[0][2][1] = 0;
//0は{0,0,3,4,5,6,7,8,9}の(1 + 1)番目,5は座標(0, 4)のセルの内容の5
によって成立しないので以降実行されずに{0,0,3,4,5,6,7,8,9}のまま
j = 2のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,5,6,7,8,9}
if (lst[0][2][2] == mondai[0][4])lst[0][2][2] = 0;
if (3 == 5)lst[0][2][2] = 0;
//3は{0,0,3,4,5,6,7,8,9}の(2 + 1)番目,5は座標(0, 4)のセルの内容の5
3 == 5は正しくないので何もされずに{0,0,3,4,5,6,7,8,9}
j = 3のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,5,6,7,8,9}
if (lst[0][2][3] == mondai[0][4])lst[0][2][3] = 0;
if (4 == 5)lst[0][2][3] = 0;
//4は{0,0,3,4,5,6,7,8,9}の(3 + 1)番目,5は座標(0, 4)のセルの内容の5
4 == 5は正しくないので何もされずに{0,0,3,4,5,6,7,8,9}
j = 4のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,5,6,7,8,9}
if (lst[0][2][4] == mondai[0][4])lst[0][2][4] = 0;
if (5 == 5)lst[0][2][4] = 0;
//5は{0,0,3,4,5,6,7,8,9}の(4 + 1)番目,5は座標(0, 4)のセルの内容の5
成立するのでlst[0][2][4] = 0;実行され{0,0,3,4,0,6,7,8,9}候補数字5が外された!
j = 5のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,0,6,7,8,9}
if (lst[0][2][5] == mondai[0][4])lst[0][2][5] = 0;
if (6 == 2)lst[0][2][5] = 0;
//0は{0,0,3,4,5,6,7,8,9}の(5 + 1)番目,5は座標(0, 4)のセルの内容の5
6 == 2は正しくないので何もされずに{0,0,3,4,0,6,7,8,9}
j = 6のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,0,6,7,8,9}
if (lst[0][2][6] == mondai[0][4])lst[0][2][6] = 0;
if (7 == 5)lst[0][2][6] = 0;
//0は{0,0,3,4,5,6,7,8,9}の(6 + 1)番目,5は座標(0, 4)のセルの内容の5
7 == 5は正しくないので何もされずに{0,0,3,4,0,6,7,8,9}
j = 7のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,0,6,7,8,9}
if (lst[0][2][7] == mondai[0][4])lst[0][2][7] = 0;
if (8 == 5)lst[0][2][7] = 0;
//8は{0,0,3,4,5,6,7,8,9}の(7 + 1)番目,5は座標(0, 4)のセルの内容の5
8 == 5は正しくないので何もされずに{0,0,3,4,0,6,7,8,9}
j = 8のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,0,6,7,8,9}
if (lst[0][2][5] == mondai[0][4])lst[0][2][5] = 0;
if (9 == 5)lst[0][2][8] = 0;
//9は{0,0,3,4,5,6,7,8,9}の(8 + 1)番目,5は座標(0, 4)のセルの内容の5
9 == 5は正しくないので何もされずに{0,0,3,4,0,6,7,8,9}
i = 5 のとき (y = 0, x = 2)が前提
j = 0のとき (y = 0, x = 2)の数字候補は{0,0,3,4,0,6,7,8,9}
if (lst[0][2][0] == mondai[0][5])lst[0][2][0] = 0;
if (0 == 0)lst[0][2][0] = 0;
//0は{0,0,3,4,5,6,7,8,9}の(0 + 1)番目,0は座標(0, 5)のセルの内容の0 //空欄は0でしたね
成立してlst[0][2][0] = 0;が実行されるがもともと0なので何もしないと同じで{0,0,3,4,0,6,7,8,9}
j = 1のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,0,6,7,8,9}
if (lst[0][2][1] == mondai[0][5])lst[0][2][1] = 0;
if (0 == 0)lst[0][2][1] = 0;
//0は{0,0,3,4,5,6,7,8,9}の(1 + 1)番目,0は座標(0, 5)のセルの内容の0
成立してlst[0][2][1] = 0;が実行されるがもともと0なので何もしないと同じで{0,0,3,4,0,6,7,8,9}
j = 2のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,5,6,7,8,9}
if (lst[0][2][2] == mondai[0][5])lst[0][2][2] = 0;
if (3 == 0)lst[0][2][2] = 0;
//3は{0,0,3,4,5,6,7,8,9}の(2 + 1)番目,0は座標(0, 5)のセルの内容の0
3 == 0は正しくないので何もされずに{0,0,3,4,0,6,7,8,9}
j = 3のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,0,6,7,8,9}
if (lst[0][2][3] == mondai[0][5])lst[0][2][3] = 0;
if (4 == 0)lst[0][2][3] = 0;
//0は{0,0,3,4,5,6,7,8,9}の(3 + 1)番目,0は座標(0, 5)のセルの内容の0
4 == 2は正しくないので何もされずに{0,0,3,4,0,6,7,8,9}
j = 4のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,0,6,7,8,9}
if (lst[0][2][4] == mondai[0][2])lst[0][2][4] = 0;
if (0 == 0)lst[0][2][4] = 0;
//0は{0,0,3,4,5,6,7,8,9}の(4 + 1)番目,0は座標(0, 5)のセルの内容の0
成立してlst[0][2][4] = 0;が実行されますがもともと0なので{0,0,3,4,0,6,7,8,9}
j = 5のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,0,6,7,8,9}
if (lst[0][2][5] == mondai[0][5])lst[0][2][5] = 0;
if (6 == 5)lst[0][2][5] = 0;
//6は{0,0,3,4,5,6,7,8,9}の(5 + 1)番目,0は座標(0, 5)のセルの内容の0
//空欄は0です。
6 == 5は正しくないので何もされずに{0,0,3,4,0,6,7,8,9}
j = 6のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,0,6,7,8,9}
if (lst[0][2][6] == mondai[0][5])lst[0][2][6] = 0;
if (7 == 0)lst[0][2][6] = 0;
//7は{0,0,3,4,5,6,7,8,9}の(6 + 1)番目,0は座標(0, 5)のセルの内容の0
//空欄は0です。
7 == 0は正しくないので何もされずに{0,0,3,4,0,6,7,8,9}
j = 7のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,0,6,7,8,9}
if (lst[0][2][7] == mondai[0][5])lst[0][2][7] = 0;
if (8 == 0)lst[0][2][7] = 0;
//8は{0,0,3,4,5,6,7,8,9}の(7 + 1)番目,0は座標(0, 5)のセルの内容の0
//空欄は0です。
8 == 0は正しくないので何もされずに{0,0,3,4,0,6,7,8,9}
j = 8のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,0,6,7,8,9}
if (lst[0][2][5] == mondai[0][5])lst[0][2][5] = 0;
if (9 == 0)lst[0][2][8] = 0;
//9は{0,0,3,4,5,6,7,8,9}の(8 + 1)番目,0は座標(0, 5)ののセルの内容0
//空欄は0です。
9 == 0は正しくないので何もされずに{0,0,3,4,0,6,7,8,9}
-----------------------------以上引用-----------------------------------------------------
数独自動生成ソフトを開発するとなると、
たくさんの変数や添え字が出てきます。
そして、1つ1つが異なる役割を与えられています。
i = 2 のとき (y = 0, x = 2)が前提
if (2 != 2) {//自分自身は対象にしない
が満たされず以降は実行されません。
i = 3 のとき (y = 0, x = 2)が前提
if (3 != 2) {//自分自身は対象にしない
は満たされますが、
if (mondai[0][3] > 0) { //0は座標(0, 1)のセルの内容の0 空欄は0であることに注意
if (0 > 0) { //0は座標(0, 1)の0
0 > 0が成立しないで以降は実行されずに{0,0,3,4,5,6,7,8,9}のまま
i = 4 のとき (y = 0, x = 2)が前提
j = 0のとき (y = 0, x = 2)の数字候補は{0,0,3,4,5,6,7,8,9}
if (lst[0][2][0] == mondai[0][4])lst[0][2][0] = 0;
if (0 == 5)lst[0][2][0] = 0;
//0は{0,0,3,4,5,6,7,8,9}の(0 + 1)番目,5は座標(0, 4)のセルの内容の5
0 == 5成立しないので以降実行されずに{0,0,3,4,5,6,7,8,9}のまま
j = 1のとき ((y = 0, x = 2)の数字候補は{0,0,3,4,5,6,7,8,9}
if (lst[0][2][1] == mondai[0][4])lst[0][2][1] = 0;
if (0 == 5)lst[0][2][1] = 0;
//0は{0,0,3,4,5,6,7,8,9}の(1 + 1)番目,5は座標(0, 4)のセルの内容の5
によって成立しないので以降実行されずに{0,0,3,4,5,6,7,8,9}のまま
のように各変数や添え字の動きを追っていきます。
添え字というのはlst[0][2][1] の[0][2][1]の部分を指します。
初心者は添え字が複数になると理解するのが難しくなっていきます。
ですから、それぞれの添え字が何を指すか色を使って説明しているわけです。
10年ぐらい前には私のプログラミング講義はGoogleランキングで上位を独占していたことは、
すでに述べていますが、
私のサイトに好意的なコメントが寄せられました。
「本文を読まなくても色をみれば内容が理解できる」などです。
i = 4 のとき (y = 0, x = 2)が前提
j = 0のとき (y = 0, x = 2)の数字候補は{0,0,3,4,5,6,7,8,9}
などをみればy座標(縦座標)は赤に統一されており、
x座標(横座標)は青に統一されていることがわかると思います。
トレースの分量はおそらく他のサイトを圧倒していると思います。
すごく肩の凝る作業ですが、
そのおかげでいろいろな方が私のサイトを推薦してくれて、
リンクを貼っていただきました。
今は変わっているかもしれませんが、
重みをつけたリンク数の合計でGoogleのランキングは決められていました。
重みというのは重要なサイトからのリンクは10と数えたり、
重要でないサイトからのリンクは1と数えたりするということです。
さて、序章は以上にしましていよいよ本格的な講義を展開することにしましょう。
第1講第11話へ 第2講第1話へ
トップへ