繰り返し

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

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 ループは有効です。

条件によって処理を変える

プログラムは特に指示がない限り最初から最後に向かって順に処理をしていきます。でもそれではとても単純な仕事しかコンピューターにさせることができません。なので、プログラミング言語は処理の流れを変える仕組みを持っています。

if 文

今回は条件によって処理の流れを変える仕組みを説明しようと思います。では、簡単な例題プログラムを入力してみましょう。

now=Clock.Hour
if now >= 18 Then
  TextWindow.WriteLine("こんばんは")
EndIf

1行目のClock.Hourはこのプログラムを実行した時刻(時)を24時間制で表わしていています。変数 now に代入しているので、nowに現在時刻の何時何分の「何時」かの値が入っていることになります。

2行目の「if」というキーワードに注目しましょう。これは英語で「もしも〜」というような意味があって、仮定を表現する際に使われます。その後の「then」というキーワードは「〜であれば」くらいの意味があります。4行目の「EndIf (End If)」は英語ではちょっとこういう言い方はまずしませんが、敢えて日本語に直せば「仮定の話はここで終わり」くらいの意味です。
つまり、2行目から4行目までを敢えて日本語で表現してみると、こんな感じになります。

もし now >= 18 正しいようであれば、
  TextWindow.WriteLine("こんばんは") を実行しなさい。
仮定は終わり

つまり、例題の2行目の「if」と「then」の間の条件が正しい場合にだけ「if」文の直後から「endif」までの命令が実行され、条件が正しくない場合には直ちにendifの次の行に処理が移ります。今回の例題の場合、4行目のendifの後には命令がないので、そのままプログラムは終了します。ちなみに「>=」は、数学でいうところの「≧」と同じ意味です。つまり、プログラムを実行した時刻が18時(午後6時)以後であれば「こんばんは」と表示されますが、そうでない場合はなにも表示されません。if文とendif文の間には複数の命令を書くことができます。条件が正しければif文とendif文の間の全ての命令が実行されます。

else 文

でも、18時より以前になにも表示されないのは寂しいのでプログラムを下のように変更してみましょう。

now=Clock.Hour
If now > 18 Then
  TextWindow.WriteLine("こんばんは")
Else
  TextWindow.WriteLine("こんにちは")
EndIf

else」は英語で「〜そうでなければ」くらいの意味があります。つまり現在時刻が18時以降であれば「こんばんは」と表示されますが、そうでなければ「こんにちは」と表示されます。

複雑な if 文

でも、朝は「おはよう」と表示したいし、深夜には「こんばんは」と表示したいよね。なので、とりあえずまとめると次の表のようになるようにします。

4時〜11時 現在時刻 >= 4 かつ 現在時刻 < 11 おはよう
11時〜18時 現在時刻 >= 12 かつ 現在時刻 < 18 こんにちは
18時〜4時 現在時刻 >= 18 または 現在時刻 < 4 こんばんは

では、このように表示するようにプログラムを改造してみましょう。

now=Clock.Hour
If now >= 18 or now < 4 Then
  TextWindow.WriteLine("こんばんは")
ElseIf now >= 4 and now < 11 then
  TextWindow.WriteLine("おはよう")
Else
  TextWindow.WriteLine("こんにちは")
EndIf

4行目の「ElseIf(else if)」はelseとifを組み合わせた命令で、「〜そうでなく、しかも仮に〜であれば」くらいの意味になります。つまり、この例で説明すると、「2行目の条件が成り立たない場合であり、かつ4行目の条件が成り立つ場合」には、6行目のelse文までの命令が実行されます。elseif文は幾つも連ねることができます。

if 〜 then
   aaa
elseif 〜 then
   bbb
elseif 〜 then
   ccc
elseif 〜 then
   ddd
...
else
   zzz
endif

条件を先頭から確認していって、条件に合った場合にのみ特定の動きをプログラムにさせたいときにこのような構文が便利です。

ところで、2行目の条件がちょっと複雑です。

If now >= 18 or now < 4 Then

赤く色を付けた二つの箇所が二つの条件を表現しています。青色の「or」は「または〜」くらいの意味があります。つまり、2行目の例だと、「now が 18以上、または now が4未満の場合には...」という風な意味になります。

同じく4行目の「and」は「〜であり、かつ〜」という位の意味です。なので、4行目の例だと「now が4以上であり、かつ now が11未満の場合には...」という風な意味になります。

