Visual Basic 初級講座 |
Visual Basic 中学校 > 初級講座 >
第7回 繰り返し処理
繰り返し処理は「ループ」とも呼ばれ、似たような処理を何回も実行するときに便利です。たとえば、1000行書かなくてはいけないプログラムもうまくループを使えば 数行で書けたりします。
この回の概要 ・ループを使うとプログラムの部分を繰り返して実行できる。 ・ループするには Do 〜 Loopや For 〜 Next を使う。 ・For 〜 Next を使ってたくさんの円を描く方法 ・Exit For, Exit Doを使うとループを中止できる。 |
さて、円を書くにはGraphicsクラスのDrawEllipseメソッドを使うのでした。たとえば、次のコードは 緑色の円を書きます。
Dim
g As Graphics = Me.CreateGraphics g.DrawEllipse(Pens.Green, 0, 0, 100, 100) |
■リスト1:円を描く
一つのDrawEllipseメソッドでは一つの円しか書けません。それでは1000個の円を書くには1000回もDrawEllipseメソッドを使わなければならないのでしょうか?そんなことはありません。これから1000個の円をたった 数行で描く方法を説明しましょう。
冒頭にも書いたようにループとは「繰り返し(くりかえし)」のことです。
たとえば、次のプログラムはメッセージボックスを何回も繰り返して表示します。
(このプログラムをとめるには開発環境で[デバッグ]メニューの[デバッグの停止]をクリックしてください。)
Do MsgBox("Hello!") Loop |
■リスト2:繰り返す
この例のように Do 〜 Loop の間に書いたコードは繰り返し実行されます。この例ではMsgBoxの1行しかかかれていませんが、ループの中には何行でもコードを書くことができます。
プログラムでループを終了させるには、ループの終了条件を書くか、自分でループを抜けるように命令します。これについては後で説明します。またFor 〜 Next を使うと指定した回数だけ繰り返すようなループを作ることもできます。
For 〜 Nextを使った単純な例は次のようになります。
Dim
K As
Long
For K = 0
To 5
MsgBox("今" & K & "周目") Next |
■リスト3:6回繰り返す
この例では6回繰り返した後自動的にループは終了します。K = 0 To 5 という指示は「 K が 0から始まって5になるまで」という意味です。それで 0, 1, 2, 3, 4, 5の6回繰り返されます。このときKの値はループが1周回るごとに自動的に1ずつ増加していきます。
VBで特に用意されているループ構文には次のものがあります。
キーワード | 特徴 |
Do 〜 Loop | 終了条件または継続条件が指定できる。 |
For 〜 Next | 繰り返し数が指定できる。 |
For Each 〜 Next | コレクション用の特別なループ。 |
While 〜 End While | 継続条件が指定できる。あまり使わない。 |
2. ぴったりの円を描く
それでは、For 〜 Next を利用した具体的な例を見てみましょう。まずはループを使わないで単純に円がぴったりとフォームに描かれるようにします。
円が描かれる場所は外接四角形の座標で指定しますから、円がフォームにぴったり描かれるようにするには円の外接四角形の大きさをフォーム と同じにすれば良いだけです。フォームの描画領域の横の長さは Me.ClientSize.Width でわかります。たての長さは Me.ClientSize.Height でわかります。
そこで、円をフォームにぴったりになる大きさで描くには次のようになります。
Private
Sub Form1_Click(ByVal
sender As Object,
ByVal e As
System.EventArgs) Handles
MyBase.Click
Dim g As Graphics =
Me.CreateGraphics Yoko = Me.ClientSize.Width
- 1 g.DrawEllipse(Pens.Green, 0, 0, Yoko, Tate) End Sub |
■リスト4:ぴったりの円を描く
なお、今回はフォームのClickイベントプロシージャにプログラムしてみました。実行してフォームをクリックすると円が描かれます。
3.円を5個描く
ぴったりとした円が描けたところで、今度は大きさを少しずつ変えて5個の円を描きます。
ループを使わないで書くと次のようになります。(これは悪い例なのでまねしないでください!)
'悪い例 Private Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.ClickDim g As Graphics = Me.CreateGraphicsDim Yoko As Integer Dim Tate As Integer Yoko = Me.ClientSize.Width
- 1 '背景を黒くする。 '5つの円を描く End Sub |
■リスト5:ループを使わないで5つの円を描く
フォームをクリックすると大きさの違う緑の円が5個描かれるでしょう。その場でフォームの大きさを変えてもまたクリックすればちゃんと真ん中に描かれるので気持ちいいです。 分かりやすいようにフォームの背景色が黒になるようにもしてみました。
■画像1
しかし、5つのDrawEllipseメソッドは座標の数字がちょっとづつ違うだけ すよね。この部分のコードには色をつけておきましたのでよく見てみてください。具体的には外接四角形の位置を10ずつずらし、大きさを10ずつ小さくしているだけです。(数字上、大きさは20ずつ小さくなっているように見えるが、位置が10小さくなるのだから、Yoko、Tateの値を20小さくしないと大きさが10小さくならない。)
そこで、次のように繰り返し命令(くりかえしめいれい)で処理できるわけです。
5つの円を書くよい例。
Private
Sub Form1_Click(ByVal
sender As Object,
ByVal e As
System.EventArgs) Handles
MyBase.Click
Dim g As Graphics =
Me.CreateGraphics Yoko = Me.ClientSize.Width
- 1 g.FillRectangle(Brushes.Black, Me.ClientRectangle) For
K = 0 To 40 Step
10 End Sub |
■リスト6:ループを使って5つの円を描く
このコードを実行してもさっきと全く同じ5個の円が描かれます。それではいよいよでてきたFor Nextについて説明しましょう!
For Next は「この間にあるコードを繰り返せ」という命令です。この場合は間にあるのはDrawEllipseなのでこれが繰り返されます。別にどんな文を間に入れてもかまわないし、2つ以上の文を入れてもよいです。ただし、Nextがないとエラーになります。
VBはこの命令でコードが何回繰り返したかを数えています。それがこの例で言うと K です。この例では K としましたが、別にXだろうが、Testだろうがなんても結構です。このようにForループでループ数を制御するのに使う変数のことを「カウンタ変数」と呼びます。
For K = 0 To 40 は 「Kは始め 0 で、これが 40 になるまでくりかえせ」という意味です。通常は1回繰り返すごとに自動的にKの値は1増えます。だから 234回目の繰り返しの時、K=233です(1周目がK=0という点に注意してください)。
ところが、
For K = 0 To 40 Step 10 と打つと少し違います。「1回繰り返すごとに自動的にKの値が1増える」というところだけちがくなって「1回繰り返すごとに自動的にKの値が10増える」ということになります。
だから、5回しか繰り返されません。これで5個の円が描かれる理由が分かりましたか?
さらに、このKを座標の指定に利用すれば座標もちょっとずつ変わっていくという見事さです!
それが、g.DrawEllipse(Pens.Green, 0 + K, 0 + K, Yoko - (K * 2), Tate - (K * 2)) の座標指定にKが使われている理由です。リスト6の色が付いている部分をリスト5の色が付いている部分と比較してみてください。
さて、ここまで説明すれば円を1000個描く方法はすぐ分かるでしょうか?
4.1000個の円を描く
1000個の円を書くにはさっきの5個の円を描くコードの繰り返し部分を1000回繰り返すようにすればよいのです。Kは1回繰り返すと10ずつ増えるのだから、1000回繰り返させるにはKが9990にまでなるようにすればよい わけです。ですから次のようにたった数字一つを直すだけで終わりです。
Private
Sub Form1_Click(ByVal
sender As Object,
ByVal e As
System.EventArgs) Handles
MyBase.Click
Dim g As Graphics =
Me.CreateGraphics Yoko = Me.ClientSize.Width
- 1 g.FillRectangle(Brushes.Black, Me.ClientRectangle) For
K = 0 To 9990 Step
10 End Sub |
■リスト7:たくさんの円を描く
実行させてみるとどうです?なにやら不思議な文様が…?
■画像2:リスト7の実行結果
実はKの値が大きくなっていくとだんだんと座標がマイナスになっていくので、途中から円が反転してしまうのです。それで反転した円と普通の円が無数に交差して不思議な文様になるわけです。(フォームのクライアント領域が丁度正方形の場合はこのような文様は出現しません。)
さて、せっかくですからループと離れて少し遊んでみます。
プログラムの行数を短くして、円の色を少しずつ変えてみましょう。
本来プログラムは短く書くよりわかりやすく書いた方がかっこいいし、後々のため なのですが、そこはまぁこういうこともできるというサンプルだと思ってください。まだ説明していない文法やキーワードも登場しています。
Private
Sub Form1_Click(ByVal
sender As Object,
ByVal e As
System.EventArgs) Handles
MyBase.Click Dim g As Graphics = Me.CreateGraphics g.FillRectangle(Brushes.Black, Me.ClientRectangle) For K As Integer = 0 To 1000 Step 7 g.DrawEllipse(New Pen(Color.FromArgb(K Mod 200, K Mod 160, K Mod 123)), 0 + K, 0 + K, ClientSize.Width - 1 - (K * 2), ClientSize.Height - 1 - (K * 2)) Next K End Sub |
■リスト8:色を変えてたくさんの円を描く
DrawEllipseの行が長くて分かりにくいですね。実行結果は次のようになります。考えてみれば私はプログラムを始めたばかりの頃はこんな感じで模様を書いて遊んでいました。小学校1年生の頃のことです。そのときはループを理解できなかったので円の数だけプログラムを書いてました…。
■画像3:リスト8の実行結果
博士のワンポイントレッスン
|
以上For 〜 Nextを使ってループする方法を説明しましたが、VBにはこの他にもDo 〜 Loop (読み方:Do = ドゥー, Loop = ループ)、While 〜 End While(読み方:While = ホワイル, End = エンド)、For Each 〜 Next (読み方:Each = イーチ)が用意されています。
While 〜 End WhileはDo 〜 Loop の機能縮小版です。まず使わないので説明しません。またWhile End Whileは知らない人が多いので混乱を招きますから使わないようにしてください。
For Each 〜 Next は特殊なループ構文ですので今回は解説しません。
Do 〜 Loop の特徴は終了条件 または継続条件を指定できる点です。For 〜 Next の場合は数値が指定した値になったときにループを終了するという単純な条件しか指定できませんでしたが、Do 〜 Loopを使うとIf文と同じくらい複雑な条件を指定できます。
Do 〜 Loop で終了条件を指定するには Until (読み方:Until = アンティル)を使います。
たとえば、次の例では変数の値が100を越えるとループは終了します。
Dim
X As
Integer X = 1 Do
Until X > 100 |
■リスト9
途中に出てくるDebug.WriteLineは出力ウィンドウにに値を書き出す命令ですから、結果を確認するには 出力ウィンドウを見てみてください。出力ウィンドウを表示するにはVBの[表示]メニューから[その他のウィンドウ] - [出力]をクリックします。
出力ウィンドウではさまざまな出力が表示できますので、この結果を確認するときは、下の画像のように「デバッグ」を選択してください。
■画像4:リスト9の実行結果
結果を確認してみると分かるのですが、実際には最後に 128 と出力されます。 100を越えているのでおかしいようにも思えますが、X > 100 という終了条件の判断はループの一番先頭で行われている点に注意してください。
つまり、足し算→出力→判定 の順序なので 128 は判定されるより前に出力されてしまいます。
この例で128が出力されないようにするには次のようにします。
Dim
X As
Integer X = 1 Do |
■リスト10
この例では 出力→足し算→判定 の順序になるので 100 を超える値は絶対に出力されません。
ただし、前の例では出力されていなかった 1 が最初に出力されるようになります。
このように Do 〜Loop 文の条件は Do または Loop とともに指定することができます。ほとんどの人は Do のところで指定しているみたいですが、 Loopでも条件を指定できるということは時には重要な意味を持ってくる場合もあります。
Do 〜 Loop で継続条件を指定するには While (While = ホワイル)を使います。
たとえば、次の例では変数の値が100以下であればループを継続します。
Dim
X As
Integer X = 1 Do
While X <= 100 |
■リスト11
Do 〜 Loop はデータベースの処理や、ファイルの処理などに良く使われます。「最後まで読め」という命令がしやすいからです。For 〜 Next だと「何回繰り返せ」という形式になるので、はじめから繰り返し回数が分かっている場合にしか使えません。
ただ、データベースのサンプルは複雑し、ファイル処理も.NET Frameworkのクラスを使うと簡単にできるようになっているので今回はこういったサンプルは紹介しません。
ループはただ繰り返しているだけではなく、プログラムからループの中止と続行を指示することができます。続行の指示はVB2005以降でないと使用できません。
ループの中止とは、繰り返しを終了してループを抜けるという意味です。具体的には次の表にある脱出命令を使ってループを終了します。ループを中止した場合は、ループを抜けた次の行からプログラムが実行されます。
ループの種類 | 脱出命令 |
Do 〜 Loop | Exit Do |
For 〜 Next | Exit For |
While 〜 Wend | Exit While |
■表1
たとえば、Exit For (読み方:Exit=エグジット)を使うと、まだループ回数が残っていてもFor 〜 Nextループを中止して、ループを抜けた次の行から実行を再開します。
サンプルも紹介しておきましょう。次のプログラムではテキストボックスの文字数が15文字になった時点でループが終了します。実際に試すときはテキストボックスを画面に配置してから実行してください。
Do If TextBox1.Text.Length > 15 Then Exit Do End If TextBox1.AppendText("<") Loop |
■リスト12
このプログラムは、次のように書くこともできます。
Do
Until TextBox1.Text.Length > 15 TextBox1.AppendText("<") Loop |
■リスト13
この例だとExit Doを使わない方がコードが短くてすっきりしています。場合によって使い分けてください。
VB2005から導入されたループの続行は、現在の周を中止して、次の周からループを再開するという意味です。具体的には次の表にある続行命令を使用します。
ループの種類 | 続行命令 |
Do 〜 Loop | Continue Do |
For 〜 Next | Continue For |
While 〜 Wend | Continue While |
■表2
たとえば、次のプログラムでは K = 5 の時だけその周の処理を飛ばして次の周から処理を続行します。Continue For (読み方:Continue=コンティニュー)を使用しています。
Dim
K As
Integer
For K = 0
To 9
If K
= 5 Then MsgBox(K) Next |
■リスト14
ループの中止も継続もループ内の処理が単純な場合にはありがたみを感じませんが、ループ内のコードの量が多いときには構造がすっきりして重宝します。
7 補足
最後に、説明し切れないループの性質が3つほどありましたので補足しておきます。
カウンタ変数はあらかじめ宣言しなくても、For文の中で宣言することができます。次のようになります。
For
K As Integer = 0
To 5 MsgBox("今" & K & "周目") Next K |
ループの中でループをすることもできます。Forループの中でDoループを使ったりもできます。もちろん同じ種類のループ同士をネストすることもできます。
繰り返し実行するには今回紹介した以外の方法もあります。たとえば、一定時間ごとに繰り返したい場合はDo 〜 Loop や For 〜 Next よりも タイマーコントロールを使った処理の方が適しています。
また、自分で自分を呼び出す再帰処理によってループを作ることも可能で、この再帰処理が非常に有効に働く場面もあります。
それぞれの詳細はまたの機会に説明します。