第28講 細胞構成法による魔方陣の作成△
第12話 細胞合成の解説その1
コード再掲
void sbg(int g){
if(ks==200)return;
int i,j,k,h,w,ii,iii;
ii=rand()%24;
for(i=0;i<24;i++){
iii=(ii+i)%24;
for(j=0;j<2;j++){
for(k=0;k<2;k++){
a3[2*y[g]+j][2*x[g]+k]=sbr[iii][j][k];
}
}
h=1;
if(g==n-1){
w=0;
for(j=0;j<2*n;j++){
w+=a3[j][j];
}
if(w!=5*n)h=0;
}
if(h==1){
if(g==2*n-2){
w=0;
for(j=0;j<2*n;j++){
w+=a3[j][2*n-1-j];
}
if(w!=5*n)h=0;
}
}
if(h==1){
if(y[g]==0 && x[g]==n-2){
for(j=0;j<2;j++){
w=0;
for(k=0;k<2*n;k++){
w+=a3[2*y[g]+j][k];
}
if(w!=5*n){
h=0;
break;
}
}
}
}
if(h==1){
if(x[g]==0 && y[g]==n-2){
for(j=0;j<2;j++){
w=0;
for(k=0;k<2*n;k++){
w+=a3[k][2*x[g]+j];
}
if(w!=5*n){
h=0;
break;
}
}
}
}
if(h==1){
if(g>2*n-2 && x[g]==n-1){
for(j=0;j<2;j++){
w=0;
for(k=0;k<2*n;k++){
w+=a3[2*y[g]+j][k];
}
if(w!=5*n){
h=0;
break;
}
}
}
}
if(h==1){
if(g>2*n-2 && y[g]==n-1){
for(j=0;j<2;j++){
w=0;
for(k=0;k<2*n;k++){
w+=a3[k][2*x[g]+j];
}
if(w!=5*n){
h=0;
break;
}
}
}
}
if(h==1){
if(g==n*n-2){
for(j=0;j<2;j++){
w=0;
for(k=0;k<2*n;k++){
w+=a3[k][2*x[g]+j];
}
if(w!=5*n){
h=0;
break;
}
}
}
}
if(h==1){
if(g==n*n-1){
for(j=0;j<2;j++){
w=0;
for(k=0;k<2*n;k++){
w+=a3[2*y[g]+j][k];
}
if(w!=5*n){
h=0;
break;
}
}
}
}
if(h==1){
if(g+1<n*n){
sbg(g+1);
}
else{
array<String^>^ w=gcnew array<String^>(15);
for(j=0;j<2*n;j++){
for(k=0;k<2*n;k++){
w[k]=(a3[j][k]).ToString();
}
dataGridView1->Rows->Add(w);
}
for(j=0;j<14;j++)w[j]=L"";
dataGridView1->Rows->Add(w);
ks++;
if(ks==200)return;
}
}
}
}
難解なプログラムである細胞の合成を解説しましょう。
基本的な考え方は、24個の細胞を適当に組み合わせて、行・列・対角線の合計が同じになるものを探すです。
ですから、
第17講 関数の再帰的呼び出しによる3次・4次魔方陣ソフトの改良再講義☆
第1話 プログラムの改良(旧講義と共通)
第2話 仮屋崎さんの天才的方法
第3話 仮屋崎さんの天才的方法の解説
や
第20講 一般種法による魔方陣ソフトの高速化再講義☆
第1話
一般種とは?(旧講義と共通)
第2話 仮屋崎さんのエレガントな方法
第3話 仮屋崎さんのエレガントな方法の解説
第4話 仮屋崎さんのエレガントな方法その2
などと基本的な考え方は同じです。
ただし、各セルにはめ込むでいくのは、第17講や第20講とは違い単独の数字でなく細胞です。
細胞は3次元配列になっていて、char sbr[24][2][2];
sbr[i][j][k]の最初のiが細胞の番号になっていて、0から23までとなっています。
一般種法と同じで、まず対角線上に細胞を埋めていきます。
以下、6次の場合で解説していきます。
対角線が埋まった段階で、対角線の合計が同じになっているか調べます。
1 |
2 |
* |
* |
* |
* |
3 |
4 |
* |
* |
* |
* |
* |
* |
1 |
2 |
* |
* |
* |
* |
3 |
4 |
* |
* |
* |
* |
* |
* |
1 |
2 |
* |
* |
* |
* |
3 |
4 |
対角線の合計は細胞の平均の2倍(1+2+3+4)÷4×2=5の3倍になっていればよいです。
3倍というのは、今6次で解説しているからです。対角線の合計は15で条件をクリアです。そこで、
1 |
2 |
* |
* |
1 |
2 |
3 |
4 |
* |
* |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
* |
* |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
1 |
2 |
3 |
4 |
* |
* |
3 |
4 |
今回も、運良く一回でクリアします。
1 |
2 |
1 |
2 |
1 |
2 |
3 |
4 |
3 |
4 |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
* |
* |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
1 |
2 |
3 |
4 |
* |
* |
3 |
4 |
今回は、1行目の合計が一致しません。そこで
1 |
2 |
1 |
2 |
1 |
2 |
3 |
4 |
4 |
3 |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
* |
* |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
1 |
2 |
3 |
4 |
* |
* |
3 |
4 |
そこで、2番目の細胞を組み込みますが、残念ながら合計は一致しません。以下
1 |
2 |
1 |
3 |
1 |
2 |
3 |
4 |
2 |
4 |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
* |
* |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
1 |
2 |
3 |
4 |
* |
* |
3 |
4 |
1 |
2 |
1 |
3 |
1 |
2 |
3 |
4 |
4 |
2 |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
* |
* |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
1 |
2 |
3 |
4 |
* |
* |
3 |
4 |
1 |
2 |
1 |
4 |
1 |
2 |
3 |
4 |
2 |
3 |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
* |
* |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
1 |
2 |
3 |
4 |
* |
* |
3 |
4 |
となっていき最終的には、
1 |
2 |
4 |
3 |
1 |
2 |
3 |
4 |
2 |
1 |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
* |
* |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
1 |
2 |
3 |
4 |
* |
* |
3 |
4 |
となりますが、これも1行目の合計は13で15にはなりません。
1 |
2 |
* |
* |
1 |
2 |
3 |
4 |
* |
* |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
* |
* |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
1 |
2 |
4 |
3 |
* |
* |
3 |
4 |
となりますが、今度は逆対角線の合計も15にならず、
1 |
2 |
* |
* |
1 |
2 |
3 |
4 |
* |
* |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
* |
* |
3 |
4 |
* |
* |
1 |
3 |
* |
* |
1 |
2 |
2 |
4 |
* |
* |
3 |
4 |
となり、今回は逆対角線の合計が15になりクリアです。そして、次に進みますが、
1 |
2 |
1 |
2 |
1 |
2 |
3 |
4 |
3 |
4 |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
* |
* |
3 |
4 |
* |
* |
1 |
3 |
* |
* |
1 |
2 |
2 |
4 |
* |
* |
3 |
4 |
左右が
である限りは、
を何に変えても合計を15にすることは出来ません。左右が0ということは、その合計は6にすぎなく、
残り1個の細胞では差9を埋めることは出来ないからです。
結局、1行目をクリアするのは
1 |
2 |
1 |
4 |
3 |
4 |
3 |
4 |
2 |
3 |
1 |
2 |
* |
* |
1 |
2 |
* |
* |
* |
* |
3 |
4 |
* |
* |
1 |
2 |
* |
* |
1 |
2 |
3 |
4 |
* |
* |
3 |
4 |
となったときです。これは、オレンジの2行目の合計を15にして薄紺の1行目をやっとクリアします。
以下同様すべてがクリアするまで、このプログラムは試行錯誤を繰り返します。
第11話へ 第13話へ
VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual
Basic入門基礎講座