最終講 卒業研究と卒業試験

第4話 課題3 9次ラテン方陣にブロックの条件を加える

解答例
#pragma once
int a[9][9];
int x[81],y[81];

int s;
namespace 順列方陣 {

  using namespace System;  
        ・

        ・
        ・
#pragma endregion
  private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
           DateTime hj=DateTime::Now;
           s=0;
           h();
           f(0);
           array<String^>^ w=gcnew array<String^>(14);
           w[8]=L"順";w[9]=L"列";w[10]=L"総";w[11]=L"数";w[12]=L":";w[13]=s.ToString();
           dataGridView1->Rows->Add(w);
           DateTime ow=DateTime::Now;
           TimeSpan sa=ow-hj;
           w[8]=L"時";w[9]=L"間";w[10]=L"計";w[11]=L"則";w[12]=L":";w[13]=(sa.TotalSeconds).ToString();
           dataGridView1->Rows->Add(w);
        }
        void h(){
           char i;
           for(i=0;i<81;i++){
             x[i]=i%9;
             y[i]=i/9;
           }
        }
        void f(char g){
           if(s==100)return;  'すべて計算させるとかなり時間がかかるので100個で止めている。
           int i,j,k,h,xs,ys;
           for(i=0;i<9;i++){
             a[y[g]][x[g]]=i+1;
             h=1;
              if(y[g]>0){
               for(j=0;j<y[g];j++){
                 if(a[y[g]][x[g]]==a[j][x[g]]){
                   h=0;
                   break;
                 }
               }
             }

             
if(h==1){
               if(x[g]>0){
                 for(j=0;j<x[g];j++){
                   if(a[y[g]][x[g]]==a[y[g]][j]){
                     h=0;
                     break;

                  
}
                 }
               }
              }

             if(h==1){
               xs=x[g]/3;
               ys=y[g]/3;
               for(j=0;j<=y[g]-3*ys;j++){
                 for(k=0;k<3;k++){
                   if(j==y[g])if(k==x[g])break;
                   if((y[g]!=3*ys+j) && (x[g]!=3*xs+k)){
                     if(a[y[g]][x[g]]==a[3*ys+j][3*xs+k]){
                       h=0;
                       break;
                     }
                   }
                 }
                 if(h==0)break;
               }
             }


              if(h==1){
                if(g+1<81){
                  f(g+1);
                }
               else{
                 for(j=0;j<9;j++){
                   dataGridView1->Rows->Add();
                   for(k=0;k<9;k++){
                     dataGridView1[k,j+10*s]->Value=a[j][k];
                   }
                 }
                 dataGridView1->Rows->Add();

                 s++;
               }
             }
            }
        }

  };
}
実行例
初心者
解説
             if(h==1){
               xs=x[g]/3;
               ys=y[g]/3;
               for(j=0;j<=y[g]-3*ys;j++){
                 for(k=0;k<3;k++){
                   if(j==y[g])if(k==x[g])break;
                   if((y[g]!=3*ys+j) && (x[g]!=3*xs+k)){
                     if(a[y[g]][x[g]]==a[3*ys+j][3*xs+k]){
                       h=0;
                       break;
                     }
                   }
                 }
                 if(h==0)break;
               }
             }

が加えた部分です。
               xs=x[g]/3;
               ys=y[g]/3;

では何をしているんでしょうか。実はブロック番号を計算しています。

1 2 3
0 0 1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16 17
18 19 20 21 22 23 24 25 26
1 27 28 29 30 31 32 33 34 35
36 37 38 39 40 41 42 43 44
45 46 47 48 49 50 51 52 53
2 54 55 56 57 58 59 60 61 62
63 64 65 66 67 68 69 70 71
72 73 74 75 76 77 78 79 80

例えば、セル番号49は、ブロック番号(02)に対応します。
セル番号の49とき、
               for(j=0;j<=y[g]-3*ys;j++){
                 for(k=0;k<3;k++){
                   if(j==y[g])if(k==x[g])break;
                   if((y[g]!=3*ys+j) && (x[g]!=3*xs+k)){
                     if(a[y[g]][x[g]]==a[3*ys+j][3*xs+k]){
                       h=0;
                       break;
                     }
                   }
                 }
                 if(h==0)break;
               }
では、セル番号49とセル番号30,32,39,41の内容が比較されます。
セル番号31,40,48
           for(i=0;i<9;i++){
             a[y[g]][x[g]]=i+1;
             h=1;
              if(y[g]>0){
               for(j=0;j<y[g];j++){
                 if(a[y[g]][x[g]]==a[j][x[g]]){
                   h=0;
                   break;
                 }
               }
             }

             
if(h==1){
               if(x[g]>0){
                 for(j=0;j<x[g];j++){
                   if(a[y[g]][x[g]]==a[y[g]][j]){
                     h=0;
                     break;

                  
}
                 }
               }
              }
において重複チェックが済んでいまし、セル番号0から順に入れてきてセル番号49までしか数字が入っていませんから、
セル番号
50にはまだ数字が入っていないので比較の必要がないわけです。

30 31 32
39 40 41
48 49 50

if(j==y[g])if(k==x[g])break;セル番号50を検査対象から外すためにあります。
セル番号49に達したら検査を終了するようになっています。
(y[g]!=3*ys+j) && (x[g]!=3*xs+k))は、同行と同列を検査対象から外すためにあります。
31,40,48は一度検査されているのでテストの必要はないわけです。
では、for(j=0;j<=y[g]-3*ys;j++)j=0;j<=y[g]-3*ys;j++の意味は何でしょうか。
例えば、セル番号39なら

30 31 32
39 40 41
48 49 50


最後の行は検査する必要はありません。
セル番号39までしか数字が入っていないからです。






では皆さん、
課題4
課題3で完成させたソフトに
入門
ブロックの区切り*入れましょう。

課題5
課題4にさらにランダムを入れて自然な数独にしましょう。
基礎
に挑戦して、卒業研究課題は終了です。
後は、卒業試験を残すのみとなります。











第3話へ 第5話へ


025


vc++講義へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ



数学研究室に戻る