繰り返し

まず少し変わった命令を紹介します。

Math.GetRandomNumber(max)

"Get Random Number"とは「でたらめな数を得る」位の意味です。どういうことかというと、この命令は1からmaxで指定された値までの間の数を一つでたらめに選んで返してくれます。例えば Math.GetRandomNumber(100)とすれば1〜100までの間の整数をでたらめに返してくれるのです。そして、でたらめな数はこの命令を実行する度に変化します。ためしに次のサンプルを何回か実行してみると様子がわかるかと思います。

TextWindow.WriteLine(Math.GetRandomNumber())

さて、次のプログラムを実行すると何が起きるでしょうか?

WIDTH=640
HEIGHT=400
RR=50
GraphicsWindow.Width=WIDTH
GraphicsWindow.Height=HEIGHT
x=Math.GetRandomNumber(WIDTH)
y=math.GetRandomNumber(HEIGHT)
r=math.GetRandomNumber(RR)+20
GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
GraphicsWindow.FillEllipse(x,y,r,r)

GraphicsWindow.WidthはGraphicsWindowのプロパティで、グラフィックスウィンドーの幅を指定します。同じく、GraphicsWindow.Heightはグラフィックスウィンドーの高さを指定します。つまりこの二つのプロパティの値を変えることでグラフィックスウィンドーの大きさを変えることができます。

GraphicsWindow.BrushColor(Brush Colorは筆の色くらいの意味)というプロパティはグラフィックスウィンドーに描画するときの色を指定するために使われます。GraphicsWindow.GetRandomColor()は色をでたらめに選ぶための命令です。"Get Random Color"は「でたらめな色を得る」くらいの意味です。
10行目のGraphicsWindow.FillEllipse()という命令は以前に使ったGraphicsWindow.DrawEllipse()と似ていますが、違うのはGraphicsWindow.FillEllipse()は楕円(円)を描いてその中を塗りつぶす命令だということです。

このプログラムを実行すると、実行する度にグラフィックスウィンドーのでたらめな(ランダムな)場所にランダムな大きさの円盤を描きます。試しに何回かプログラムを実行してみましょう。

10個の円を描いてみよう

ではチャレンジです。このプログラムを改造して10個のランダムな円盤を描いてみましょう。

たぶん直ぐに思いつくのはGraphicsWindow.FillEllipse()を10回使うことだと思います。こんな風に。

WIDTH=640
HEIGHT=400
RR=50
GraphicsWindow.Width=WIDTH
GraphicsWindow.Height=HEIGHT
x=Math.GetRandomNumber(WIDTH)
y=math.GetRandomNumber(HEIGHT)
r=math.GetRandomNumber(RR)+20
GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
GraphicsWindow.FillEllipse(x,y,r,r)
GraphicsWindow.FillEllipse(x,y,r,r)
GraphicsWindow.FillEllipse(x,y,r,r)
GraphicsWindow.FillEllipse(x,y,r,r)
GraphicsWindow.FillEllipse(x,y,r,r)
GraphicsWindow.FillEllipse(x,y,r,r)
GraphicsWindow.FillEllipse(x,y,r,r)
GraphicsWindow.FillEllipse(x,y,r,r)
GraphicsWindow.FillEllipse(x,y,r,r)
GraphicsWindow.FillEllipse(x,y,r,r)

あぁ…でもこれは思ったような結果にはなりません。なぜかというと、円のx座標、y座標、半径、色が10回描画する際にすべて同じなので、単に同じ円盤を10回上書きするだけの結果になるのです。では、x,y,rとブラシの色も10回変更してみましょう。

WIDTH=640
HEIGHT=400
RR=50
GraphicsWindow.Width=WIDTH
GraphicsWindow.Height=HEIGHT

x=Math.GetRandomNumber(WIDTH)
y=math.GetRandomNumber(HEIGHT)
r=math.GetRandomNumber(RR)+20
GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
GraphicsWindow.FillEllipse(x,y,r,r)