andやorを組み合わせることにより複雑な条件を指示することができますが、うまく組み合わせを表現するには少し練習がいるかもしれませんね。

字下げ(インデント)

ところで、例題の3行目や5行目の命令には先頭に空白(スペース)がいくつか入っています。Small Basicでは""でかこまれた文字列の中以外では空白は無視されます。なので、この空白はあってもなくてもどちらでも構いませんし、プログラムの実行にはなんの影響も及ぼしません。
じゃ、なぜ空白を入れるかと言うとそうするとプログラムが読みやすくなるからです。
こういう目的で使われている空白を「字下げ」とか「インデント」と呼びます。

例えば、If文はその終わりを示すEndIfと必ず対になっていますが、If文からEndifまでの一連の命令を塊として考えたほうがプログラムの内容を理解するときに理解しやすいことがあります。例としてIf/EndIfの中に入れ子になってIf/EndIfが書かれた場合を考えてみましょう。

下の例はif文が二重に入れ子になっているサンプルです。

now=Clock.Hour
If now >= 11 or now < 18 Then
  If now = 12 Then
    TextWindow.WriteLine("お昼だ!!")
  Else
    TextWindow.WriteLine("こんにちは")
  EndIf
EndIf

この例題のインデントをなくしても、プログラムは全く同じに動作します。

now=Clock.Hour
If now >= 11 or now < 18 Then
If now = 12 Then
TextWindow.WriteLine("お昼だ!!")
Else
TextWindow.WriteLine("こんにちは")
EndIf
EndIf

でも、見やすいのはどちらでしょうか?まぁ、入れ子が二重くらいであれば見やすさに違いはそれほどないかもしれないけれど、入れ子がもっと複雑になったり、If/EndIfの中の命令がもっとたくさんになってくると、下の例のようにインデントを一切入れないで書くとプログラムを読むときの見通しがとても悪くなってしまうのです。一方でインデントを入れた例では、どのくらい字下げを行っているかで対になるIf/EndIfがどれなのか、がとても分かりやすくなります。

というわけで、Small Basicに限らず近代的なプログラミング言語でプログラミングをする場合にはインデントをうまく使うようにする習慣があります。今回の例では空白を二つずつ行の頭に入れてインデントしていますが、いくつ空白を入れるかはプログラミング言語や、プログラムを作る人によって様々な習慣があって、どれが正しいといれるものでもありません。ただし、プログラムを読みやすくする為にプログラム全体にわたって決まったルールでインデントするようにしましょう。

文字列の判定

では次に次のようなサンプルを試してみましょう。

TextWindow.Write("お名前は? ")
name=TextWindow.Read()
If name = "たけし" Then
  TextWindow.ForegroundColor="blue"
EndIf
TextWindow.WriteLine(name+"さん、こんにちは")

2行目までは大丈夫だと思うけど、3行目のif文で、「name = "たけし"」という式があります。これは「変数nameの中身が"たけし"(ダブルコーテーションは含まない)と同じであれば」という条件式を表しています。つまり、if文の中では数だけでなく、文字列も比較することができるのです。

4行目ではTextWindow.ForegroundColorというまるで変数のようなものに"blue"という文字列を代入しています。このForegroundColorは「TextWindowのプロパティ」と呼ばれていてまるで変数のように使う事ができますが、Small Basicによって最初から用意されているものでTextWindowの性質を表現するための特別な変数のようなものです。TextWindowにはSmall Basicによって最初から用意されている(定義されている)このようなプロパティが幾つかありますが、後からプログラマーがプロパティを追加することはできません。

「Foreground Color」は「前景色」とでも訳せばよいのでしょうか。テキストウィンドーに表示される文字の色を表しています。「blue」はもう習ったかもしれないけど、色の「青」だよね。なので、「4行目は文字の色を青にしなさい」というような指示のための行になります。


もうひとつ6行目の「name+"さん、こんにちは"」が奇妙な点に気付きましたか?このnameという変数には2行目でプログラム実行時にキーボードから入力した文字列が入っているはずです。例えばキーボードから"あつし"と入力していた場合、ここは「"あつし"+"さん、こんにちは"」という式と同等となると思います。では、文字列と文字列を「足す(+)」とはいったいどういう意味なのでしょうか?

