第31講 数独(ナンバープレイス)問題解決ソフトVer.2の制作
(数独(ナンバープレイス)問題作成ソフトに挑戦する人は☆☆)
第13話 第9話入力順の構築コード解説その2
コード再掲
void nyuryokujyunkoutiku(char g){
char i,j,k,h,jh,ih;
char min=100;
k=0;
for(i=0;i<9;i++){
for(j=0;j<9;j++){
if(a[i][j]==0){
h=1;
if(g>0){
for(k=0;k<g;k++){
if(j==zx[k] && i==zy[k]){ //この辺の記述にも問題がありました。以降赤が訂正箇所。
h=0;
break;
}
}
}
if(h==1){
if(b[i][j]<min){
min=b[i][j];
ih=i;
jh=j;
}
}
}
}
}
zx[g]=jh;
zy[g]=ih;
if(g+1<cn){
nyuryokujyunkoutiku(g+1);
}
//以降は、動作が正常であることが確認され次第削除
else{
for(i=0;i<4;i++)for(j=0;j<13;j++)dataGridView1[j,4*i+28]->Value=L"*";
for(i=0;i<4;i++)for(j=0;j<13;j++)dataGridView1[4*i,j+28]->Value=L"*";
for(i=0;i<cn;i++){
if(a[zy[i]][zx[i]]==0){
if(zx[i]<3)xx=zx[i];
if(zx[i]>2 && zx[i]<6)xx=zx[i]+1;
if(zx[i]>5 && zx[i]<9)xx=zx[i]+2;
if(zy[i]<3)yy=zy[i];
if(zy[i]>2 && zy[i]<6)yy=zy[i]+1;
if(zy[i]>5 && zy[i]<9)yy=zy[i]+2;
dataGridView1[xx+1,yy+29]->Value=i;
}
for(i=0;i<9;i++){
for(j=0;j<9;j++){
if(a[i][j]>0){
if(j<3)xx=j;
if(j>2 && j<6)xx=j+1;
if(j>5 && j<9)xx=j+2;
if(i<3)yy=i;
if(i>2 && i<6)yy=i+1;
if(i>5 && i<9)yy=i+2;
dataGridView1[xx+1,yy+29]->Value=L"/";
}
}
}
}
//ここまでが削除対象
}
}
コード解説
不要な部分を削除して、再度掲示してみましょう。
void nyuryokujyunkoutiku(char g){
char i,j,k,h,jh,ih;
char min=100;
k=0;
for(i=0;i<9;i++){
for(j=0;j<9;j++){
if(a[i][j]==0){
h=1;
if(g>0){
for(k=0;k<g;k++){
if(j==zx[k] && i==zy[k]){ //この辺の記述にも問題がありました。以降赤が訂正箇所。
h=0;
break;
}
}
}
if(h==1){
if(b[i][j]<min){
min=b[i][j];
ih=i;
jh=j;
}
}
}
}
}
zx[g]=jh;
zy[g]=ih;
if(g+1<cn){
nyuryokujyunkoutiku(g+1);
}
}
}
と結構シンプルになりましたが、まだまだ複雑なコードです。
if(a[i][j]==0){
・
}
については、セルが空欄の場合だけに番号を割り振るために必要です。
問題で入力されたセルに番号を割り振ってはいけませんね。
for(k=0;k<g;k++){
if(j==jhs[k] && i==ihs[k]){
h=0;
break;
}
}
の意味は何でしょうか。これは、空欄の中ですでに番号が割り振られている場合はスルーするように入れてあります。
ですから、
if(h==1){
if(b[i][j]<min){
min=b[i][j];
ih=i;
jh=j;
}
}
は、まだ番号が割り振られていないセルの中で最小のものを探しています。
b[i][j]<minはb[i][j]=<minでもうまく動作します。これの違いは、
* | 6 | 5 | 3 | 5 | 4 | * | 5 | 5 |
3 | 5 | * | * | 5 | * | 5 | 4 | 5 |
5 | 7 | 6 | 5 | 6 | 5 | 8 | 6 | 6 |
5 | 7 | 6 | 3 | 6 | * | 5 | 6 | 5 |
4 | 7 | * | 1 | 4 | 4 | 5 | 6 | * |
4 | 5 | 4 | 3 | * | * | 5 | * | 4 |
3 | 4 | 4 | * | 4 | 3 | 5 | * | * |
* | 7 | 5 | 5 | 5 | 4 | 5 | 5 | 6 |
* | 6 | 4 | * | 5 | 4 | 5 | 5 | 5 |
b[i][j]<minの場合は、最初に見つかった方に番号を割り振ります。つまり
3 |
に番号が割り振られます。それに対して、b[i][j]=<minでは最後に見つかった最小値
3 |
に番号が割り振られます。リスト候補数が同じですから、どちらに対して小さい方の番号を割り振ってもいいわけです。
問題によってはb[i][j]<minの方が速く解けるときもあるし、b[i][j]=<minの場合の方が速い場合もあります。
どちらが向いているかは、実際に解いてみるしかありません。
しかし、平均をとれば同じ速度になります。
汎用性を目的とする数独問題解決ソフトですから、どちらを採用しても同じことになります。
最小値が見つかったら
zx[g]=jh;
zy[g]=ih;
によって番号を割り振り、次の番号を割り振る
if(g+1<cn){
nyuryokujyunkoutiku(g+1);
}
の作業へと進みます。
以上で第31講は終わりとします。第32講では、Ver.2を改良してVer.3 の作成を目指します。
第12話へ 第32講第1話へ
VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual
Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)