学校設定科目「コンピュータサイエンス」の記事3回目です。
AppLabの使い方の学習を終えて、9月からは実際にコンピュータを使って課題を解決する手法を学ぶ時間とし、数学的な課題2つ、理科的な課題2つを実施することにしました。
私以外の先生はプログラミング経験が少なく、生徒と一緒にコーディングを学んでいました。先に私が一つ例となる課題を作り、先生方に示しました。
課題1 数字の●を言ったら負けゲーム
数学の先生が作ってくれた課題の1つ目は「数字の●を言ったら負けゲーム」の必勝法を教えてくれるアプリでした。皆さんも小さい頃やった記憶がありませんか?例えば、1度に3つまで数字を言うことができ、交互に数字を言っていき、30を言ったほうが負け、というゲームです。先生方がボスとなって、アプリを使ってボスを倒そうという課題でした。(生徒は必ず先攻だという条件付きで)
1度に3つずつ数字が言える場合、相手が何個数字を言うかに関わらず、必ず「4つ」ずつ数字を進めることができます。また、30の1つ手前の29を自分が言えば良いので、そこから4つずつ戻って「29、25、21…、9、5、1」を言えば勝ちということが分かります。これは「初項が1、公差が4の等差数列」ですね。
ただしボスは数字の●の部分を変えて出題してきます。どんな数字が出てもこの数列を出力するようなアプリを作らなければならない、ということになります。生徒たちは自分たちで戦いながら数列という法則を見つけ、それをプログラムによって求める必要があるわけです。さらに中ボスになると「ゴールは30だけど、何個ずつ言えるかはわからない」状態で戦わなければならず、ラスボスは「ゴールも、1回に言える数字もわからない」状態で戦わなければならない、という風にレベルが上っていきます。
最初手作業で計算していたものをコンピュータに計算させるために、変数や繰り返しといった考え方が必要になるため、初回の課題として、とても良い教材になったと思います。
課題2 BMI測定アプリ
数学的課題の2つ目は「BMI測定アプリ」です。BMIの計算式を最初に示し、任意の値を入力するとBMIが出力されるようにするアプリです。それだけでなく、身長に基づく「適正体重」を出力し、「現在の体重との差」、「肥満の程度」、「肥満の程度を1つ改善するために変化させるべき体重」を出力するように求められています。計算そのものは難しくないのですが、気をつけなければならないことがあります。それは「四捨五入」です。
条件として、BMIは小数第1位まで表示することとなっており、小数第2位を四捨五入する必要があるのですが、これがちょっと考えないと難しいのです。プログラミングに慣れている人であればお気づきでしょうが、使用する言語によって四捨五入に気をつけなければならないのです。code.orgのAppLabはJavaScriptで書かれており、Math.round関数は必ず「小数第1位を四捨五入」するようになっています。Excelのround関数であれば、引数として四捨五入した後の桁数を入力できますが、JavaScriptだとそうはいかないのです。
この場合は「10倍して四捨五入してから10分の1にする」という計算が必要で、ここにたどり着くまでに時間がかかる生徒が多くいました。ただ、ここで引っかかることは数学の先生方も理解されていたようで(ご自身が困った経験があったからだそうです)、このことに注意して授業をされていたのが素晴らしかったと思います。
BMIの値によって出力される値を変化させなければならないので、if文の使い方も学べますし、入力・出力についても学べる良い課題となりました。
課題3 バドミントンのクリア
3つ目の課題は私が担当する物理の課題。オイラー法を用いて物体の運動をシミュレーションする方法を行いました。
オイラー法とは微分方程式の数値的解法の一つで、微小時間において加速度や速度が一定であるとみなして物体の位置を計算します。具体的には微小時間をdtとして
$$v = a \times dt x = v \times dt$$
これをxとyについて繰り返し計算していくことになります。そして加速度に数値や計算式を代入することで、重力による放物運動や単振動を実装することができます。
まずはオイラー法を実装するためのコードを示し、そっくりそのままコーディングしてボールが落ちていくことを確認させました。そして鉛直投げ上げや斜方投射にするにはどうしたらよいかを考えさせました。
最後に加速度=速度×(−1)×定数となるようにプログラムを書き換えて、空気抵抗が表現できることまで伝えた後、課題を示しました。「最も良いバドミントンのクリアの軌道を示しなさい」というものです。
空気抵抗の程度を表す定数値を探し、バドミントンコートとネットをスクリーン幅と実際の幅の比を考慮して描画し、パラメータを変えながら軌道を確認し、コートの奥まで飛ばすための速さと角度を見つけることを目標にしました。
実際の空気抵抗がどうなっているかは分かりませんので、単純化したモデルではありますが、ボールが抵抗を受けながら飛んでいく様子を見て、生徒たちは楽しみながら試行錯誤していました。(結果については出張中だったため確認できていません)
課題4 動物の年齢と人間の年齢
最後の課題は生物専門の先生から。これは来週出題される予定のもので、どんな感じで進んでいくかは予想できていません。
内容は、「動物」か「人間」の年齢を入力し、「動物の種類」を選んでボタンを押すと、年齢が「人間」または「動物」の年齢に換算されて出力されるものです。年齢の換算式は与えられますが、選択すべきものが2つあることで、条件の指定が複雑になっています。
例えば動物の種類が「犬」と「猫」の2つだとすると、入力する数値が1つだけですから、「犬の年齢→人間の年齢」「人間の年齢→犬の年齢」「猫の年齢→人間の年齢」「人間の年齢→猫の年齢」の4パターンのどれなのかを判断する必要があります。おそらくこの程度であればif文を4つ書けば処理できるので、実装は難しくないと思いますが…。
選べる「動物の種類」が増えると話が変わってきます。4種類あれば8パターン、8種類あれば16パターンの計算が必要となり、これを全てif文で書くのは冗長な気がします。
担当する先生から相談されて、連想配列を使うことを提案しました。配列のキーを「動物の種類」にして、値をさらに連想配列にします。その連想配列のキーは「動物→人間」と「人間→動物」にして、それぞれの値を換算した年齢にするわけです。こうするとif文は全く必要なく、選択した条件に応じて結果が出力されます。(入力を受け取った段階でこの配列を宣言するので、全ての計算をしなければならないのが若干ネックですが…)
このように「どうしたらもっと良いプログラムになるか」というのを同僚と議論できる日が来るとは思ってもいませんでしたから、相談を受けた時はとても嬉しかったです。これまでの授業は私が主として動いていましたから、どうなることかと心配していました。しかし自分が担当しなければならない状況をあえて作ったことで、プログラムと向き合い、よりよい解決方法を探って下さったのだと思います。以前の記事で書いた通り「まずはやってもらう」ことで、先生方に浸透した良い例となったと思います。
果たして生徒たちはこの課題をクリアすることができるのでしょうか。来週の授業が楽しみです。
コメント