Small Basicでは文字列と文字列を足すと、二つの文字列を「連結する」という意味になります。つまり、この式の結果は「"あつしさん、こんにちは"」となるのです。じゃぁ、文字列同士の引き算や掛け算、割り算もあるのか、というと残念ながらそういう演算はできません。文字列同士の足し算はある種の便法のようなものなのですね*1

=(イコール)の話

さて、もし君が十分に注意深いならば前回の記事で等号記号/イコール(=)は変数への代入を表している、と説明されていたことを覚えているかと思います。ところが今回のif文の条件式の中で使われた = 記号はいわゆる等号、つまり = の左右の式が同じ値である、という条件を表現しています。

つまり何を言いたいかというと等号記号 = は、使われる場所によりその意味するところが異なってくるということです。これはとてもややっこしいので注意する必要があります。

整理しておくと、if文などの条件式で使われる = は等値関係の条件を表し、それ以外の場所で使われるときは変数やプロパティへの代入を表しています。

ちなみに等値関係は = ですが、「≧」は「>=」と表現し、「≦」は「<=」と表現します。「≠(等号否定)」は「<>」と表現します。つまり、

If(num <> 2) Then
  ....
EndIf

という条件式は「numが2と等しくなければ」という意味になります。

複雑なif文

And や Or を使い複雑な条件を表現することを説明したかと思いますが、次のサンプルの条件式をみてみましょう。四つの条件式が括弧やand/orで複雑に組み合わされています。これは文章にすると、「nameが"たけし"または"あつし"で、かつ、seibetsuが"男"または"おとこ"の場合」という意味になります。

TextWindow.Write("お名前は? ")
name=TextWindow.Read()
TextWindow.Write("性別は? ")
seibetsu=TextWindow.Read()
If ((seibetsu = "男") or (seibetsu = "おとこ")) and ((name = "たけし") or (name = "あつし")) Then
  TextWindow.ForegroundColor="blue"
EndIf
TextWindow.WriteLine(name+"さん、こんにちは")

「条件式Aまたは条件式B」という条件を表現する場合にはorというキーワードを使い、二つの条件を連結しましたが、この条件そのものが新たな条件式になることに気づくでしょうか?つまり、「条件式AB=条件式A or 条件式B」という関係がなりたちます。これはandでも同じです。そうすると今回の複雑な条件式は、「((条件式1[seibetsu = "男"]) or (条件式2[seibetsu = "おとこ"])) and ((条件式3[name = "たけし"]) or (条件式4[name = "あつし"]))」、つまり「((条件式1) or (条件式2)) and ((条件式3) or (条件式4))」と表現できますので、orで連結された条件式を整理すると「(条件式12) and (条件式34)」という意味になります。当然これもandで連結された条件式なので、新たな一つの条件式になります。

ところでやたらと括弧()で条件式を括っていたのはなぜなのでしょうか?

例えば「条件式A and 条件式B or 条件式C」という条件式があった場合、これは「条件AとBがともに成立するか、もしくは条件Cが成立する場合」という意味なのか、「条件BまたはCが成立し、さらに条件Aが成立する場合」という意味なのかはっきりとはわかりません*2。この条件式は「条件式A and (条件式B or 条件式C)」や「(条件式A and 条件式B) or 条件式C」と括弧を使ってまとめることができます。この場合の括弧は数学で使う括弧と似ていて「括弧の中を先に計算する(評価する)」ということを意味しています。つまり、「条件式A and (条件式B or 条件式C)」は「条件BまたはCが成立し、さらに条件Aが成立する場合」という意味であることがはっきりするのです。

まとめ

If文を使う事で条件によってプログラムの流れを変えることができます。条件は数が同じかどうか、大きいか小さいかを比較することができますし、文字列が同じかどうかを比較することもできます。

今日出てきた用語
インデント
プログラムを見やすくするために行の先頭に入れる空白のこと。この空白はSmall Basicから無視される。
文字列
一つの塊として扱われる文章、文字の集まりのこと。ダブルコーテーションで前後を挟んで表現されるが、そのダブルコーテーションそのものは文字列の一部としては扱われない。変数に代入することができる。

*1:実はSmall Basicでは文字列同士の引き算や掛け算をしてもエラーにはなりません。それぞれが数値0として扱われて引き算や掛け算が行われるようです。

*2:実はSmall Basicからするとルールがはっきりしているのでとても明確なのですが、人間が条件を読んだときにどちらを意味するか分かりにくい、ということが問題なのです

簡単な計算をしてみよう

