Scratch(渡し舟問題・川渡り問題)

Scratch-RiverCrossing001プログラム

今回の作品はこちら

中身をみたい場合はこちら

https://scratch.mit.edu/projects/567099787

ゲームの説明

有名な渡し舟問題(川渡し問題)です。スタートボタンを押してキャラクターをマウスで触れる(もしくはタブレットなら指タップ)すると向こう岸にわたります。誰も舟に乗っていないときでも舟をタップすると移動します。渡し舟問題のルールは次の項をみてね。

渡舟(川渡し)問題とは

渡舟問題は、狼・やぎ・キャベツ渡し舟に乗る人がいて。舟には狼・やぎ・キャベツの1つずつしか乗せることができないというルールがあります。

そして、人が岸にいて目を見張っている時は問題ないですが、人が岸から離れると、狼はやぎを食べてしまい。やぎはキャベツをたべてしまいます。狼もやぎもキャベツも食べられないで全部向こう岸に渡せるとゲームクリアにはなります。

Scratch-RiverCrossing001

この食べられないで全員を向こう岸に渡すには、どの順番で渡せばいいでしょう?正解にたどりつくには、舟だけ戻ってこさせたり、狼とやぎを向こう岸に渡した状態で、どちらかを引き戻すといったことも必要です。(ポイントは人が岸についてみている限りにおいては、食べられないというところですよ。)

プログラムを作る上での考え方

では、プログラムを作る上での考え方を説明したいとおもいます。まず今回は最初にどんな「変数」を作るのかを説明しながらイメージをつかんでいきますね。今回つくる変数はこちらです。

Scratch-RiverCrossing008

まず舟の状態を示す変数についてです。全部で4つの状態を用意しており、1のときがこちら岸に着岸している状態。2のときが何か物を乗せて向こう岸に渡っている状態。3があちら岸に着岸している状態。4のときが何か物を乗せてこちら岸に向かっている状態です。

この2と4が移動している状態だけでなく、何か乗せている状態と表現したのは、舟には一度に狼・やぎ・キャベツのいずれか1つのみしか乗せらせないので、2と4の状態のときには他のスプライトをクリックしても乗せる処理を発動させないという考え、裏を返せば舟の状態が1と3のときのみスプライトは舟に乗る事ができるとことになります。

次にいる場所という変数の存在です。これは渡し舟、狼・やぎ・キャベツがどちらの岸にいるかを表す変数です。これは厳密には、各スプライトそれぞれの名前の変数をつくる案もありますが、今回はローカル変数とすることで同じ名前で1種類(実質はスプライトごとに1つなので4つ)用意しました。※ローカル変数について知りたい場合はこちら

そして、取りうる値として舟の状態とあわせてわかりやすいようにこちら岸にいる時を1あちら岸にいる状態を3として2値のみを用意しています。

Scratch-RiverCrossing003

続いて、合計(こちら)合計(あちら)の変数の説明になります。これは以下の考え方に基づいて用意しています。

まず狼を値4、やぎを値2、キャベツを値1と定義します。(それぞれの年齢と思ってもらってもよいかもしれませんね。)そして、それらを以下の表のように組み合わせると、なんということでしょう。すべてのパターンにおいて、狼とやぎとキャベツの値の合計は1つも被ることなる1から7のいずれかで表現できるのです。

Scratch-RiverCrossing002

つまり、合計(こちら)と合計(あちら)の値がいくつかなのを見るだけで、狼とやぎとキャベツがどちらの岸にいるかが判断できるのです。

渡舟問題のゲームルールは、人が見はっていない時に狼とヤギが一緒にいたらOUT、同じくヤギとキャベツが一緒ならOUT、そして、狼・やぎ・キャベツがあちら岸に渡り切ったらSUCCESS(クリア)となります。

これを表でみると合計値が3と6と7の時に処理をしてあげる必要があるということがわかります。これがこちら岸とあちら岸の2種あるので、合計6パターンを用意する感じですね。

 

プログラムの中身

スプライトの説明となります。

狼・やぎ・キャベツのスプライト

Scratch-RiverCrossing009

まずは狼とやぎとキャベツのスプライトの説明です。基本的に3つは同じような処理で、違いはX.Y座標と合計を計算する際の値の変動幅、それから食べるアニメ処理くらいな感じです。コードの中身は以下の通り。

Scratch-RiverCrossing006

ここでのポイントは舟の状態をみて舟が自分がいる岸についていている時、自分にマウスが触れたらアクションを起こすという条件分岐、そして、条件が発動されたら舟の方向に向かって移動、舟に乗っている姿は舟と同じスピードで同じ座標に向かうということで実現しています。そして処理がおわったら自分のいる場所と合計値をあちら岸とこちら岸それぞれから足したり引いたりしているところです。

 

渡し舟のスプライト

Scratch-RiverCrossing010

渡し舟のスプライトのコードについては以下となります。ポイントとしては、舟もどうようにどちらの岸にいるかの状態をもっており、その状態に基づいてどっち側の岸に移動するのかの次の状態を判断する条件分岐、それから、状態2と4の時は川を渡る処理を実行しますが、そのトリガー(起動条件)は自身がマウスでクリックされた時と狼たちのスプライトがクリックされた時になっています。

Scratch-RiverCrossing005-1

背景のスプライト

今回は背景にもコードを入れています。背景の役割は先に示した表の状態になった時に、「くわれる」というアニメーションを起動させる役割です。先に述べたとおり6つのパターンの条件分岐を作っています。条件に合致した場合は、くわれる動作をメッセージを送る処理で指示をだし、背景を変えてプログラムを終了させる形となります。

Scratch-RiverCrossing004

背景はこのように、5パターン用意して画面変化をつけています。

Scratch-RiverCrossing007

 

まとめ

いかがでしたか?今回は狼・やぎ・キャベツが持つ数値の合計値の0~7で状態を表すというところが特徴的な考え方でしたよね。実はこの1・2・4を足し合わせて状態を表すのはLinuxのファイル/フォルダの権限管理の考え方なんですよね。

参考:Linuxのファイル/フォルダ権限管理

数字モード権限
4r (read)読み取り
2w (Write)書き込み
1x (eXecutable)実行

このように、簡単な法則を発見(もしくは使いまわして)論理的に考えていくのが、プログラミング教育で求められていることなのです。と、最後、強引にまとめて今回の記事を終わります。

 

コメント

タイトルとURLをコピーしました