第10講 関数の学習
第10話 第9話プログラムの改良とトレース

プログラム
void f2(void){
  char i;
  char j;
  char k;
  char l;
  String^ w=L"";
  char h=0;

  for(i=0;i<4;i++){
    for(j=0;j<4;j++){
      for(k=0;k<4;k++){
        for(l=0;l<4;l++){
          if((k!=i) | (l!=j)){
            if(a[i][j]==a[k][l]){
              h=1;
              break;
            }
          }
        }
        if(h==1)break;
      }
      if(h==1)break;
    }
    if(h==1)break;
  }
  if(h==0)label2->Text=L"数字の重複はありませんでした。";
  if(h==1)label2->Text=L"数字の重複がありました。";
}
だと、例えば

比べられるセル 比べるセル
9 6 15 4
12 8 13 1
7 11 2 14
6 9 4 15
と
9 6 15 4
12 8 13 1
7 11 2 14
6 9 4 15

の組み合わせと

比べられるセル 比べるセル
9 6 15 4
12 8 13 1
7 11 2 14
6 9 4 15
と
9 6 15 4
12 8 13 1
7 11 2 14
6 9 4 15

の組み合わせの両方の場合を調べてしまいます。

比べられるセル 比べるセル
9 6 15 4
12 8 13 1
7 11 2 14
6 9 4 15
と
9 6 15 4
12 8 13 1
7 11 2 14
6 9 4 15

で数字の重複がなければ同然

比べられるセル 比べるセル
9 6 15 4
12 8 13 1
7 11 2 14
6 9 4 15
と
9 6 15 4
12 8 13 1
7 11 2 14
6 9 4 15

でも数字の重複はありません。
また、片一方に重複があれば他方にも当然重複があります。

組み合わせとしては、

(
8
,
2
) と (
2
,
8
)

は同じです。
ですから、一方だけを調べればいいわけですが、現在のままだと両方調べてしまいます。

したがって、プログラムは次のように改良すればよいのです。

void f2(void){
  char i;
  char j;
  char k;
  char l;
  String^ w=L"";
  char h=0;

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

関数版
void f2(void){
  char i;
  char j;
  String^ w=L"";
  char h;

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

char f3(char s,char t){
  char i;
  char j;
  char h=0;
  for(i=s;i<4;i++){
    for(j=t;j<4;j++){
      if((i!=s) | (j!=t)){
        if(a[i][j]==a[s][t]){
          h=1;
          break;
        }
      }
    }
    if(h==1)break;
  }
  return(h);
}



では、プログラム
void f2(void){
  char i;
  char j;
  char k;
  char l;
  String^ w=L"";
  char h=0;

  for(i=0;i<4;i++){
    for(j=0;j<4;j++){
      for(k=i;k<4;k++){
        for(l=j;l<4;l++){
          if((k!=i) | (l!=j)){
            if(a[i][j]==a[k][l]){
              h=1;
              break;
            }
          }
        }
        if(h==1)break;
      }
      if(h==1)break;
    }
    if(h==1)break;
  }
  if(h==0)label2->Text=L"数字の重複はありませんでした。";
  if(h==1)label2->Text=L"数字の重複がありました。";
}
の場合で、正しく判定されることをいろいろな例で確認してみましょう。

まず、

j 0 1 2 3
i
0  9 16 15  4
1 12  8 13  1
2  7 11  2 14
3  6  9  4 15
l 0 1 2 3
k
0  9 16 15  4
1 12  8 13  1
2  7 11  2 14
3  6  9  4 15

の場合でトレースしてみましょう。

00000007
はif文によって対象外にされるセル


i j セル内の数字
0 0 9
k l セル内の数字
0 0 9
0 1 16
0 2 15
0 3 4
1 0 12
1 1 8
1 2 13
1 3 1
2 0 7
2 1 11
2 2 2
2 3 14
3 0 6
3 1 9

比べられるセルi=0,j=0 比べるセルk=3,l=1のときにif文の条件a[i][j]==a[k][l]を満たし、if文
if(a[i][j]==a[k][l]){
  h=1;
  break;
}
が実行され、h=1となります。そして、一番内側のfor(l=j;l<4;l++)文が強制終了されます。
さらに、
        if(h==1)break;
      }
      if(h==1)break;
    }
    if(h==1)break;
によって、for(k=i;k<4;k++)文、for(j=0;j<4;j++)、for(i=0;i<4;i++)の順にfor文が強制終了されて、
if(h==1)label2->Text=L"数字の重複がありました。";によって、『数字の重複がありました。』と表示されます。


では皆さん、

j 0 1 2 3
i
0 16 13  1  8
1  9 11 12  3
2  5  6  7 14
3 12  2  4 15
l 0 1 2 3
k
0 16 13  1  8
1  9 11 12  3
2  5  6  7 14
3 12  2  4 15

の場合でトレースしてみてください。


第9話へ 第11話へ

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