x=Math.GetRandomNumber(WIDTH)
y=math.GetRandomNumber(HEIGHT)
r=math.GetRandomNumber(RR)+20
GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
GraphicsWindow.FillEllipse(x,y,r,r)

x=Math.GetRandomNumber(WIDTH)
y=math.GetRandomNumber(HEIGHT)
r=math.GetRandomNumber(RR)+20
GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
GraphicsWindow.FillEllipse(x,y,r,r)

x=Math.GetRandomNumber(WIDTH)
y=math.GetRandomNumber(HEIGHT)
r=math.GetRandomNumber(RR)+20
GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
GraphicsWindow.FillEllipse(x,y,r,r)

x=Math.GetRandomNumber(WIDTH)
y=math.GetRandomNumber(HEIGHT)
r=math.GetRandomNumber(RR)+20
GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
GraphicsWindow.FillEllipse(x,y,r,r)

x=Math.GetRandomNumber(WIDTH)
y=math.GetRandomNumber(HEIGHT)
r=math.GetRandomNumber(RR)+20
GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
GraphicsWindow.FillEllipse(x,y,r,r)

x=Math.GetRandomNumber(WIDTH)
y=math.GetRandomNumber(HEIGHT)
r=math.GetRandomNumber(RR)+20
GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
GraphicsWindow.FillEllipse(x,y,r,r)

x=Math.GetRandomNumber(WIDTH)
y=math.GetRandomNumber(HEIGHT)
r=math.GetRandomNumber(RR)+20
GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
GraphicsWindow.FillEllipse(x,y,r,r)

x=Math.GetRandomNumber(WIDTH)
y=math.GetRandomNumber(HEIGHT)
r=math.GetRandomNumber(RR)+20
GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
GraphicsWindow.FillEllipse(x,y,r,r)

x=Math.GetRandomNumber(WIDTH)
y=math.GetRandomNumber(HEIGHT)
r=math.GetRandomNumber(RR)+20
GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
GraphicsWindow.FillEllipse(x,y,r,r)

一応思い描いていたような結果が表示されましたね。でもなんだかバカバカしくないかな? プログラム自体はカットアンドペーストで張り付けるだけでいいとしても、同じことを繰り返す同じような命令を何度も書かないといけません。

じゃぁ、円盤を100個描画しなさい、と言われた時は100回ペーストするのかな?たしかにそれでもプログラムは動くけど、じゃぁ1000個の円盤ではどうするのか…?

繰り返し

Small Basicやそのほかのプログラミング言語にも繰り返し同じことを処理するための構文があります。その一つが for 文です。

WIDTH=640
HEIGHT=400
RR=50
GraphicsWindow.Width=WIDTH
GraphicsWindow.Height=HEIGHT
For i=1 To 100
  x=Math.GetRandomNumber(WIDTH)
  y=math.GetRandomNumber(HEIGHT)
  r=math.GetRandomNumber(RR)+20
  GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
  GraphicsWindow.FillEllipse(x,y,r,r)
EndFor

6行名に注目してください。これは i という変数の値を1から100まで順に一つずつ増やし、その間にFor と EndForで囲まれた命令を繰り返し実行しなさい、という命令です。もっと簡単に言うと、For とEndForの間の命令を100回実行しなさい、という命令です。お?なんだか、前の例題のように100回もカットアドペーストしなくともよさそうですよ。

詳しく見ていきましょう。6行目が初めて実行されるとき、まず変数 i に1が代入されます。次に7行目から11行目(インデントされている部分)が実行され、最初の円盤が描画されます。12行目にいくと、対応するFor文、つまり6行目に処理が戻ります。6行目に処理がもどると、For文は変数 i の値を自動的に1増やされ2になります。そしてもう一度7行目から11行目が実行され、再度12行目のEndForにたどり着きますが、ここでまたもよ6行目のFor文に処理が移動します。6行目のFor文では変数 i の値がまたもや1増やされて今度は3になります。そしてこの一連のながれが変数 i の値が100になるまで繰り返されるのです。

