第30講 数独(ナンバープレイス)問題解決ソフトVer.1の制作
(数独(ナンバープレイス)問題作成ソフトに挑戦する人は☆☆)


第9話 行の条件(横の条件)を加えるの解説その2
            k1=0;
            for(i=0;i<13;i++){
              if(i%4==0)k1++;
                if(i%4!=0){
                  k2=0;
                 h=1;
                  for(j=0;j<13;j++){
                    if(j%4==0)k2++;
                    if(j%4!=0){
                      if(a[i-k1][j-k2]==0){
                       if(j-k2>0){
                         for(k=0;k<j-k2;k++){
                           if(a[i-k1][k]==j-k2+1){
                             h=0;
                             break;
                           }
                         }
                       }
                       if(h==1){
                         a[i-k1][j-k2]=j-k2+1;
                         dataGridView1[j,15+i]->Value=a[i-k1][j-k2];
                       }
                     }
                   }
                  }          
                }
              }
これがだめな理由は、
初心者
入門
結果を見れば一目瞭然です。
初心者基礎と重複検査をしないのは当然です。
コードが
                       if(j-k2>0){
                         for(k=0;k<j-k2;k++){
                           if(a[i-k1][k]==j-k2+1){
                             h=0;
                             break;
                           }
                         }
                       }
となっていて、自分の前初歩と重複チェックはしていますが、
後ろとはしていないからです。
vc++に数字が入らないのも当然です。jは11列目ですから、
                         for(k=0;k<j-k2;k++){
                           if(a[i-k1][k]==j-k2+1){
                             h=0;
                             break;
                           }
                         }
の一番最初のときにc++と重複しています。

            k1=0;
            for(i=0;i<13;i++){
              if(i%4==0)k1++;
                if(i%4!=0){
                  k2=0;
                 h=1;
                  for(j=0;j<13;j++){
                    if(j%4==0)k2++;
                    if(j%4!=0){
                      if(a[i-k1][j-k2]==0){
                       if(j-k2>0){
                         for(k=0;k<j-k2;k++){
                           if(a[i-k1][k]==j-k2+1){
                             h=0;
                             break;
                           }
                         }
                       }
                       if(h==1){
                         a[i-k1][j-k2]=j-k2+1;
                         dataGridView1[j,15+i]->Value=a[i-k1][j-k2];
                       }
                     }
                   }
                  }          
                }
              }
が問題なのは、a[i-k1][j-k2]=j-k2+1となっていて、重複検査にひっかからないときのみ入れているのです。
[j-k2]に対してすべての数字1,2,3,4,5,6,8,9を試して検査に抵触しないときのみ入れるべきなのに、1つしか調べていないのです。
具体的はvisual c++では、a[i-k1][8]=9しか試していないのです。
すべての場合を試すようにするためには、もう一つ変数を用意しなければなりません。
それで、正解は
            k1=0;
            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(a[i-k1][j-k2]==0){
                       for(k=1;k<10;k++){
                         h=1;
                         if(j-k2>0){
                           for(l=0;l<j-k2;l++){
                             if(a[i-k1][l]==k){
                               h=0;
                               break;
                             }
                           }
                         }
                         if(h==1){
                           if(j-k2+1<8){
                             for(l=j-k2+1;l<9;l++){
                               if(a[i-k1][l]==k){
                                 h=0;
                                 break;
                               }
                             }
                           }
                         }
                         if(h==1){
                           a[i-k1][j-k2]=k;
                           dataGridView1[j,15+i]->Value=a[i-k1][j-k2];
                         }
                       }
                     }
                    }
                  }          
                }
というわけです。
前との重複検査を
                         if(j-k2>0){
                           for(l=0;l<j-k2;l++){
                             if(a[i-k1][l]==k){
                               h=0;
                               break;
                             }
                           }
                         }
が担当し、後ろとの検査を
                         if(h==1){
                           if(j-k2<8){
                             for(l=j-k2;l<9;l++){
                               if(a[i-k1][l]==k){
                                 h=0;
                                 break;
                               }
                             }
                           }
                         }
が行っています。
そして、a[i-k1][j-k2]=k;なのですべての場合が試されます。
a[i-k1][
j-k2]=j-k2+1;のときは、紺色の部分が同じで1つの場合しか調べていません。

第8話へ 第10話へ

戻る

VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)