では、実際にSmall Basicでプログラミングを試してみよう。

この例を実際にSmall Basicに入力して動かしてみましょう。

TextWindow.WriteLine("1:値を入力してください")
num1=TextWindow.ReadNumber()
TextWindow.WriteLine("2:値を入力してください")
num2=TextWindow.ReadNumber()
num3=num1+num2
TextWindow.Write("合計は")
TextWindow.Write(num3)
TextWindow.WriteLine("です")

これは二つの数値を入力させ、その「和」を計算して表示するプログラムです。

文字を表示する

一つ一つ見ていきましょう。

TextWindow.WriteLine("1:値を入力してください")

この文は、()で囲まれた内容をテキストウィンドーに表示する命令です。「テキストウィンドー」とはこのプログラムを実行した時に現れる背景が黒色のウィンドーのことです。テキストウィンドーは文字を表示したり、キーボードから入力するために使われます。

TextWindow.WriteLine()

はテキストウィンドーに文字や数値を書き込み、最後に改行を行う命令です。例えば、

TextWindow.WriteLine("ABCDEFG")

という命令を実行すると、

ABCDEFG

とテキストウィンドーに表示されます。表示する文字の前後を「"(ダブルコーテーション)」で囲んでいることに注意してください。
例題の6行目と8行目に

TextWindow.Write()

というTextWindow.WriteLine()とよく似た名前の命令が使われていることに気づいたかもしれません。この命令も同じく指定された文字や数値をウィンドーに出力しますが、違いは最後に改行を行うかどうかだけです。

TextWindow.WriteLine("ABCDE")
ABCDEと表示した後改行する。
TextWindow.Write("ABCDE")
ABCDEと表示した後改行しない。

これは次のプログラム例を実行してみればわかると思います。

TextWindow.Write("klmno")
TextWindow.Write("pqrst")
TextWindow.WriteLine("abcde")
TextWindow.WriteLine("fghij")

実行した結果は次のようになると思います。

"klmno"と"pqrst"の間、それに"pqrst"と"abcde"は次の行に改行されないでそのまま続けて表示されるのに、"abcde"の後に次の行に改行されてから"fghij"が表示されます。

キーボードからの入力

2行目と4行目を見てください。

num1=TextWindow.ReadNumber()

TextWindow.ReadNumber()はキーボードから数を入力する命令です。数(0〜9)以外の文字は入力できません(しても無視されます)。数を入力した後は「Enter」キーをたたく必要があります(は「エンターキー」のつもり)。

12345

では、入力された数はどこにいったのでしょうか?TextWindow.ReadNumber()の前に「num1=」というのが着いていますが、これは「TextWindow.ReadNumber()で読み取った数を、変数 num1に代入せよ」という意味になります。

ところで数字だけでなく、他にも文字を入力するには

TextWindow.Read()

という命令を使います。

変数

「変数」は「名前のついた入れ物」のようなものと考えてください。この入れ物には色々なものが入れられます。中学校ではそろそろ「関数」を習い始めていると思うので、そこで使うxやyのようなものと考えてもよいかもしれません。

変数の名前はある程度は自由につけることができますが、規則があります。

  1. 使える文字は(a〜z(A〜Z)のアルファベット、数字と記号「_(アンダースコア)]のみ。アンダースコアは空白の代わりに使われることがよくあります。
  2. アルファベットの大文字と小文字は区別しません。つまり、NumBeR と number は同じものとみなされます
  3. 数字が名前の先頭に来てはいけません。つまりnum1はokですが、1ban はだめ。
  4. Small Basicのキーワードと同じ名前の変数は使えません。


変数へなにかを入れる(代入すると言ったりします)には、記号「=」を使います。例えば、変数"num1"に3.141592という値を代入するには、

mum1=3.14159

とします。

ここでは「=」は数学でいうところの「等号」をあらわしているのではなく、代入を表しています。なので、こういう書き方をすることもあります。

x=3
x=x+5

「=」が等号だと考えると、一行目はともかくとして二行目は妙な感じがすると思います。数学的には二行目が成り立つようなxは存在しませんからね。*1

Small Basicで=が代入だとすると、上の例は次のように解釈できます。

x=3    変数xに3を代入する
x=x+5   変数xの値(この場合3)に5を加えて、xに代入する

代入された値は単に変数の名前を書けば参照できます。上の例では2行目の = 記号の右側にあるxはその値を参照していることを示しています。一行目でxに3を代入しているので、2行目でxを参照する際には3という値を得ることができます。