ためしに6行目の100を色々な数に変えて実行してみましょう。

このように使われる変数iのことを「カウンター」と呼んだりします。カウンターとは数を数えるときに指でボタンを押して数える小さな機械のことです。

じゃぁ、問題です。テキストウィンドーに自分の名前を10回表示するプログラムを作ってみてください。簡単だよね。

正解はこんな感じ。

For i=1 To 10
  TextWindow.WriteLine("たけし")
EndFor

ちなみにForとEndForで囲まれた構文のことを「Forループ」と呼んだりします。「ループ」とは「輪(わ)」という意味です。輪のように囲まれた命令をグルグルと繰り返し実行するのだからイメージしやすいのじゃないかなと思います。

Stepを指定する

次に下のサンプルを入力して実行してみよう。

WIDTH=640
HEIGHT=400
GraphicsWindow.Width=WIDTH
GraphicsWindow.Height=HEIGHT
For y=0 To HEIGHT Step 10
  GraphicsWindow.DrawLine(0,y,WIDTH,y)
EndFor

実行するとこんな感じになるかと思います。

プログラムの内容は代替理解できると思うけど、5行目のFor文のお尻に「Step 10」というキーワードがついているのに気付いただろうか。前節で説明したように5行目のFor文は変数yの値を0から変数HEIGH(2行目で400に設定していることに注意)まで変化させるのだけど、Stepキーワードがつくと1づつではなく、Stepで指定した数だけ増えていきます。「Step」は英語で「段階」くらいの意味になります。

とすると5行目のFor文で最初に0に設定された変数yの値はFor/EndForの間を繰り返す間に(0,10,20,30,...400)と10づつ増えていきます。
とすると6行目のGraphicWindow.DrawLine()で直線を引くと、10づつ間隔をあけて平行な線を引くことになるのが理解できると思います。

試しにStepで指定する値を10から例えば3や20に変更するとどうなるか試してみましょう。

二重ループ

では次に、以下のサンプルを試してみよう。

WIDTH=640
HEIGHT=400
BOX_HEIGHT=20
BOX_WIDTH=40
GraphicsWindow.Width=WIDTH
GraphicsWindow.Height=HEIGHT
For y=0 To HEIGHT/2 Step BOX_HEIGHT
  GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
  For x=0 To WIDTH Step BOX_WIDTH
    GraphicsWindow.FillRectangle(x+2,y+2,BOX_WIDTH-5,BOX_HEIGHT-5)
  EndFor
EndFor

実行結果はこんな感じ。

7行目と9行目にそれぞれFor文があって入れ子になっているのに気付くと思います。このように二重に入れ子になったForループを二重Forループと呼んだりします。もちろん、必要があれば3重や4重になってもかまいません。
7行目のForループは8行目から11行目までを繰り返します。また、9行目のForループは10行目の命令を繰り返します。

7行目のForループでは最初変数 y に初期値 0 が入ります。9行目のforループではyの値が0のまま、xが0からWIDTH(640)まで40づつ増加していきます。xが640まで達すると、12行目のEndForで7行目のFor文に戻ります。そしてyの増分20が足され、yが20になります。次に9行目のFor文に再び戻ってきます。9〜11行目のForループではyの値が20のままxが0から640まで40づつ増加していきます。ここで注意してほしいのはyの値が0から20に変わりつつも、xが0から640まで40づつ再び変化するということです。

まとめ

Forループを使うと処理を繰り返し実行することができます。例えばある処理を20回実行したい場合には適当な変数をカウンターにつかい、For c=1 to 20 のように変数を1から希望の回数まで増やしながらループさせ、そのループの中にその処理を入れれば実現できます。

一方、変数を特定の初期値から最終値まで一定の増分ごとに変化させたい場合にもFor ループは有効です。