第16講 魔方陣汎用的生成プログラムへの挑戦
第7話 魔方陣汎用的自動生成プログラム解説その3
コード再掲
f(0);
}
public static void f(int g){
if(cn>20)return;
int i,j,k,h;
for(i=1;i<n*n+1;i++){
h=1;
m[y[g]][x[g]]=i;
for(j=0;j<g;j++){
if(m[y[g]][x[g]]==m[y[j]][x[j]]){
h=0;
}
}
for(j=0;j<g;j++){
if(m[y[g]][x[g]]==m[y[j]][x[j]]){
h=0;
}
}
if(h==1){
if(x[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[y[g]][j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(y[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[j][x[g]];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(y[g]==n-1 && x[g]==0){
w=0;
for(j=0;j<n;j++){
w+=m[j][n-1-j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(y[g]==n-1 && x[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[j][j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(g+1<n*n){
f(g+1);
if(cn>20)return;
}
else{
cn++;
for(j=0;j<n;j++){
for(k=0;k<n;k++){
if(m[j][k]<10){
System.out.print(" "+m[j][k]+" ");
}
else{
System.out.print(m[j][k]+" ");
}
}
System.out.println();
}
System.out.println();
if(cn>20)return;
}
}
}
}
}
ではトレースの旅を始めましょう。
f(0);で
0 | 1 | 2 | |
0 | |||
1 | |||
2 |
のピンク世界にとびます。
for(i=1;i<n*n+1;i++){
h=1;
m[y[g]][x[g]]=i;
によって、ピンクのセル0に1から9まで入れていきます。最初の試行で、
0 | 1 | 2 | |
0 | 1 | ||
1 | |||
2 |
となります。
for(j=0;j<g;j++){
if(m[y[g]][x[g]]==m[y[j]][x[j]]){
h=0;
}
}
for(j=0;j<g;j++){
if(m[y[g]][x[g]]==m[y[j]][x[j]]){
h=0;
}
}
if(h==1){
if(x[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[y[g]][j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(y[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[j][x[g]];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(y[g]==n-1 && x[g]==0){
w=0;
for(j=0;j<n;j++){
w+=m[j][n-1-j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(y[g]==n-1 && x[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[j][j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
では何をしているでしょうか。まず、
for(j=0;j<g;j++){
if(m[y[g]][x[g]]==m[y[j]][x[j]]){
h=0;
}
}
は数字の重複チェックです。各セルに同じ数字が入ってはいけないのでこれが入っています。
ただし、現時点ではf(0);ですからg=0ですので、
for(j=0;j<g;j++){
if(m[y[g]][x[g]]==m[y[j]][x[j]]){
h=0;
}
}
は実行されません。
if(h==1){
if(x[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[y[g]][j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(y[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[j][x[g]];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(y[g]==n-1 && x[g]==0){
w=0;
for(j=0;j<n;j++){
w+=m[j][n-1-j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(y[g]==n-1 && x[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[j][j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
では何をしているのでしょうか。
if(h==1){
if(x[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[y[g]][j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
0 | 1 | 2 | |
0 | 2 | 7 | 6 |
1 | 9 | 5 | 1 |
2 | 4 | 3 | 8 |
の対象セルは、上の
2 |
6 |
1 |
8 |
になります。
if(x[g]==n-1)
であるからです。
n-1は現在3次魔方陣を対象にしていますから2ですね。
if(h==1){
if(x[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[y[g]][j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
では行合計(横合計)がn*(n*n+1)/2=3*(3*3+1)/2=15になっているかどうかをチェックしているのです。
次の
if(h==1){
if(y[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[j][x[g]];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
対象セルは
0 | 1 | 2 | |
0 | 2 | 7 | 6 |
1 | 9 | 5 | 1 |
2 | 4 | 3 | 8 |
は上表の
2 | 4 | 3 | 8 |
です。if(y[g]==n-1)であるかです。
ここでも合計が15になるかどうかを調べているます。
if(h==1){
if(y[g]==n-1 && x[g]==0){
w=0;
for(j=0;j<n;j++){
w+=m[j][n-1-j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
の対象セルは
0 | 1 | 2 | |
0 | 2 | 7 | 6 |
1 | 9 | 5 | 1 |
2 | 4 | 3 | 8 |
です。ここでは逆対角線
0 | 1 | 2 | |
0 | 2 | 7 | 6 |
1 | 9 | 5 | 1 |
2 | 4 | 3 | 8 |
の合計が15になるかをチェックしています。
最後の
if(h==1){
if(y[g]==n-1 && x[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[j][j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
はもうお分かりですね。
0 | 1 | 2 | |
0 | 2 | 7 | 6 |
1 | 9 | 5 | 1 |
2 | 4 | 3 | 8 |
対象セルは(2,2)であり、
0 | 1 | 2 | |
0 | 2 | 7 | 6 |
1 | 9 | 5 | 1 |
2 | 4 | 3 | 8 |
対角線のセルの数字が合計され、それが15になっているかチェックしています。
ただし、現時点では
0 | 1 | 2 | |
0 | 1 | ||
1 | |||
2 |
ですから、
if(h==1){
if(x[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[y[g]][j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(y[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[j][x[g]];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(y[g]==n-1 && x[g]==0){
w=0;
for(j=0;j<n;j++){
w+=m[j][n-1-j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
if(h==1){
if(y[g]==n-1 && x[g]==n-1){
w=0;
for(j=0;j<n;j++){
w+=m[j][j];
}
if(w!=n*(n*n+1)/2)h=0;
}
}
はいずれも実行されず、hは1のままで、
if(h==1){
if(g+1<n*n){
f(g+1);
if(cn>20)return;
}
else{
cn++;
for(j=0;j<n;j++){
for(k=0;k<n;k++){
if(m[j][k]<10){
System.out.print(" "+m[j][k]+" ");
}
else{
System.out.print(m[j][k]+" ");
}
}
System.out.println();
}
System.out.println();
if(cn>20)return;
}
}
が実行されるわけです。g=0ですので、if文の肯定側が遂行され、
0 | 1 | 2 | |
0 | 1 | ||
1 | |||
2 |
の世界f(1)へと跳躍するのです。
第6話へ 第8話へ
VB講義へ
VB講義基礎へ
vc++講義へ第1部へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)
初心者のための VC++による C言語 入門 C++ 入門
基礎から応用まで第1部
初心者のための VC++による C言語 入門 C++ 入門
基礎から応用まで第2部
初心者のための
VC++による C言語 入門 C++ 入門 基礎から応用まで第3部