変数の値を「参照する」といった場合、それは変数の中をみて何が格納されているかを調べているだけなので参照したからと言っても中の値が消えるというわけではありません。最初に変数への代入は名前付きの入れ物になんかを入れるようなものだ、という書き方をしましたが、だからと言って参照するときに中から取り出してしまうというわけではないのです。

ところで、変数を参照するとしてもあらかじめその中になにも入っていなかったらどうなるのでしょうか?試してみましょう。

予めなにも値を代入していない変数 hoge をTextWindow.WriteLineで表示しようとしていますが、「変数'hoge'は使われていますが、それに対する値は指定されていません。正しく値を確認したか確認してください」というエラーが発生してしまいました。

つまり、予めその中になにも入っていない変数は参照することができない、ということなのです。

変数には数値だけではなくて、色々な物を入れることができます。例として文章(文字列と呼んだりします)を入れてみましょう。文字列を指定する場合には文字列の前後を引用符(ダブルコーテーション)で囲んでやる必要があります。ただし、代入された文字列の中にダブルコーテションは含まれません。

num1="Hello World"

数学で習った変数のことを考えると、変数に文章が入るのはなんだか奇妙な感じがするかもしれませんね。でも、変数を「入れ物」と考えると少しわかりやすいかもしれません。

ところで、変数には一度には一つのモノしか入れることができません。新しいモノを入れると、以前から入っていたモノは捨てられてしまいます。

計算をさせる

コンピューターは計算が得意です*2。Small Basicでも四則演算を始めとして様々な計算が可能です。ここではとりあえず四則演算を覚えましょう。

+
足し算を行います。
-
引き算を行います。
*
掛け算を行います。×記号の代わりです。* はアスタリスクと呼びます。
/
割り算を行います。÷記号の代わりです。/ はスラッシュと呼びます。分数記号のようなものと覚えてもいいかも。

この記事の最初の例の5行目では足し算をしていますね。

num3=num1+num2

ここでは変数num1に格納されている値と、変数num2に格納される値の和を計算して、結果をnum3に代入しています。試しに + 記号を他の四則演算の記号と置き換えて実行するとどうなるか見てみてください。

まとめ

変数とは様々なデータを格納できる名前の付いた入れ物のようなものです。今回は変数の使い方を説明しました。また、テキストウィンドーに文字を表示したり、キーボードから文字や数を入力する方法、数に四則演算を行う方法も説明しました。

今日出てきた用語
テキストウィンドー
文字を表示したりキーボードから文字や数を入力するためのウィンドー
変数
様々なデータを格納できる名前がついた入れ物のようなもの

*1:これが気持ち悪い、と感じる人は他にもいたようでPascalというプログラミング言語では代入には「:=」というコロン(:)とイコール(=)を組み合わせた書き方をします、がそれは余談。

*2:試しに家のパソコン(i5-2400)でπを一億桁計算させてみたら4分弱で終わりました。すごいな最近のPCは

プログラミング

そもそも「プログラム」や「プログラミング」とは何なのでしょう?

プログラムとは

コンピューターは実に色々な事ができます。膨大な計算を行い、膨大なデータを蓄え、電車やロケットを制御し、そしてコンピューターゲームや音楽、CGなどを人間にとっての楽しみさえも提供します。

ただ、どれだけ複雑な事をしているようであっても結局のところは人間が指示したとおりに動いているにすぎません。その「指示」のことを「プログラム」とよび、プログラムを作成することを「プログラミング」と呼びます。人間が指示、つまりプログラミングした以外のことはコンピューターはなにもできないのです。
もともとの指示が間違っていた場合は、コンピューターは「間違ったように」動作します。こういう指示の間違いのことを「バグ」と呼んだりします。

「プログラム」は敢えて日本語に訳すと「算譜」と訳されることが多いようです。これは「楽譜」と言葉が似ていると思いますが、基本的な構造やルールもプログラムと楽譜(五線譜)はとてもよく似ています。

例えば次のような点です。

  1. 小さな構成単位に分解されます。楽譜では音符やその他の記号に分解されますが、プログラムも同様です(後で詳しく説明します)
  2. 最初から始まり特別な指示がない限り終わりまで読み進めていきます
  3. 特定の指示があった場合には指示された区間を繰り返すなど、処理の流れを途中で変更する手段を持っています



