第33講 数独(ナンバープレイス)問題解決ソフトVer.4の制作
(数独(ナンバープレイス)問題作成ソフトに挑戦する人は☆☆)
第2話 Ver.7コード例
以下に示すコードは、とっても難解なコードです。
前にVer.7まであると予告しましたが、
このコードはVer.7に相当するものです。
ですからバージョンを3飛ばしたことになります。
超難解なコードですので、次話より詳しく解説していきます。
実は、Ver.4の作成に10時間近くかけたのですがうまくいきませんでした。
原因が解明できず、時間だけがすぎ疲労困憊し、肩こりは極限です。
これだけの時間と労力をかけ成果がないのでは余りにもしんどすぎますので、
次善の策を練りました。
それはWindows版マルチスレッド対応の数独問題作成ソフトVer.1のコードを転用することです。
自分で作ったソフトながらコードを解読するとなると、やはり困難が伴います。
作ってから1年半近くも立っていて、細部を覚えていないからです。
それにしても、ほぼこれと同じような内容でVer.4を作ったつもりなのですが、
正常に動作しなかったことは誠に不思議です。
単なるスペリングミスなのか、どこか考え違いをしているのか、・・・
尚、
1 | 4 | |||||||
3 | 9 | 6 | ||||||
5 | ||||||||
6 | 3 | |||||||
1 | 4 | 8 | ||||||
2 | 3 | 6 | ||||||
5 | ||||||||
4 | 8 |
この問題は、Ver.3が約0.94秒だったのに対して、約0.04秒で解いてみます。
約23.5倍の速さになりました。
#pragma once
#include<stdlib.h>
#include<math.h>
#include<ctime>
char a[9][9],b[9][9],lst[9][9][9],rlst[9][9][9],jz[81],iz[81];
char
s,cn,rh[81],gh[81],bh[81],kkr[81],chs,h1[81][9],h2[81][9],h3[81][3][3],chsh[81],hs;
namespace 数独問題解決ソフトVer4 {
・
・
・
#pragma endregion
private:
System::Void button1_Click(System::Object^
sender, System::EventArgs^
e) {
int
i,j;
dataGridView1->Rows->Clear();
array<String^>^
x=gcnew array<String^>(15);
for(i=1;i<14;i++){
if(i%4==1)for(j=0;j<13;j++)x[j]=L"*";
if(i%4!=1)for(j=1;j<13;j++){
if(j%4==1)x[j]=L"*";
if(j%4!=1)x[j-1]=L"";
}
dataGridView1->Rows->Add(x);
}
dataGridView1[1,1]->Value=L"1";
dataGridView1[3,2]->Value=L"3";
dataGridView1[5,2]->Value=L"9";
dataGridView1[7,2]->Value=L"6";
dataGridView1[9,1]->Value=L"4";
dataGridView1[7,5]->Value=L"5";
dataGridView1[3,6]->Value=L"6";
dataGridView1[6,7]->Value=L"1";
dataGridView1[11,6]->Value=L"3";
dataGridView1[7,7]->Value=L"4";
dataGridView1[10,7]->Value=L"8";
dataGridView1[5,9]->Value=L"2";
dataGridView1[10,9]->Value=L"3";
dataGridView1[11,9]->Value=L"6";
dataGridView1[1,10]->Value=L"5";
dataGridView1[1,11]->Value=L"4";
dataGridView1[5,11]->Value=L"8";
}
private:
System::Void button2_Click(System::Object^
sender, System::EventArgs^
e) {
//srand(static_cast<unsigned
int>(time(0)));
srand(16);
int
i,j;
array<String^,2>^
w=gcnew array<String^,2>(15,100);
for(i=0;i<15;i++)dataGridView1->Rows->Add();
for(i=0;i<14;i++){
for(j=0;j<14;j++){
if(static_cast<String^>(dataGridView1[j,i]->Value)!=L"
" &&
static_cast<String^>(dataGridView1[j,i]->Value)!=L" ")w[i,j]=static_cast<String^>(dataGridView1[j,i]->Value);
if(static_cast<String^>(dataGridView1[j,i]->Value)==L"
" ||
static_cast<String^>(dataGridView1[j,i]->Value)==L" " )w[i,j]=L"";
}
}
DateTime^
hj=DateTime::Now; //開始時間
cn=0;
s=0;
syokika();
dainyuu(w);
zentaikouzoukaiseki();
//for(i=0;i<30;i++)dataGridView1->Rows->Add();
nyuuryokujyunkoutiku(0);
//for(i=0;i<15;i++)dataGridView1->Rows->Add();
f(0);
DateTime^
ow=DateTime::Now; //終了時間
TimeSpan
sa=ow->Subtract(*hj); //経過時間の計算
dataGridView1[30,25]->Value=L"解答作成時間";
dataGridView1[30,26]->Value=sa.TotalSeconds.ToString();
if(cn==2)dataGridView1[30,27]->Value=L"解答が複数存在する";
if(cn==2)dataGridView1[30,28]->Value=L"不適切な問題です。";
if(cn==0)dataGridView1[30,27]->Value=L"解答が存在しない";
if(cn==0)dataGridView1[30,28]->Value=L"不適切な問題です。";
}
void syokika(){
cn=0;
chs=0;
hs=0;
register char i,j;
for(i=0;i<9;i++){
for(j=0;j<9;j++){
a[i][j]=0;
b[i][j]=0;
}
}
}
void dainyuu(array<String^,2>^ w){
int
i,j;
char
k1=0,k2;
for(i=0;i<13;i++){
if(i%4==0)k1++;
if(i%4!=0){
k2=0;
for(j=0;j<13;j++){
if(j%4==0)k2++;
if(j%4!=0){
if(w[i,j]!=L"")a[i-k1][j-k2]=char::Parse(w[i,j]);
if(w[i,j]==L""){
a[i-k1][j-k2]=0;
hs++;
}
}
}
}
}
}
void zentaikouzoukaiseki(){
register char i1,i2,i3,i4;
char i1s,i2s;
for(i1=0;i1<9;i1++){
for(i2=0;i2<9;i2++){
if(a[i1][i2]==0){
for(i3=0;i3<9;i3++){
lst[i1][i2][i3]=0;
}
for(i3=0;i3<9;i3++){
if(a[i1][i3]>0)lst[i1][i2][a[i1][i3]-1]=1;
}
for(i3=0;i3<9;i3++){
if(a[i3][i2]>0)lst[i1][i2][a[i3][i2]-1]=1;
}
i1s=i1/3;
i2s=i2/3;
for(i3=0;i3<3;i3++){
for(i4=0;i4<3;i4++){
if(3*i1s+i3!=i1 && 3*i2s+i4!=i2
&& a[3*i1s+i3][3*i2s+i4]>0)lst[i1][i2][a[3*i1s+i3][3*i2s+i4]-1]=1;
}
}
for(i3=0;i3<9;i3++){
if(lst[i1][i2][i3]==0){
rlst[i1][i2][b[i1][i2]]=i3+1;
b[i1][i2]++;
}
}
if(b[i1][i2]==1){
iz[chs]=i1;
jz[chs]=i2;
chs++;
}
}
}
}
}
void nyuuryokujyunkoutiku(char g){
register char i,j;
register char Min,imin,jmin;
chsh[g]=0;
if(g>=chs){
Min=9;
for(i=0;i<9;i++){
for(j=0;j<9;j++){
if(a[i][j]==0){
if(b[i][j]<Min){
Min=b[i][j];
imin=i;
jmin=j;
}
}
if(Min==2)break;
}
if(Min==2)break;
}
iz[g]=imin;
jz[g]=jmin;
chs=chs+1;
chsh[g]=1;
}
}
void f(char g){
if(cn==2)return;
register char k,kk,kkk;
char i,j,mx,k1,k2,i1,j1;
j=jz[g];
i=iz[g];
mx=b[i][j];
if(mx==0)return;
kk=rand()%mx;
for(k=0;k<mx;k++){
kkk=(kk+k)%mx;
a[i][j]=rlst[i][j][kkk];
if(g+1<hs){
bubunkouzoukaiseki(g);
nyuuryokujyunkoutiku(g+1);
f(g+1);
if(chsh[g+1]==1)chs--;
gyakububunkouzoukaiseki(g);
}
else{
k1=0;
for(i1=0;i1<13;i1++){
if(i1%4==0){
k1++;
for(j1=0;j1<13;j1++)dataGridView1[j1,i1+14]->Value=L"*";
}
if(i1%4>0){
k2=0;
for(j1=0;j1<13;j1++){
if(j1%4==0){
dataGridView1[j1,i1+14]->Value=L"*";
k2++;
}
if(j1%4>0){
dataGridView1[j1,i1+14]->Value=a[i1-k1][j1-k2];
}
}
}
}
cn++;
if(cn==2)return;
}
}
a[i][j]=0;
}
void bubunkouzoukaiseki(char g){
register char i,j,k;
char x,y,xs,ys;
x=iz[g];
y=jz[g];
ys=y/3;
xs=x/3;
char w;
for(i=0;i<9;i++){
if(a[i][y]==0){
h1[g][i]=0;
if(lst[i][y][a[x][y]-1]==0){
lst[i][y][a[x][y]-1]=1;
b[i][y]--;
h1[g][i]=1;
if(b[i][y]==1){
iz[chs]=i;
jz[chs]=y;
chs++;
}
if(b[i][y]>0){
for(j=0;j<b[i][y];j++){
if(rlst[i][y][j]==a[x][y]){
w=rlst[i][y][b[i][y]];
rlst[i][y][b[i][y]]=a[x][y];
rlst[i][y][j]=w;
break;
}
}
}
}
}
}
for(i=0;i<9;i++){
if(a[x][i]==0){
h2[g][i]=0;
if(lst[x][i][a[x][y]-1]==0){
lst[x][i][a[x][y]-1]=1;
b[x][i]--;
h2[g][i]=1;
if(b[x][i]==1){
iz[chs]=x;
jz[chs]=i;
chs++;
}
if(b[x][i]>0){
for(j=0;j<b[x][i];j++){
if(rlst[x][i][j]==a[x][y]){
w=rlst[x][i][b[x][i]];
rlst[x][i][b[x][i]]=a[x][y];
rlst[x][i][j]=w;
break;
}
}
}
}
}
}
for(i=0;i<3;i++){
for(j=0;j<3;j++){
if((3*ys+j!=y) && (3*xs+i!=x)
&& (a[3*xs+i][3*ys+j]==0)){
h3[g][i][j]=0;
if(lst[3*xs+i][3*ys+j][a[x][y]-1]==0){
lst[3*xs+i][3*ys+j][a[x][y]-1]=1;
b[3*xs+i][3*ys+j]--;
h3[g][i][j]=1;
if(b[3*xs+i][3*ys+j]==1){
iz[chs]=3*xs+i;
jz[chs]=3*ys+j;
chs++;
}
if(b[3*xs+i][3*ys+j]>0){
for(k=0;k<b[3*xs+i][3*ys+j];k++){
if(rlst[3*xs+i][3*ys+j][k]==a[x][y]){
w=rlst[3*xs+i][3*ys+j][b[3*xs+i][3*ys+j]];
rlst[3*xs+i][3*ys+j][b[3*xs+i][3*ys+j]]=a[x][y];
rlst[3*xs+i][3*ys+j][k]=w;
break;
}
}
}
}
}
}
}
}
void gyakububunkouzoukaiseki(char g){
register char i,j;
char x,y,xs,ys;
x=iz[g];
y=jz[g];
ys=y/3;
xs=x/3;
for(i=0;i<9;i++){
if(a[i][y]==0){
if(h1[g][i]==1){
lst[i][y][a[x][y]-1]=0;
b[i][y]++;
if(b[i][y]==2)chs--;
}
}
}
for(i=0;i<9;i++){
if(a[x][i]==0){
if(h2[g][i]==1){
lst[x][i][a[x][y]-1]=0;
b[x][i]++;
if(b[x][i]==2)chs--;
}
}
}
for(i=0;i<3;i++){
for(j=0;j<3;j++){
if((3*ys+j!=y) && (3*xs+i!=x)
&& (a[3*xs+i][3*ys+j]==0)){
if(h3[g][i][j]==1){
lst[3*xs+i][3*ys+j][a[x][y]-1]=0;
b[3*xs+i][3*ys+j]++;
if(b[3*xs+i][3*ys+j]==2)chs--;
}
}
}
}
}
};
}
ダウンロード用参考ファイルForm1.h
ダウンロード用EXE(実行)ファイル
VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual
Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)