第7講 Subプロシージャ

第4話 Subプロシージャを利用した4次元ループ

全問題解答例
Public Class Form1
   Dim a(4, 4) As Integer, h As Integer  'hはf2()においてループを継続するかどうかの判定に使う。h=1なら継続でh=0なら中断という設定にしてある。
   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     f1() 'ランダム行列の作成
     h = 1
     f2() '行列内の数字の重複の検査
   End Sub

   Sub f1()
     '変数の宣言
     Dim i As Integer, j As Integer
     Dim w As String

     'ランダム行列の発生
     For i = 0 To 4
       For j = 0 To 4
         a(i, j) = Int(1000 * Rnd())
       Next
     Next

     'ランダム行列の表示
     For i = 0 To 4
       For j = 0 To 4
         If a(i, j) < 10 Then w = w + "00" + a(i, j).ToString + " "
         If a(i, j) >= 10 And a(i, j) < 100 Then w = w + "0" + a(i, j).ToString + " "
         If a(i, j) >= 100 Then w = w + a(i, j).ToString + " "
       Next
       w = w + vbNewLine
     Next
     Label1.Text = w
   End Sub

   Sub f2()
     '変数の宣言
     Dim i As Integer, j As Integer

     '重複検査 比べる側
     For i = 0 To 4
       For j = 0 To 4
         f3(i, j)
         If h = 0 Then Exit Sub
       Next
     Next

     Label2.Text = "数字の重複がありませんでした。"
   End Sub

   Sub f3(ByVal p As Integer, ByVal q As Integer)
     '変数の宣言
     Dim i As Integer, j As Integer

     '重複検査 比べられる側
     For i = 0 To 4
       For j = 0 To 4
         If p <> i Or q <> j Then  'セルが自分自身と比較しないために必要 セルは常に他のセルと比較しなければならない。
           If a(p, q) = a(i, j) Then
             Label2.Text = "数字の重複がありました。"
             h = 0
             Exit Sub
           End If
         End If
       Next
     Next
   End Sub

End Class

実行例


解説
グローバル変数hは、f2()においてループを継続するかしないかの判定に使われています。
今回のプログラミングではh=0なら不継続、h=1なら継続としています。
逆の設定でもかまいません。
プログラマーがこの辺は自由に設定することが出来ます。
尚、次に学習する戻り値を持つFunctionプロシージャにすればグローバル変数にする必要はありません。
不継続条件0または継続条件1をFunctionプロシージャが返してやればよいからです。
その場合、
    '重複検査
    For i = 0 To 4
      For j = 0 To 4
        f3(i, j)
        If h = 0 Then Exit Sub
      Next
    Next

    '重複検査
    For i = 0 To 4
      For j = 0 To 4
        If f3(i, j) = 0 Then Exit Sub
      Next
    Next
となります。

今回の注目点は、f3(i, j)の引数です。呼び出す側ではijになっていますが、
対応する呼び出される側ではpqになっているという点です。

実は、引き渡す側と引き渡される側が別の変数名でもかまわないのです。
ただし、pqで引き渡されたときは、引き渡された側はプロシージャ内でpqに統一しなければなりません。
今回はそれぞれ1回しか使いませんが、数回使うときには常にpqでなければならないわけです。

注意しなければならない点は、比べる側と比べられる側に分けていますが、対象は同じ行列
であることを忘れてはなりません。If p <> i Or q <> j Then の条件がなければ例えば705は705と比較してしまいます。
これだといつでも
          If a(p, q) = a(i, j) Then
            Label2.Text = "数字の重複がありました。"
            h = 0
            Exit Sub
          End If
において重複と判定されてしまいます。705はそれ以外のセルと比較しなければなりませんので、
If p <> i Or q <> j Then の条件が付いているわけです。

さて、難解な4次元ループが比較的わかりやすくなりました。
理由は、比べる側をf2が、比べられる側をf3がそれぞれ担当して分業しているからです。
構造を明確にすることが出来る=これが構造化プログラミングの思想です。

ところで、今回数字が重複している場合
どこが重複しているのか探すのが大変です。そこで改良して、重複している数字がどれかわかるようにしましょう。
解答例は、30行下。




























解答例
Public Class Form1
   Dim a(4, 4) As Integer, h As Integer  'hはf2()においてループを継続するかどうかの判定に使う。h=1なら継続でh=0なら中断という設定にしてある。
   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     f1() 'ランダム行列の作成
     h = 1
     f2() '行列内の数字の重複の検査
   End Sub

   Sub f1()
     '変数の宣言
     Dim i As Integer, j As Integer
     Dim w As String

     'ランダム行列の発生
     For i = 0 To 4
       For j = 0 To 4
         a(i, j) = Int(1000 * Rnd())
       Next
    Next

    'ランダム行列の表示
    For i = 0 To 4
      For j = 0 To 4
        If a(i, j) < 10 Then w = w + "00" + a(i, j).ToString + " "
        If a(i, j) >= 10 And a(i, j) < 100 Then w = w + "0" + a(i, j).ToString + " "
        If a(i, j) >= 100 Then w = w + a(i, j).ToString + " "
      Next
      w = w + vbNewLine
    Next
    Label1.Text = w
   End Sub

   Sub f2()
    '変数の宣言
    Dim i As Integer, j As Integer

    '重複検査
    For i = 0 To 4
      For j = 0 To 4
        f3(i, j)
        If h = 0 Then Exit Sub
      Next
    Next

    Label2.Text = "数字の重複がありませんでした。"
   End Sub

   Sub f3(ByVal p As Integer, ByVal q As Integer)
    '変数の宣言
    Dim i As Integer, j As Integer

    '重複検査
    For i = 0 To 4
      For j = 0 To 4
        If p <> i Or q <> j Then  'セルが自分自身と比較しないために必要 セルは常に他のセルと比較しなければならない。
          If a(p, q) = a(i, j) Then
            Label2.Text = "数字の重複がありました。" & vbNewLine + "その数字は" + a(p, q).ToString + "です。"
            h = 0
            Exit Sub
          End If
        End If
      Next
    Next
   End Sub

End Class

実行例

変更点は、Label2.Text = "数字の重複がありました。" & vbNewLine + "その数字は" + a(p, q).ToString + "です。"の1カ所のみです。


さらに、改良してすべての重複している数字を指摘するにはどうしたらよいでしょうか。
本日の課題としてこの話を閉じます。
尚、重複を増やすにはa(i, j) = Int(1000 * Rnd())の1000の部分を小さくすればよいのです。
1000のままだと重複はあっても1カ所程度です。余り小さくしてしまうと、重複しない場合がほとんどないとなってしまいますので、
適当に調整されてください。






第3話へ 第5話へ

006

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

数学研究室に戻る