(楽譜の例)

または、演劇の脚本のようなものだと考えても良いかもしれません。

プログラミング言語

実はコンピューターはとても単純な処理しかできません。ただ、それをとても素早く行うことができます。
コンピューターに指示を行う、つまりプログラミングをする場合にはそのコンピューターに理解できる形で指示を与えてやる必要があります。しかしその指示はとても単純な処理を山のように組み合わせることによって行う必要があります。例えるならば、「レゴブロック」で実際の大きさの高層ビルやタンカーを作れ、と言っている様なものなのです。仮にレゴブロックに十分な強さがあったとしても、それを一人の手で組み立てて高層ビルを作ることは絶対に不可能とは言わないけれど、あまりやりたいことではないと思います。

そこで考えられたのが、できるだけ人間が普段使うような言葉に近い人工的な言語を作り出し、その言語を使ってプログラミングを行い、そしてできたプログラムをコンピューターが理解できる言語へ翻訳してやるという方法です。そう聞くとかえって難しいことをやっているように思えるかもしれませんが、例えば前回の例ででてきた

GraphicsWindow.DrawRectangle(100,100,200,200)

Small Basicのこのたった一行の命令は裏では多分数千から数万もの命令に翻訳されているのです*1

人間の言葉にも英語や日本語、フランス語といったように色々な言葉があるようにプログラミングをするための言語にも沢山の種類があります。これを「プログラミング言語」と読んだりします。いくつか例を見せましょう。これらは全て1から10までの自然数を足し合わせた結果を表示するプログラムです。


C言語

#include <stdio.h>

void main(int argc, char **argv)
{
    int i;
    int sum=0;

    for(i=1;i<=10;i++){
        sum+=i;
    }
    printf("Sum of 1~10 is: %d\n",sum);
}

Common Lisp

(defun sumnum (start end)
  (if (> start end)
    0
    (+ start (sumnum (+ start 1) end))
  )
)
(format t "Sum of 1~~10 is: ~D" (sumnum 1 10))

Perl*2

printf "Sum of 1~10 is: %d\n",sub{$s+=$_ foreach (1..10);return $s}->();

FORTRAN 77」

       INTEGER  I, SUM

       SUM=0
       DO  10 I=1,10
          SUM=SUM+I
   10  CONTINUE

       WRITE(*,*) 'SUM OF 1~10 IS: ', SUM

       END

「APL」

Java

public class Sum10 {
    public static void main(String[] args) {
        int  i, sum;
        sum=0;
        for(i=1;i<=10;i++){
            sum+=i;
        }
        System.out.println("Sum of 1~10 is: "+sum);
    }

}

上の例はほんの一例で、世の中にはもっとたくさんのプログラミング言語が存在し、そして使われています。
なぜそんなに沢山の種類のプログラミング言語があるのか?どれか一つに統一したほうがよいのじゃないのか?
そう思うかもしれませんが、それぞれの言語にはそれぞれの特徴や得意な分野が存在し、使い分けられているのです。

じゃぁ、コンピューターを使いこなすためにはそれらのたくさんのプログラミング言語を覚えなければいけないのか、というとそうでもありません。
実際によくつかわれるプログラミング言語はほんの少数ですし、
もし自分がよく知っているプログラミング言語ではないプログラミング言語を使わなくてはならなくなったとしても、
どれか一つの言語に習熟できていれば、その他の言語を覚えるのは比較的容易いと思います。

まとめ

「プログラム」とはコンピューターに指示を与えるために考案された人工の言語(プログラミング言語)でかかれた指示のことです。
Small Basicもプログラミング言語の一種です。
コンピューターは指示されたように動きますが、指示された以外の動きはしません。間違った指示のことを「バグ」と呼びます。

今日出てきた用語
プログラミング言語
コンピューターに指示を与えるために使われる人工の言語。
プログラム
コンピュータに指示を与えるためにプログラミング言語で書かれた指示書のこと
バグ
プログラムのうち、期待したように動作をさせないような間違った指示のこと

*1:実はこの説明には微妙なウソがというか、ややっこしい事情があるのだけど、それはまた別の機会に説明します

*2:敢えてperlらしく(?) ワンライナーで書いてみましたが、無名関数を使うよりももっとスマートに書ける方法があるかもしれない...

まずは動かしてみよう

何はともあれSmall Basicを動かしてみよう。

Small Basicの画面

