4 車を道に沿って走らせてみよう

このプロジェクトでは,直線の道を折り返したり,円形の道に沿って走ったりする少し知的な車をプログラミングすることに挑戦します. これを実現するためには,道を判別する「センサー」と「場合分け」という概念を学習する必要があります.

プログラムもだんだんと複雑になってくるので,それを整理するために「フローチャート」という図法を活用します. まずは既にあるプログラムをフローチャートで表現することで,プログラムの構造を理解してみましょう. 次に実行前のプログラムのフローチャートを見て,どんな動作をするのか予想してみましょう.

プログラミングに関するキーワード

Squeakに関するキーワード

4.1 場合分け(1)- 各場合に実行する命令が1つの時

M先生
新しくproject3という名前のプロジェクトを作ってもらえるかな.今まで使ってきた車も用意しておいてね.
Sくん
はい.
M先生
まずは道路を往復する車を作ってみよう.道の端に車がくると,折り返して走り続けるようにしてみようか.
Tさん
すごい.そんなことができるんですね.
M先生
先に必要な部品を作ってしまおう.まず横向きの直線道路を描いてくれるかい?後で必要になるから,道路の両端に印をつけておこう. あとは道路の真ん中にセンターラインも入れておこう.車は青ハロを使って横向きにしておいてね.
Sくん
はい.道路の両端の印は緑色で描いておきました.こんな感じですかね.

M先生
いいね.次は車を少し改造するよ.道の端に来たかどうかを判別するために車に「 センサー 」を付けよう.
Sくん
えっ,また車を描くのかー.面倒くさいなー.
Tさん
描き直しハロを使えば,センサーだけを描き足すことができるよ.
Sくん
おっと.そうか.

M先生
センサーは車のボディの色と違う色にするのがポイントだよ.詳しくは後で説明するけれど,こうしておけば車が道の端に来たかどうか検知できるんだ.
Sくん
センサーをつけ終わりました.

M先生
よし,これで部品は全部そろったね.次は完成させたい車の動きをしっかり確認してみよう.
Tさん
言葉で説明するとしたら,「車は道に沿って直進し,道の両端に来たらそれまで走っていた方向と逆向きに反転する」かな.
M先生
言葉だけで説明するのは難しいね.図も一緒に描くと分かりやすいかな.
Sくん
こんな感じですね.

M先生
いいね.

M先生
さて,いよいよプログラミングをしてみよう.まず,車に「道路を往復する」という名前のスクリプトを作ってくれるかい?
Sくん
はい.できました.

M先生
まずは,プログラムを組み立てる前に車の動きを整理してみようか.
Sくん
はい.
M先生
道路の端に車が来た場合はどのような命令が必要かな?
Tさん
180度回転させればよいと思います.
M先生
じゃあ,車が道路の端以外ところにある場合はどうしたらいいかな?
Sくん
進めればよいのではないでしょうか.
M先生
そうだね,車が道路の端に来た場合とそれ以外の場合で処理を変えればよいんだ.

Tさん
まずは「車が道路の端に来たかどうか調べる」ことがしたいですね.
Sくん
うーん,そんなタイルはどのカテゴリにもありませんね.
M先生
そこでセンサーの出番だね.センサーを使えるとすると,どのようなことを調べればいいかな?
Sくん
「センサーが道の端を検知したかどうか調べる」ですね.
Tさん
でも「センサーが道の端を検知したかどうか調べる」というタイルもないですね.
M先生
「センサーが道の端を検知したかどうか調べる」ことをもっと具体的にしなければいけないんだ.今回は「色」による判定を使ってみよう. 「 センサーカテゴリ 」に「 部分が色に触れているか 」タイルがあるだろう.

Sくん
なるほど.このタイルを使えば「車のセンサー(青色)が,道の端の印(緑色)に触れているか」を調べることができるんだ.
M先生
では実際にやってみよう.「部分が色に触れているか」タイルを「道路を往復する」スクリプトに入れてみて.
Sくん
はい.

Tさん
わぁ,タイルが変化しましたね.

M先生
次に色の設定をしよう.まず左側の色から.左側の色の部分をクリックすると,色を選ぶスポイトが表示されるよね.

Sくん
このパレットから色を選べばいいんですね.センサーの色にするのが微妙で難しいなー.
Tさん
そんなことせずに,センサーの色をスポイトで選択すればいいじゃない.こうやって.

Sくん
おっ.鋭いねー.
M先生
あとは右側も同じ要領で,道路の端の印の色(緑色)を選択すればいいね.
Tさん
残るはそれぞれの場合に実行する命令ですね.「何もしない」と書いてある部分にタイルが入るんですね.
Sくん
えっと,反転させるためには回すタイルを使えばいいから....あれっ?
Tさん
先生,私の方はできました.

