第7講 Subプロシージャ

第3話 Subプロシージャを利用して重複判定を行う

前話問題解答
Public Class Form1

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     '1から100までの整数の和
     f1(0)
   End Sub

   Sub f1(ByVal w As Integer)
     Dim i As Integer
     For i = 1 To 100
       w = w + i
     Next
     TextBox1.Text = w.ToString
     f2(w) 'プロシージャの独立性のため同じwが使われていても影響がない。
   End Sub

   Sub f2(ByVal w As Integer)
     Dim i As Integer, w As Integer
     w = 0
     For i = 2 To 100 Step 2
       w = w + i
     Next
     TextBox2.Text = w.ToString
     w = w + w
     f3(w) 'プロシージャの独立性のため同じwが使われていても影響がない。
   End Sub

   Sub f3(ByVal w As Integer)
     Dim i As Integer, w As Integer
     w = 0
     For i = 1 To 100
       w = w + i * i
     Next
     TextBox1.Text = w.ToString
     w = w + w
     f4(w) 'プロシージャの独立性のため同じwが使われていても影響がない。
   End Sub

   Sub f4(ByVal w As Integer)
     Dim i As Integer, w As Integer
     w = 0
     For i = 2 To 100 Step 2
       w = w + i * i
     Next
     TextBox4.Text = w.ToString
     w = w + w
     TextBox5.Text = w.ToString
   End Sub

End Class

Form1を少し改良して累積値のみを示すように改良しましょう。
この場合f2、f3、f4におけるwは不要になります。

この場合のコードを考えてください。
模範解答例は。30行下。





























累積方式模範解答例
Public Class Form1

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     '1から100までの整数の和
     f1(0)
   End Sub

   Sub f1(ByVal w As Integer)
     Dim i As Integer
     For i = 1 To 100
       w = w + i
     Next
     TextBox1.Text = w.ToString
     f2(w) 'プロシージャの独立性のため同じwが使われていても影響がない。
   End Sub

   Sub f2(ByVal w As Integer)
     Dim i As Integer
     For i = 2 To 100 Step 2
       w = w + i
     Next
     TextBox2.Text = w.ToString
     f3(w) 'プロシージャの独立性のため同じwが使われていても影響がない。
   End Sub

   Sub f3(ByVal w As Integer)
     Dim i As Integer
     For i = 1 To 100
       w = w + i * i
     Next
     TextBox1.Text = w.ToString
     f4(w) 'プロシージャの独立性のため同じwが使われていても影響がない。
   End Sub

   Sub f4(ByVal w As Integer)
     Dim i As Integer
     For i = 2 To 100 Step 2
       w = w + i * i
     Next
     TextBox4.Text = w.ToString
     TextBox5.Text = w.ToString
   End Sub

End Class


では次の課題です。
次ようなForm1を作り、

実行すると3桁以内のランダムな数字の行列

が表示されるようなソフトを作ってください。
コード例は、30行下。
























コード例
Public Class Form1
   Dim a(4, 4) As Integer 'グローバル配列の宣言
   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     f1() 'ランダム行列の作成
   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(100 * Rnd())
       Next
     Next

     For i = 0 To 4
       For j = 0 To 4
         If a(i, j) < 10 Then w = w + "0" + a(i, j).ToString + " "
         If a(i, j) >= 10 Then w = w + a(i, j).ToString + " "
       Next
       w = w & vbNewLine
     Next
     Label1.Text = w
   End Sub

End Class

では次の課題です。
Subプロシージャf2を作り、関数f2において

出来たランダムな行列の中に、同じ数字が入っていないかチェックし、
結果を表示させるプログラムを考えてください。
もちろん、Label2を貼り付けておく必要があります。

コード例は30行下。


































Public Class Form1
   Dim a(4, 4) As Integer 'グローバル配列の宣言
   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     f1() 'ランダム行列の作成
     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(100 * Rnd())
       Next
     Next

     For i = 0 To 4
       For j = 0 To 4
         If a(i, j) < 10 Then w = w + "0" + a(i, j).ToString + " "
         If a(i, j) >= 10 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
     '1次元配列の宣言
     Dim b(1000) As Integer

     '1次元配列の初期化
     For i = 0 To 1000
       b(i) = 0
     Next

     '重複検査
     For i = 0 To 4
       For j = 0 To 4
         If b(a(i, j)) = 0 Then
           b(a(i, j)) = 1
         Else
           Label2.Text = "数字の重複がありました。" '結果報告
           Exit Sub
         End If
       Next
     Next

     '結果報告
     Label2.Text = "数字の重複がありませんでした。"

   End Sub

End Class

コード解説
     For i = 0 To 1000
       b(i) = 0
     Next
によって、

 i 
b(i) 


A


となります。すると、

の場合、
     For i = 0 To 4
       For j = 0 To 4
         If b(a(i, j)) = 0 Then
           b(a(i, j)) = 1
         Else
           Label2.Text = "数字の重複がありました。" '結果報告
           Exit Sub
         End If
       Next
     Next
の一巡目のループで

 i  702 703 704 705 706 707 708
b(i)   0  0  0    0  0  0


B

となります。2つの表A,Bを次のようなイメージでとらえてください。
Aにおいてすべて清掃されます。
各セルから、碁石をすべて取り去っているのがA
b(i)=0は碁石がない状態を表します。
すなわち
     '1次元配列の初期化
     For i = 0 To 1000
       b(i) = 0
     Next
です。
そして、
     For i = 0 To 4
       For j = 0 To 4
         If b(a(i, j)) = 0 Then
           b(a(i, j)) = 1
         Else
           Label2.Text = "数字の重複がありました。" '結果報告
           Exit Sub
         End If
       Next
     Next
によって各セルに碁石をおいていきます。
b(a(i, j))=1が碁石のある状態を表します。セルがすでに碁石が埋まっていておけなければそれは数字の重複を意味しますから
Label2.Text = "数字の重複がありました。" '結果報告 と結果報告がなされ、f2はExit Subによって強制的に終了となります。
もし、めでたくすべての碁石がおければ
     '結果報告
     Label2.Text = "数字の重複がありませんでした。"
となるというわけです。
ポイントはbの()内がa(i, j)になっている点です。a(i, j)には0から999の整数が入っていました。
したがって、の例ではb(a(0, 0))=b(705)です。


さて、以上の考え方で数字の重複判定は可能なわけですが、
次のような直接的な考え方でも判定は可能です。

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



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


(便宜上比べる側を

20


で比べられる側を

30


で表していますが、両方とも実際には同じです。
色を分けたのは、同じ方陣でも比べる側と比べられる側と役割が違うことを表すためです。)

例えば

31


のセルをピンク側のすべてのセルと比較して同じものがないか調べるのです。
この場合、

31


のセルは、2次元上を動きます。
また、比べられる側

12


セルも2次元上を動きます。
2次元かつ2次元ですから、
2×2=4で4次元になってしまいます。
2次元でさえ頭がこんがりそうなのに、4次元では頭が爆発しそうです。

ですが、、プロシージャをうまく使えば4次元は2次元に落とせます。
つまり、
For i = 0 To 4
  For j = 0 To 4
    f3(i , j)
  Next
Next
のようにすればよいです。
もちろん、f3が2次元ループになっているので積算されて4次元になるのです。
高次元を低次元に落とすことが出来ることがプロシージャの意義の1つです。
皆さん、コーティングを考えてみてください。





第2話へ 第4話へ

006

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

数学研究室に戻る