第10講 関数の学習
第7話 重複判定プログラムの解説

解答例

#pragma once
char a[4][4];
     ・
     ・
     ・
#pragma endregion
  private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
           f1();
           f2();
        }

        void f1(void){
          char i;
          char j;
          String^ w=L"";
          for(i=0;i<4;i++){
            for(j=0;j<4;j++){
              a[i][j]=4*i+j+1;
              if(a[i][j]<10)w=w+L"0"+(a[i][j]).ToString()+L" ";
              if(a[i][j]>=10)w=w+(a[i][j]).ToString()+L" ";
            }
            w=w+L"\n";
          }
          label1->Text=w;
        }

        void f2(void){
          char i;
          char j;
          char b[16];
          String^ w=L"";
          char h=0;
          char k;
          for(i=0;i<16;i++)b[i]=0;
          for(i=0;i<4;i++){
            for(j=0;j<4;j++){
            k=a[i][j]-1;
            if(b[k]==1){
              h=1;
              break;
            }
            else{
              b[k]=1;
            }
          }
          if(h==1)break;
        }
        if(h==0)label2->Text=L"数字の重複はありませんでした。";
        if(h==1)label2->Text=L"数字の重複がありました。";
      }

  };
}





(コピーペースト用

#pragma once
char a[4][4];
     ・
     ・
     ・
#pragma endregion
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
f1();
f2();
}

void f1(void){
char i;
char j;
String^ w=L"";
for(i=0;i<4;i++){
for(j=0;j<4;j++){
a[i][j]=4*i+j+1;
if(a[i][j]<10)w=w+L"0"+(a[i][j]).ToString()+L" ";
if(a[i][j]>=10)w=w+(a[i][j]).ToString()+L" ";
}
w=w+L"\n";
}
label1->Text=w;
}

void f2(void){
char i;
char j;
char b[16];
String^ w=L"";
char h=0;
char k;
for(i=0;i<16;i++)b[i]=0;
for(i=0;i<4;i++){
for(j=0;j<4;j++){
k=a[i][j]-1;
if(b[k]==1){
h=1;
break;
}
else{
b[k]=1;
}
}
if(h==1)break;
}
if(h==0)label2->Text=L"数字の重複はありませんでした。";
if(h==1)label2->Text=L"数字の重複がありました。";
}

};





解説

はじめ

 1 ×
 2 ×
 3 ×
 4 ×
 5 ×
 6 ×
 7 ×
 8 ×
 9 ×
10 ×
11 ×
12 ×
13 ×
14 ×
15 ×
16 ×

としておいて、1から16のどれかの数字があったら×を○に変更していきます。
例えば

 1  2  3  4
 5  6  7  8
 9 10 11 12
13 14 15 16

の場合は

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16

すべてに丸が1個ずつ付きます。
ところが、

   2  3  4
 5  6  7  8
 9 10 11 12
13 14 15  

の場合は、

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16 ×

となり、1のところに○が2ついてしまいます。
○が2つ以上付いたら数字が重複しています。

プログラムでは、×を0に対応させ、○を1に対応させています。
for(i=0;i<16;i++)b[i]=0;で

 1 ×
 2 ×
 3 ×
 4 ×
 5 ×
 6 ×
 7 ×
 8 ×
 9 ×
10 ×
11 ×
12 ×
13 ×
14 ×
15 ×
16 ×

の状態を実現しています。
ただし、例えば、b[5-1]=0は

 5 ×

に対応します。b[i]の添え字は0から始まるので1個ずれます。

          for(i=0;i<4;i++){
            for(j=0;j<4;j++){
            k=a[i][j]-1;
            if(b[k]==1){
              h=1;
              break;
            }
            else{
              b[k]=1;
            }
          }
          if(h==1)break;
        }
        if(h==0)label2->Text=L"数字の重複はありませんでした。";
        if(h==1)label2->Text=Text=L"数字の重複がありました。";

をトレースしましょう。

i
   2  3  4
 5  6  7  8
 9 10 11 12
13 14 15  

の場合は

i j セル内の数字
10
11
12
13
14
15

です。b[k]のkはk=a[i][j]-1ですから、セルの数から1引いた数です。
したがって、
b[1-1]=0→b[1-1]=1
b[2-1]=0→b[2-1]=1
b[3-1]=0→b[3-1]=1
b[4-1]=0→b[4-1]=1
b[5-1]=0→b[5-1]=1
b[6-1]=0→b[6-1]=1
b[7-1]=0→b[7-1]=1
b[8-1]=0→b[8-1]=1
b[9-1]=0→b[9-1]=1
b[10-1]=0→b[10-1]=1
b[11-1]=0→b[11-1]=1
b[12-1]=0→b[12-1]=1
b[13-1]=0→b[13-1]=1
b[14-1]=0→b[14-1]=1
b[15-1]=0→b[15-1]=1
までは
if(b[k]==1){
  h=1;
  break;
}
else{
  b[k]=1;
}
のelse文の方が実行されてきましたが、
1行目b[1-1]=0→b[1-1]=1によって、b[0]=1となっていますので、b[1-1]のとき、はじめてif文の方が実行されて、
h=1;
break;
となります。break;によって中のfor文(for(j=0;j<4;j++))が強制終了されます。
さらにこのとき、if(h==1)break;によって外のfor文(for(i=0;i<4;i++))が強制終了されます。
最後にif(h==1)label2->Text=Text=L"数字の重複がありました。";によってlabel2に『数字の重複がありました』
と表示されることになります。

実際に関数f1に
        void f1(void){
          char i;
          char j;
          String^ w=L"";
          for(i=0;i<4;i++){
            for(j=0;j<4;j++){
              a[i][j]=4*i+j+1;
              if(a[i][j]==16)a[i][j]=1;
              if(a[i][j]<10)w=w+L"0"+(a[i][j]).ToString()+L" ";
              if(a[i][j]>=10)w=w+(a[i][j]).ToString()+L" ";
            }
            w=w+L"\n";
          }
          label1->Text=w;
        }
if(a[i][j]==16)a[i][j]=1;の1行付け加え、ビルドして実行をクリックすると、
となります。そのほか、いろいろ実験してみてください。

元に戻って

 1  2  3  4
 5  6  7  8
 9 10 11 12
13 14 15 16

のような場合は、

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16

すなわち

b[1-1]=0→b[1-1]=1
b[2-1]=0→b[2-1]=1
b[3-1]=0→b[3-1]=1
b[4-1]=0→b[4-1]=1
b[5-1]=0→b[5-1]=1
b[6-1]=0→b[6-1]=1
b[7-1]=0→b[7-1]=1
b[8-1]=0→b[8-1]=1
b[9-1]=0→b[9-1]=1
b[10-1]=0→b[10-1]=1
b[11-1]=0→b[11-1]=1
b[12-1]=0→b[12-1]=1
b[13-1]=0→b[13-1]=1
b[14-1]=0→b[14-1]=1
b[15-1]=0→b[15-1]=1
b[16-1]=0→b[16-1]=1
からh=1は1度も実行されませんので、char h=0;でしたからhは0で、
if(h==0)label2->Text=L"数字の重複はありませんでした。";
によって、label2は『数字の重複はありませんでした。』と表示されます。


第6話へ 第8話へ



初心者のためのJava 入門 基礎から応用まで
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第1部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第2部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第3部
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすい vb 入門 vba 入門 基礎から応用まで 第1部
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座へ