Sくん
どれどれ.
Tさん
ちょっとー.カンニングしないでよ.
Sくん
ケチだなー.
No. 3-1 やってみよう!

道路の両端に印を付けないで,同じ動き方をする車を作ってみましょう.



No. 3-2 考えてみよう!

例題で作ったプログラムに以下のような改造を加えると,車はどのような動きをするか予想し,その理由を説明してみましょう.

  • 色に触れているかの判定タイルの左側の色を車のボディの色に変更する
  • 車を進めるドット数を大きくする.(ドット数がある値以上になると,車はどのように動くでしょうか)


ヒント

どうしても理由が分からないときは,「実行ボタン」を押してスクリプトを一回ずつ実行し,車の動きを観察してみましょう.



4.2 場合分け(2)- 各場合に実行する命令が複数の時

M先生
これまで車は一直線に走っていたけれど,次は道の端で折り返すときに車線を変更するようにしてみよう.
Sくん
車の動きを図にするとこんな感じですね.こうすれば車が2台になっても正面衝突しなくなりますね.

M先生
よし,じゃプログラムを組み立てていこうか.
Tさん
スクリプトを新しく作る必要はありますか?
M先生
そうだね.「車線を変更しながら道路を往復する」というスクリプトを作ろう.次に作りたい命令を日本語で説明してみようか.
Tさん
「車が道路の端に来たかどうか調べて,道路の端に来たなら車線を変更して反転させる,それ以外のときは車を進ませる」を繰り返せばOKですね.
M先生
さっき作った命令と違うのはどこかな?
Tさん
「車線を変更して反転させる」という部分です.
Sくん
反転してから車線を変更してもいいですよね?
M先生
そうだね.ただ,反転してから車線を変更するとプログラムがややこしくなるはずだよ.
Sくん
えっ?なんでだー???
M先生
じゃあS君は反転してから車線を変更するという方法でやってみなさい.
Tさん
先生,私はできました.それぞれの場合に実行する命令を入れる部分には,複数の命令を入れることができるんですね.
M先生
そうだね.複数の命令があれば上から順番に実行されるんだ.

Sくん
うーん.できないよー.
No. 3-3 考えてみよう!

S君が選んだ,「反転させてから車線を変更する」方法ではなぜプログラムがややこしくなるのでしょうか.理由を考えてみましょう.



No. 3-4 やってみよう!

車をコピーし,複数の車を道路に走らせてみましょう.

オブジェクトをコピーすると,スクリプトも一緒にコピーされます. コピー元のオブジェクトのスクリプトを実行したままコピーするとどうなるかも試してみましょう. コピーしたオブジェクトのスクリプトを削除してもコピー元のオブジェクトのスクリプトには変化がないことを確認しましょう.


ヒント

複数のオブジェクトのスクリプトを一度に実行する場合は,部品フラップにある「全スクリプト」ツールが役に立ちます. 節[全スクリプト] に使い方の解説があります.



No. 3-5 考えてみよう!

例題として作った以下のスクリプトをよく見てください.進める命令タイルが2つ入っていますね. 四角で囲んだ2つのドット数(100ドットと10ドット)にはどんな意味があるでしょうか. 道は縦幅より横幅の方が長いはずです.縦方向に走る時のドット数(100ドット)の方が,横を走るときのドット数(10ドット)より大きいのはなぜでしょうか.



M先生
ちなみに,センサーカテゴリのタイルがなくとも,場合分けタイルだけを取り出すこともできるんだ.
Sくん
どうやるんですか?
M先生
スクリプトについている時計の横の四角いアイコンをクリックしてみて.
Sくん
はい.

M先生
出てきたタイルをスクリプトの中に入れて,「何か」の部分に調べたい事柄を表現したタイルを入れればいいんだ.

Tさん
ちょっと面倒くさいですねぇー.
M先生
あまり使わないと思うけど,念のため説明しただけだよ.

4.3 フローチャート(1)- 場合分けが1つの時

Sくん
先生,今度はコースを丸くしてみて,どっちが先に道に沿って走る車を完成できるか勝負してます.

M先生
なるほどね.どれどれ,プログラムを見せてみて.
Sくん
僕のはこうです.

Tさん
私はちょっと違います.

M先生
なるほど.直線道路のプログラムと違うのは,センサーの部分が道路の外にあるかを調べているところだね. どちらのプログラムでも車はちゃんと道に沿って走れるというわけか.
M先生
では,どちらが早くコースを一周できるか競争してみようか.車が速く走るようにプログラムを改造してもいいよ.
Sくん
車を速くするためには,進むドット数を大きくすればいいんだ.30ドット位にしてみようかな.
Tさん
私も.
Sくん
ぐはっ,進むドット数を30にすると,僕の車はコースアウトしてしまいました.