ワープロなどの普通のアプリケーションを起動するのと同じようにスタートメニューからSmall Basicを起動すると、次のような画面が表示されると思います。

画面は三つの部分からなっています。ここではそれぞれ赤青緑の箱で囲み1〜3の番号をつけてみました。


1の赤い線で囲まれた部分は「ツールバー」または「リボンツールバー」と呼ばれ、これから作るプログラムを実行したり保存したりするために使います。
2の青い線で囲まれた部分は「エディター」と呼ばれ、ここにSmall Basicのプログラムを編集します。
3の緑の線で囲まれた部分にはプログラムをしていく際に便利なヒントやヘルプが表示されます。

実験してみよう

何はともあれ実験してみます。

エディターの中に次のようなプログラムを入力してみましょう。

GraphicsWindow.DrawRectangle(100,100,200,200)
GraphicsWindow.DrawEllipse(200,200,150,150)


誤りなく正確に入力できたらツールバーの「実行」と書かれた青い三角のボタンを押してみよう。そうすると入力したプログラムが実行できます。

このプログラムは「長方形」と「円」をウィンドーに描画するプログラムです。一行目が長方形を、二行目が円を描くようにコンピュータに指示するための命令です。


では、三行目に次の行を追加してみてください。

GraphicsWindow.DrawEllipse(100,200,250,250)


下のほうがチョットはみ出してしまってるけど、大きさの違う円がもう一つ描画されました。


プログラミングをするには少しの英単語を覚えないといけないので、中学校一年生には大変かもしれませんがこのプログラムを一つずつ見ていってみましょう。ただその前に幾つか覚えておくとよい規則があるので、それを先に説明します。


Small Basicの中で使われている「単語」では大文字小文字が混じって使われているのに気づいているかもしれないけど、これは実は複数の英単語をくっつけて表現しているのです。理由はもう少しあとで詳しく説明しますが、ここでは「空白」が使えない場所があるので、便宜的に単語と単語の境目を分かりやすく表すために大文字を使っていると考えてくさい。

例えば、

Graphic window ==> GraphicWindow
Draw rectangle ==> DrawRectangle

みたいな感じに単語と単語の間の空白を取って、それだと単語の区切りが分からないので大文字にしているのです。ちなみに辞書を繰ると分かりますがそれぞれの単語の意味は、Graphic(図形)、Window(窓)、Draw(描画する)、Rectangle(長方形)、Ellipse(楕円)というくらいの意味です。

じゃぁ、「.(ピリオド)」はどういう意味をもつのでしょうか?試しに一行目の「GraphicWindow」と「DrawRectangle」の間の「.(ピリオド)」を「,(カンマ)」に変えて実行してみてください。

エディターウィンドウの下が分割されて次のようなエラーメッセージが表示されました。

いくつかのエラーが発見されました...
1,15:認識できないステートメントです。

ここでいう「ステートメント」とは「命令文」くらいの意味合いです。

つまり「.(ピリオド)」はここでは特別な意味をもっていて、この通りに入力しないとパソコンは正しく命令を解釈できないのです。

今日のポイント

コンピュータは人間が指示したとおりに動きます。指示の文法や手順が間違っていると期待した動きをしなかったり、エラーになります。このようなエラーを「バグ」と呼びます。バグを修正しない限りコンピュータはまったく動かないか、期待した動きをしません。

さて、先ほど「,(カンマ)」に変えた「.(ピリオド)」を元に戻しておきましょう。

ところで話が少し戻りますが、先の例題を入力中に度々次のようなポップアップが現れたことに気づいたでしょうか?

これは「インテリセンス」と呼ばれるプログラムの入力を助けるための仕組みです。キーボードから途中まで入力していくとその先を予測し、テキトウな選択肢のリストをリストアップしてきます。そのままキーボードで最後まで単語を打ってもかまいませんが、カーソルキーの上下キーで適当なキーワードをリストから選択してもかまいません。途中まで入力した単語にマッチするキーワードがリストにない場合、インテリセンスは灰色に霧がかかったようになります。この場合は多分それまでに入力した単語に入力ミスがあるので、もう一度よく確認してみましょう。

次に入力したプログラムの適当な箇所、例えば"DrawRectangle"というセンテンスのどこか適当な場所にカーソルを移動してみましょう。そうすると、ウィンドウの右側にメッセージが表示されました。


