14. 小さなプログラムを作る
ここまで学んだことを集めて、成績表、数当て、やることリストを一から作ってみましょう。
この章で学ぶこと
- 作りたいものを小さな部品に分ける方法
- 部品を1つずつ作って実行しながら、少しずつ育てる方法
- 3つの小さなプログラム: 成績表、数当て、やることリスト
プログラムは一度に作りません
最初から最後まで一気に書く人はほとんどいません。たいていはこう作ります。
- 何を作るかを言葉で書いてみる。
- それを小さな部品に分ける。
- いちばん簡単な部品から作って、すぐに実行してみる。
- うまくいったら、次の部品をつなげる。
部品ごとに実行すれば、エラーが出ても今直した数行だけを見ればいいので、見つけやすくなります。この章の例も、段階ごとに実行ボタンを押しながらついてきてください。
1. 成績表を作る
作るもの: 生徒たちの点数を見て、それぞれの評価とクラスの平均、1位を教えてくれるプログラムです。
部品に分ける
- 点数を入れておく → 辞書(7章)
- 点数で評価を決める → 条件文(5章)+ 関数(9章)
- 生徒ごとに出力する → 繰り返し文(8章)
- 平均と1位を求める → 繰り返しながら合計といちばん大きい値を覚えておく
ステップ1: 評価の関数
いちばん小さな部品から作ります。点数を受け取って、評価の文字を返す関数です。作ったら、いくつかの点数で試してみましょう。
〈評価〉を作ろう(『点数』):
もし(『点数』が90以上だ)なら:
「A」を返そう
もしくは(『点数』が80以上だ)なら:
「B」を返そう
もしくは(『点数』が70以上だ)なら:
「C」を返そう
「D」を返そう
(〈評価〉(95))を出力しよう
(〈評価〉(80))を出力しよう
(〈評価〉(42))を出力しよう
A、B、Dが出れば成功です。境目にある値(80のように、ちょうど基準の点数)を必ず入れてみてください。間違いがいちばん隠れやすい所です。
最後の
「D」を返そうの前にそれ以外なら:がなくても大丈夫です。前で返そうに出会うとその場で関数が終わるので、ここまで来たということは70点未満ということです。
ステップ2: 生徒ごとに出力する
今度は点数を辞書に入れて、生徒ごとに繰り返しながらステップ1の関数を使います。
〈評価〉を作ろう(『点数』):
もし(『点数』が90以上だ)なら:
「A」を返そう
もしくは(『点数』が80以上だ)なら:
「B」を返そう
もしくは(『点数』が70以上だ)なら:
「C」を返そう
「D」を返そう
『成績』を{「あおい」: 92, 「そら」: 78, 「はな」: 85, 「りく」: 64}にしよう
『成績』の『名前』ごとに繰り返そう:
『点数』を『成績』の『名前』にしよう
枠「{『名前』}: {『点数』}点 ({〈評価〉(『点数』)})」を出力しよう
ステップ3: 平均と1位
繰り返しながら、2つのことを覚えておきます。
『合計』: 点数をどんどん足していきます。回り終えたら人数で割れば平均です。『最高点』と『一位』: 今まで見た点数より大きければ入れ替えておきます。
〈評価〉を作ろう(『点数』):
もし(『点数』が90以上だ)なら:
「A」を返そう
もしくは(『点数』が80以上だ)なら:
「B」を返そう
もしくは(『点数』が70以上だ)なら:
「C」を返そう
「D」を返そう
『成績』を{「あおい」: 92, 「そら」: 78, 「はな」: 85, 「りく」: 64}にしよう
『合計』を0にしよう
『人数』を0にしよう
『最高点』を0にしよう
『一位』を「」にしよう
「===== 成績表 =====」を出力しよう
『成績』の『名前』ごとに繰り返そう:
『点数』を『成績』の『名前』にしよう
枠「{『名前』}: {『点数』}点 ({〈評価〉(『点数』)})」を出力しよう
『合計』に『点数』を足そう
『人数』に1を足そう
もし(『点数』が『最高点』より大きい)なら:
『最高点』を『点数』にしよう
『一位』を『名前』にしよう
「==================」を出力しよう
枠「クラスの平均: {『合計』 / 『人数』}点」を出力しよう
枠「1位: {『一位』} ({『最高点』}点)」を出力しよう
『人数』を別に数えるのは、辞書には『長さ』がないからです(7章)。
もっとやってみる: 生徒をもう1人入れてみてください。コードを1つも直さなくても、成績表が自動で長くなります。これは、繰り返し文と関数に分けて作ったおかげです。
2. 数当てゲーム
作るもの: コンピューターが1から100までの数を1つ決めると、ユーザーが当たるまで予想します。外れるたびに「もっと大きいです」/「もっと小さいです」と教え、当たったら何回で当てたかを教えます。
部品に分ける
- 答えを決める →
【乱数】の〈整数〉(11章) - 予想を受け取る →
入力してもらおう(2章) - 比べて教える → 条件文
- 当たるまで続ける →
間繰り返そう(8章) - 回数を数える → 繰り返すたびに1を足す
ステップ1: 入力なしでルールから
入力を受け取ると、実行するたびに自分で打たなければならないので、試すのが面倒です。そこで答えを固定して、予想もリストにあらかじめ書いておき、ルールから確かめます。
『答え』を42にしよう
『予想たち』を【50, 25, 37, 43, 40, 42】にしよう
『回数』を0にしよう
『予想たち』の『予想』ごとに繰り返そう:
『回数』に1を足そう
もし(『予想』が『答え』より小さい)なら:
枠「{『予想』}: もっと大きいです!」を出力しよう
もしくは(『予想』が『答え』より大きい)なら:
枠「{『予想』}: もっと小さいです!」を出力しよう
それ以外なら:
枠「{『予想』}: 正解!{『回数』}回で当てました。」を出力しよう
繰り返しを終わろう
『予想たち』の数字を変えながら、「もっと大きいです」と「もっと小さいです」が正しく出るか確かめてみてください。ルールが合っていれば、あとは本当の入力に変えるだけです。
ステップ2: 本当のゲーム
変わった所は3つです。
- 答えを
〈整数〉(1, 100)で選びます。 - リストの代わりに
間繰り返そうで、当たるまで回ります。『当たった』が偽の間、続けます。 - 予想を
【数字】で入力してもらおうで受け取ります。
【乱数】から〈整数〉を持ってこよう
『答え』を〈整数〉(1, 100)にしよう
『回数』を0にしよう
『当たった』を偽にしよう
「1から100までの数を1つ決めました。当ててみてください!」を出力しよう
(『当たった』が偽と同じだ)間繰り返そう:
「予想: 」を続けて出力しよう
『予想』を【数字】で入力してもらおう
『回数』に1を足そう
もし(『予想』が『答え』より小さい)なら:
「もっと大きいです!」を出力しよう
もしくは(『予想』が『答え』より大きい)なら:
「もっと小さいです!」を出力しよう
それ以外なら:
枠「正解!{『回数』}回で当てました。」を出力しよう
『当たった』を真にしよう
実行ボタンを押すと、結果の欄に入力欄ができます。半分ずつに分けながら(50 → 25か75 → …)予想すれば、7回以内に必ず当てられます。
ステップ3: 丈夫にする
今は、数字の代わりに文字を入れるとプログラムがエラーで止まります。10章の安全網で囲めば、もう一度尋ねられます。1から100の外の数もはじいてみましょう。
【乱数】から〈整数〉を持ってこよう
『答え』を〈整数〉(1, 100)にしよう
『回数』を0にしよう
『当たった』を偽にしよう
「1から100までの数を1つ決めました。当ててみてください!」を出力しよう
(『当たった』が偽と同じだ)間繰り返そう:
「予想: 」を続けて出力しよう
『予想』を0にしよう
とりあえずやってみよう:
『予想』を【数字】で入力してもらおう
発生したら:
「数字で入力してください。」を出力しよう
もし(『予想』が1より小さい)または(『予想』が100より大きい)なら:
「1から100までの数だけです。」を出力しよう
それ以外なら:
『回数』に1を足そう
もし(『予想』が『答え』より小さい)なら:
「もっと大きいです!」を出力しよう
もしくは(『予想』が『答え』より大きい)なら:
「もっと小さいです!」を出力しよう
それ以外なら:
枠「正解!{『回数』}回で当てました。」を出力しよう
『当たった』を真にしよう
『予想』を安全網の前で先に0にしておいたことに注目してください。文字を入れて入力に失敗すると、『予想』は0のまま残るので、「1から100までの数だけです。」へ進みます。発生したら:のまとまりの中で初めて作った名札は、そのまとまりが終わると消えてしまうので、外で使う名札は外で先に作っておくのが安全です。間違った入力は『回数』に数えません。
3. やることリスト
作るもの: やることを追加して、終わったことに印を付けて、リストを見せるプログラムです。
部品に分ける
- やること1つ = 「内容」と「終わったかどうか」を一緒に入れた辞書
- やること全体 = その辞書を入れたリスト
- 追加する/終わらせる/見せる = それぞれ関数1つずつ
ステップ1: データの形を決める
やること1つは、こんな形です。
『やること』を{「内容」: 「買い物」, 「完了」: 偽}にしよう
(『やること』の「内容」)を出力しよう
(『やること』の「完了」)を出力しよう
こんな辞書をリストにいくつも入れれば、やることリストになります。何をどんな形で入れるかを先に決めておくと、残りのコードが楽になります。
ステップ2: 3つの関数
『リスト』を【】にしよう
〈追加する〉を作ろう(『内容』):
『リスト』に{「内容」: 『内容』, 「完了」: 偽}を追加しよう
枠「追加しました: {『内容』}」を出力しよう
〈終わらせる〉を作ろう(『番号』):
もし(『番号』が1より小さい)または(『番号』が『リスト』の『長さ』より大きい)なら:
枠「{『番号』}番のやることはありません。」を出力しよう
返そう
『やること』を『リスト』の『番号』番目にしよう
『やること』の「完了」を真にしよう
枠「終わりました: {『やること』の「内容」}」を出力しよう
〈見せる〉を作ろう():
もし(『リスト』の『長さ』が0と同じだ)なら:
「やることはありません。」を出力しよう
返そう
『番号』を1にしよう
『リスト』の『やること』ごとに繰り返そう:
『印』を「[ ]」にしよう
もし(『やること』の「完了」)なら:
『印』を「[v]」にしよう
枠「{『番号』}. {『印』} {『やること』の「内容」}」を出力しよう
『番号』に1を足そう
〈見せる〉()を実行しよう
〈追加する〉(「買い物」)を実行しよう
〈追加する〉(「宿題」)を実行しよう
〈追加する〉(「部屋の掃除」)を実行しよう
〈終わらせる〉(2)を実行しよう
〈終わらせる〉(9)を実行しよう
〈見せる〉()を実行しよう
注目してほしい所:
- 関数の中で、外の
『リスト』を読んだり変えたりできます(9章)。 『やること』を『リスト』の『番号』番目にしてから『やること』の「完了」を変えると、リストの中のその辞書も変わります。 辞書はコピーされず、同じものを一緒に指しているからです(7章)。返そうだけを書くと、何も返さずにその場で関数を終えます。間違った番号のときに、それ以上進まないように使いました。
ステップ3: 命令で動かす
今度は、ユーザーが追加 牛乳を買う、完了 1、見る、終わりのような命令を入力するようにします。命令の文字を〈分割〉(「 」)で分けると、最初の単語が命令です(4章)。関数はステップ2と同じです。
『リスト』を【】にしよう
〈追加する〉を作ろう(『内容』):
『リスト』に{「内容」: 『内容』, 「完了」: 偽}を追加しよう
枠「追加しました: {『内容』}」を出力しよう
〈終わらせる〉を作ろう(『番号』):
もし(『番号』が1より小さい)または(『番号』が『リスト』の『長さ』より大きい)なら:
枠「{『番号』}番のやることはありません。」を出力しよう
返そう
『やること』を『リスト』の『番号』番目にしよう
『やること』の「完了」を真にしよう
枠「終わりました: {『やること』の「内容」}」を出力しよう
〈見せる〉を作ろう():
もし(『リスト』の『長さ』が0と同じだ)なら:
「やることはありません。」を出力しよう
返そう
『番号』を1にしよう
『リスト』の『やること』ごとに繰り返そう:
『印』を「[ ]」にしよう
もし(『やること』の「完了」)なら:
『印』を「[v]」にしよう
枠「{『番号』}. {『印』} {『やること』の「内容」}」を出力しよう
『番号』に1を足そう
「命令: 追加 (内容) / 完了 (番号) / 見る / 終わり」を出力しよう
『続ける』を真にしよう
(『続ける』が真と同じだ)間繰り返そう:
「> 」を続けて出力しよう
『入力』を入力してもらおう
『単語たち』を『入力』の〈分割〉(「 」)にしよう
『命令』を『単語たち』の1番目にしよう
『残り』を『入力』の〈切り取り〉(『命令』の『長さ』 + 2, 『入力』の『長さ』)にしよう
もし(『命令』が「追加」と同じだ)なら:
〈追加する〉(『残り』)を実行しよう
もしくは(『命令』が「完了」と同じだ)なら:
とりあえずやってみよう:
〈終わらせる〉(〈数字に〉(『残り』))を実行しよう
発生したら:
「番号は数字で書いてください。」を出力しよう
もしくは(『命令』が「見る」と同じだ)なら:
〈見せる〉()を実行しよう
もしくは(『命令』が「終わり」と同じだ)なら:
「さようなら!」を出力しよう
『続ける』を偽にしよう
それ以外なら:
「知らない命令です。」を出力しよう
『残り』は、命令の後ろの文字すべてです。追加 牛乳を買うなら、「追加」(2文字)の次のスペース1つを飛ばして3文字目から最後まで、つまり牛乳を買うになります。〈分割〉で分けた単語をもう一度つなげなくていいので便利です。
行き詰まったときに試す方法
- 途中の値を出力する: おかしいと思う名札を、その場で
出力しようで表示してみてください。思っていた値と違う所が、問題の始まった所です。 - もっと小さくする: コードの一部を消したり
(参考)でふさいだりして(行の前に(参考)を付けると、その行は実行されません)、問題が残るいちばん小さな形を探します。 - 入力を固定する: 数当てのステップ1のように、入力の代わりに決まった値で試せば、同じ状況を何度でも見直せます。
- エラーメッセージを読む: 何行目か、どんな種類かを教えてくれます。種類ごとの意味は付録. よく出会うエラーにあります。
まとめ
| 段階 | すること |
|---|---|
| 言葉で書く | 何を作るかを1、2文で |
| 部品に分ける | データを何に入れるか、どんな関数が必要か |
| 小さく始める | いちばん簡単な部品から、作るたびに実行 |
| 入力はあとで | 決まった値でルールを確かめてから、入力に変える |
| 丈夫にする | 間違った入力を安全網ともしではじく |
練習問題
1. 成績表に最下位(いちばん低い点数)も出力してみましょう。最初の値を何にすればいいか考えてみてください。
答えの例
最低点の最初の値は、どの点数よりも大きくなければなりません。点数は100点までなので、101から始めればいいんです。
『成績』を{「あおい」: 92, 「そら」: 78, 「はな」: 85, 「りく」: 64}にしよう
『最低点』を101にしよう
『最下位』を「」にしよう
『成績』の『名前』ごとに繰り返そう:
もし(『成績』の『名前』が『最低点』より小さい)なら:
『最低点』を『成績』の『名前』にしよう
『最下位』を『名前』にしよう
枠「いちばん低い点数: {『最下位』} ({『最低点』}点)」を出力しよう
2. 数当てのステップ1のコードに、「10回で当てられなければ終わり」というルールを足してみましょう。予想のリストを【1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 42】にして、10回目で失敗!答えは42です。が出ればOKです。
答えの例
『答え』を42にしよう
『予想たち』を【1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 42】にしよう
『回数』を0にしよう
『予想たち』の『予想』ごとに繰り返そう:
『回数』に1を足そう
もし(『予想』が『答え』と同じだ)なら:
枠「正解!{『回数』}回で当てました。」を出力しよう
繰り返しを終わろう
もし(『回数』が10と同じだ)なら:
枠「失敗!答えは{『答え』}です。」を出力しよう
繰り返しを終わろう
もし(『予想』が『答え』より小さい)なら:
枠「{『予想』}: もっと大きいです!」を出力しよう
それ以外なら:
枠「{『予想』}: もっと小さいです!」を出力しよう
正解の確認を先にしないと、10回目に当てた場合も「正解!」になりません。
3. やることリストに、残りのやることの数を数える〈残りの数〉関数を作ってみましょう。ステップ2の例の最後で呼ぶと2が出るはずです。
答えの例
『リスト』を【{「内容」: 「買い物」, 「完了」: 偽}, {「内容」: 「宿題」, 「完了」: 真}, {「内容」: 「部屋の掃除」, 「完了」: 偽}】にしよう
〈残りの数〉を作ろう():
『数』を0にしよう
『リスト』の『やること』ごとに繰り返そう:
もし(『やること』の「完了」が偽と同じだ)なら:
『数』に1を足そう
『数』を返そう
(〈残りの数〉())を出力しよう
ここまで来たら、カナデでかなり多くのものが作れます。似たものをいくつも扱うプログラムが大きくなってきたら、オブジェクト指向がコードの整理に役立ちます。ファイルを読み書きしたり、実行ファイルにまとめたりしたいなら、Hanaランタイムを見てください。