Tさん
私の車はコースアウトしませんね.
M先生
どうして違う結果になったのか説明できるかな?
Tさん
車が道から外れた時の動きが違うのかも....
Sくん
僕のプログラムでは,車を進める命令が場合分けタイルの外にあるよね.
Tさん
うん.問題は車が道から外れた時の動作の違いってことだね.

Sくん
場合分けタイルの外に進める命令があると,道から外れた状態でも車は進んでしまうんだ.
Tさん
私の場合は,車が道の方向に戻るまで進まないよ.
M先生
2人ともいい線いってるね.じゃあ,より整理して考えるために「 フローチャート 」という図法を紹介しよう. 2人のプログラムをフローチャートで表現するとこうなるね.

Sくん
微妙に違いますね.
M先生
ひし形が場合分けを表している.四角が命令を表現しているんだ.どこが違うかな?
Sくん
僕のプログラムは,まず進めるが実行されてから,場合分けが実行されるんだ.だから,進むドット数が大きすぎるとコースアウトしてしまうんですね.
Tさん
私のプログラムは,車が道から外れている場合は,回るだけです.だから進めるドット数を大きくしても大丈夫なんですね.
M先生
そうだね.Sくんのプログラムは,場合分けタイルの外に進めるという命令があるよね. これだと車が道から外れているかに関係なく,常に進める命令が実行されるということだ.
Sくん
なるほど.だから進めるドット数を大きくすると,コースアウトしてしまうんですね.
M先生
今回は既に作ってあるプログラムを整理するためにフローチャートを使ったけれど, プログラムを作る前にフローチャートを描いておくと,プログラムがどのように動作するかを考えやすくなるね.

No. 3-6 やってみよう!

節[場合分け(1)- 各場合に実行する命令が1つの時]節[場合分け(2)- 各場合に実行する命令が複数の時]で作ったプログラムのフローチャートを描いてみましょう.



4.4 フローチャート(2)- 場合分けが2つの時

Sくん
うーん.車を道の真ん中を走らせるためには....
Tさん
どうしたの?
Sくん
今までの車では道の端を走ってしまうから,道の真ん中を走らせようとしているんだ.
M先生
それなら色違いのセンサーを2つ用意するのがオススメだね.こんな感じかな.

Sくん
そうか.そうすると場合分けタイルが2つ必要になるのか.
M先生
まずはプログラムを組み立てたら,車を走らせる前に先生に見せてくれるかい?
Sくん
僕のプログラムはこうなりました.

Tさん
私のはこうなりました.

Sくん
わー,場合分けタイルの中に場合分けタイルが入るんだ.はじめて知ったよ.
M先生
そうだね.こういう状態を「 入れ子 」と呼ぶよ.
M先生
じゃあ,それぞれのプログラムをフローチャートで書くとどうなる?
Tさん
こうでしょうか.

M先生
どうだろう.このフローチャートを見て,それぞれの車の動きは違うか同じか予想してみよう.
Sくん
えっと,僕のは前に作ったのと同じで,必ず進む命令が実行される. だから,進めるドット数を大きくするとコースアウトしてしまうと思います.
Tさん
私のプログラムは道からはみ出ていない時だけ車が進むから,S君の車と違ってコースアウトはしませんね.
Sくん
実行する前からコースアウトすることが分かるなんて....しょぼーん.
M先生
じゃあ実験してみよう.
Tさん
やっぱり進めるドット数を大きくするとS君の車はコースアウトね.
M先生
まぁまぁ.フローチャートを書くことで,実行する前からプログラムの動作を予測しやすくなっただろ. S君だってどのように直せばコースアウトしないか分かったはずだよね.
Sくん
はい.
No. 3-7 考えてみよう!

以下のようなヘアピンカーブのあるコースをうまく走るためにはどうしたらよいでしょうか.



No. 3-8 考えてみよう!

以下のようなコースはセンサーが1つの車でうまく走れるでしょうか.うまく走れるかどうかを予想し,その理由を説明してみましょう.



No. 3-9 考えてみよう!

例題で作ったプログラムを,以下のように別々のスクリプトに分割し,同時に実行すると車はどのような動きをするでしょうか.



練習問題

4.1

車を走らせたり,止めたりできるスイッチを作りなさい.

4.2

車を左右に操縦できるスイッチを作りなさい.

4.3

決められた範囲内で車を前後に操縦できるスイッチを作りなさい.

4.4

あり集めゲームを作りなさい.

4.5

複数の車を競争させることができるレースゲームを作りなさい.

4.6

一定の幅で左右に移動する反転するカニを作りましょう.