これはカーソルが現在ある位置にあるSmall Basicの命令などのヘルプやヒントを表示しています。ここをよく読んでいけばSmall Basicのプログラミングをする際にとても有用な情報を得ることができます。

折角なので"DrawRectangle"の意味するところをみてみましょう。

DrawRectangle
選択されたペンを使用をして、画面上に四角形を描きます。

GraphicsWindow.
DrawRectangle(x, y, width, height)
x
四角形の X 座標。

y
四角形の Y 座標。

width
四角形の横幅。

height
四角形の高さ。

戻り値
なし


"DrawRectangle"は「()」の中に「,(カンマ)」で区切られた四つの数値を指定する必要があり、それぞれが四角形の左上の隅のX座標、Y座標、四角形の横幅と縦幅を表していることが分かります。これらの四つの数値のことを「パラメータ」とか「引数」と読んだりします。


ところでSmall BasicのXY座標について少し注意が必要です。

Small Basicのグラフィックスで座標を表現する場合は数学で使うXY座標系とは少し異なりY軸が下方向に向いています。つまり、グラフィックウィンドーの左上端がXY座標の原点(0,0)となります。


"DrawEllipse"は楕円を描画する命令です。

DrawEllipse
選択されたペンを使って画面上に楕円を描きます。

GraphicsWindow.
DrawEllipse(x, y, width, height)
x
楕円の X 座標。

y
楕円の Y 座標。

width
楕円の横幅。

height
楕円の高さ。

戻り値
なし

楕円は横幅と高さが同じ値の場合「円」になることに注意してください。DrawEllipseで指定するX座標とY座標はチョットややっこしいですが、描画する楕円がぴったり収まる長方形(円の場合は正方形)の左上端の座標です。

試しに次のプログラムを入力して実行してみましょう。DrawRectangleとDrawEllipseのそれぞれ四つのパラメータが同じ値であることに注意してください。

GraphicsWindow.DrawRectangle(100,100,300,200)
GraphicsWindow.DrawEllipse(100,100,300,200)

結果は多分このようになるでしょう。

まとめ

今回はここまで。

DrawRectangleやDrawEllipseのパラメータの値を変えるとどうなるか試してみましょう。


今日出てきた用語

プログラミングでは色々な用語が出てきます。その用語が初めて出てきたときには説明をするようにしますが、お父さんが忘れてしまっているな、と思ったときには教えてください。

ツールバー
Small Basicのウィンドーの上部に表示されているSmall Basicを操作するためのメニュー
エディター
Small Basicのプログラムを入力するウィンドー
ステートメント
Small Basicの命令文
バグ
プログラムの文法や処理方法の誤りの事
インテリセンス
Small Basicのエディタウィンドーで入力中に入力の補助をするメニューのこと
パラメータ(引数)
命令文の動作の詳細を指示する値

はじめに

中学生の息子がプログラミングに興味を持ちだしたようです。
思い返せば自分がコンピュータというものに興味を持ち、初めてのプログラミングらしきことをしたのもPC8001というもう30年近くも前のパソコン、というかその頃はマイコンと呼んでいた8bit PCの上のBASICでした。
そこで自宅のPCにSmall Basicをインストールし、息子に触らせてみることにしました。

初めてプログラミングを覚えるのにBASICがいいのか、という点では議論の余地はあるとは思いますがSmall Basicの良い点は、

  • 自分でやったプログラミングの結果を即座に確認することができること
  • 何かをする(例えばグラフィック画面上に円を描く)ための手続きがシンプルであること

この二点だと思っています。

JavaでもC++でもそうですが、初心者が何か結果を出すプログラミングをするには最初のハードルが高いのが難点だと昔から思っていました。その点Small Basicは最初のハードルが低いのでそこから学習を初めていって、もし更に興味が増すようであればC++でもJavaでも必要に応じた言語を覚えていけばよいと思います。
もっとも息子達に将来プログラマになって欲しいとかそういうことは現時点ではなにも思っていませんので、ただコンピューターという物がどういう風に動いているのか、という事の理解の足しになればよいなぁ、位の気持ちでいます。

このブログでは中学一年生の息子にSmall Basicとそのプログラミングの方法をレクチャーしながらその記録を残していこうと思います。理想的にはこのブログを見ながら彼が自分で学習していってくれるようであれば大成功です。
ブログをどう進めていこうかまだ頭の中で模索中ですし、息子がいつまで興味を持続してくれるかも未知数ですがとりあえず始めて行きたいと思います。