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


第4話 
問題解決ソフトVer.3の完成前夜
改良は簡単です。
               ・
               ・
               ・
      void f(char g){
        if(s==2)return;

               ・
               ・
               ・
          if(h==1){
             a[y][x]=rlst[y][x][iii];
             if(g+1<81){
               zentaikouzoukaiseki();
               nyuryokujyunkoutiku(g+1);
               f(g+1);
             }
               ・
               ・
               ・
if(g+1<50)zentaikouzoukaiseki();1行を入れるだけで
c++
が約1分以上から0.95秒へと短縮されました。
実験していませんが、おそらく100倍ほど速くなりました。
そこで、Ver.3の完成を宣言したいのですが、
よく考えてみると、
         void f(char g){
           if(s==2)return;
           char x,y;
           x=g%9;
           y=g/9;
           char h,i,j,k,k1,k2,ii,rlst[y][x][iii];
           if(a[y][x]>0){
             if(g+1<81){
               f(g+1);
             }
             else{
               k1=0;
               for(i=0;i<13;i++){
                 if(i%4==0){
                   k1++;
                   for(j=0;j<13;j++)dataGridView1[j,i+14]->Value=L"*";
                 }
                 if(i%4>0){
                   k2=0;
                   for(j=0;j<13;j++){
                     if(j%4==0){
                       dataGridView1[j,i+14]->Value=L"*";
                       k2++;
                     }
                     if(j%4>0){
                       dataGridView1[j,i+14]->Value=a[i-k1][j-k2];
                     }
                   }
                 }
               }
               s++;
               if(s==2)return;
             }
           }
           if(a[y][x]==0){
             
ii=rand()%b[y][x];
             for(i=1;i<10;i++){
               rlst[y][x][iii]=(i+ii)%b[y][x];
               h=1;
               if(x>0){
                 for(j=0;j<x;j++){
                   if(a[y][j]==rlst[y][x][iii]){
                     h=0;
                     break;
                   }
                 }
               }
               if(h==1){
                 if(x+1<8){
                   for(j=x+1;j<9;j++){
                     if(a[y][j]==rlst[y][x][iii]){
                       h=0;
                       break;
                     }
                   }
                 }
               }
               if(h==1){
                 if(y>0){
                   for(j=0;j<y;j++){
                     if(a[j][x]==rlst[y][x][iii]){
                       h=0;
                       break;
                     }
                   }
                 }
               }
               if(h==1){
                 if(y+1<8){
                   for(j=y+1;j<9;j++){
                     if(a[j][x]==rlst[y][x][iii]){
                       h=0;
                       break;
                     }
                   }
                 }
               }
               if(h==1){
                 for(j=0;j<3;j++){
                   if(j!=ya){
                     for(k=0;k<3;k++){
                       if(k!=xa){
                         if(a[3*ys+j][3*xs+k]>0){
                           if(a[3*ys+j][3*xs+k]==rlst[y][x][iii]){
                             h=0;
                             break; 
                           }
                         }
                       }
                     }
                     if(h==0)break;
                   }
                 }
               }
               if(h==1){
                 a[y][x]=rlst[y][x][iii];
                 if(g+1<81){
                   f(g+1);
                 }
                 else{
                   k1=0;
                   for(i=0;i<13;i++){
                     if(i%4==0){
                       k1++;
                       for(j=0;j<13;j++)dataGridView1[j,i+14]->Value=L"*";
                     }
                     if(i%4>0){
                       k2=0;
                       for(j=0;j<13;j++){
                         if(j%4==0){
                           dataGridView1[j,i+14]->Value=L"*";
                           k2++;
                         }
                         if(j%4>0){
                           dataGridView1[j,i+14]->Value=a[i-k1][j-k2];
                         }
                       }
                     }
                   }
                   s++;
                   if(s==2)return;
                 }
                 a[y][x]=0;
               }
             }
           }
         }

               h=1;
               if(x>0){
                 for(j=0;j<x;j++){
                   if(a[y][j]==rlst[y][x][iii]){
                     h=0;
                     break;
                   }
                 }
               }
               if(h==1){
                 if(x+1<8){
                   for(j=x+1;j<9;j++){
                     if(a[y][j]==rlst[y][x][iii]){
                       h=0;
                       break;
                     }
                   }
                 }
               }
               if(h==1){
                 if(y>0){
                   for(j=0;j<y;j++){
                     if(a[j][x]==rlst[y][x][iii]){
                       h=0;
                       break;
                     }
                   }
                 }
               }
               if(h==1){
                 if(y+1<8){
                   for(j=y+1;j<9;j++){
                     if(a[j][x]==rlst[y][x][iii]){
                       h=0;
                       break;
                     }
                   }
                 }
               }
               if(h==1){
                 for(j=0;j<3;j++){
                   if(j!=ya){
                     for(k=0;k<3;k++){
                       if(k!=xa){
                         if(a[3*ys+j][3*xs+k]>0){
                           if(a[3*ys+j][3*xs+k]==rlst[y][x][iii]){
                             h=0;
                             break; 
                           }
                         }
                       }
                     }
                     if(h==0)break;
                   }
                 }
               }

の部分は必要がないのです。理由は、リスト構造を解析しているので、リストから数字を選んでいけば数独のルールに反することはありません。
無駄な部分を削ると
         void f(char g){
           if(s==2)return;
           char x,y;
           x=g%9;
           y=g/9;
           char h,i,j,k,k1,k2,ii,rlst[y][x][iii];
           if(a[y][x]>0){
             if(g+1<81){
               f(g+1);
             }
             else{
               k1=0;
               for(i=0;i<13;i++){
                 if(i%4==0){
                   k1++;
                   for(j=0;j<13;j++)dataGridView1[j,i+14]->Value=L"*";
                 }
                 if(i%4>0){
                   k2=0;
                   for(j=0;j<13;j++){
                     if(j%4==0){
                       dataGridView1[j,i+14]->Value=L"*";
                       k2++;
                     }
                     if(j%4>0){
                       dataGridView1[j,i+14]->Value=a[i-k1][j-k2];
                     }
                   }
                 }
               }
               s++;
               if(s==2)return;
             }
           }
           if(a[y][x]==0){
             
ii=rand()%b[y][x];
             for(i=1;i<10;i++){
               rlst[y][x][iii]=(i+ii)%b[y][x];
               a[y][x]=rlst[y][x][iii];
               if(g+1<81){
                 f(g+1);
               }
               else{
                 k1=0;
                 for(i=0;i<13;i++){
                   if(i%4==0){
                     k1++;
                     for(j=0;j<13;j++)dataGridView1[j,i+14]->Value=L"*";
                   }
                   if(i%4>0){
                     k2=0;
                     for(j=0;j<13;j++){
                       if(j%4==0){
                         dataGridView1[j,i+14]->Value=L"*";
                         k2++;
                       }
                       if(j%4>0){
                         dataGridView1[j,i+14]->Value=a[i-k1][j-k2];
                       }
                     }
                   }
                 }
                 s++;
                 if(s==2)return;
               }
               a[y][x]=0;
             }
           }
         }

とシンプルになります。これでVer.3がほぼ完成です。
毎回全体解析を行わせていますが、本当は解析は

c++ピンクの枠の中のみ行えばよいのに、全セルを対象に解析を行っています。
これは結構CPUに負担をかけています。
そこで、途中までは全体解析をして途中からはやめる方式にします。すると、多々今削った
               h=1;
               if(x>0){
                 for(j=0;j<x;j++){
                   if(a[y][j]==rlst[y][x][iii]){
                     h=0;
                     break;
                   }
                 }
               }
               if(h==1){
                 if(x+1<8){
                   for(j=x+1;j<9;j++){
                     if(a[y][j]==rlst[y][x][iii]){
                       h=0;
                       break;
                     }
                   }
                 }
               }
               if(h==1){
                 if(y>0){
                   for(j=0;j<y;j++){
                     if(a[j][x]==rlst[y][x][iii]){
                       h=0;
                       break;
                     }
                   }
                 }
               }
               if(h==1){
                 if(y+1<8){
                   for(j=y+1;j<9;j++){
                     if(a[j][x]==rlst[y][x][iii]){
                       h=0;
                       break;
                     }
                   }
                 }
               }
               if(h==1){
                 for(j=0;j<3;j++){
                   if(j!=ya){
                     for(k=0;k<3;k++){
                       if(k!=xa){
                         if(a[3*ys+j][3*xs+k]>0){
                           if(a[3*ys+j][3*xs+k]==rlst[y][x][iii]){
                             h=0;
                             break; 
                           }
                         }
                       }
                     }
                     if(h==0)break;
                   }
                 }
               }

の部分をまた復活させなければなりません。ただし、全体構造解析やっている間は入りませんので、ifを活用して改良します。
尚、gがどのぐらいまで全体解析をやらせたら効率的かは実験によって決定するしかありません。
問題によって違ってくるので複数の問題を解かせ、平均の値で妥協するしかないでしょう。

さて、この改良を行いVer.3は完成とします。
次講では、いよいよ問題部分構造解析に挑戦します。

第3話へ 第5話へ


戻る

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