はじめての CUI プログラム
絵を描かずに,入力と計算と表示だけでプログラムを作ります.
ここまでの 6 回は,ずっとかめに絵を描かせてきました. 今回はかめを休ませて,タートルを 1 行も使わないプログラムを書きます. 画面に出るのは文字だけ,操作はキーボードだけ. このようなプログラムをCUI プログラムといいます.
絵がない代わりに,仕様(しよう)があります. どの課題にも「どんな入力を受け取り,何を計算し,何を表示するのか」が 文章で書いてあります.その文章を読んで,自分でプログラムに翻訳する ——これが,今回の中心になる練習です.実際の仕事では,こうして 「日本語で書かれた注文」からプログラムを起こします.
もう 1 つ,今回は変数の型をきちんと意識します. 絵を描くときは「数」でひとまとめにしていられましたが, 入力と計算だけのプログラムでは, 整数なのか,小数なのか,文字列なのかを取り違えると, そのまま結果が狂います.
- CUI プログラムとは何かを説明できる
input()とprint()だけで,「入力 → 処理 → 出力」の形のプログラムが書ける- 整数(
int)・小数(float)・文字列(str)・真偽値(bool)の4 つの型を区別できる int()・float()・str()で型を変えてから計算・表示できる.型変換に失敗したときのエラーも読める- モジュールとは何かを説明できる.
randomで乱数を作り,毎回結果の変わるプログラムが書ける - 仕様書を読んで,「入力」「処理」「出力」に分けて整理できる
- 仕様どおりに動く CUI プログラムを,自分で組み立てられる
- 課題は「概要」「機能」「エラー処理」「プログラム設計条件」の4 つに分けて書いてあります.まず全部読んでから,書き始めてください.
- 「▶ この課題を開く」を押すと,右側に出発点のプログラムが読み込まれます.入力を受け取るところまでは書いてあるので,計算と表示を自分で書き足してください.
input()を使う課題には,右下のコンソールの入力行にあらかじめ値が入っています.値を書き換えて,何度も実行して確かめてください.- コンソールの入力行を空にして実行すると,実行中に画面で 1 つずつ聞かれます.
- できあがったら「⤓ 保存」で
.pyファイルとして手元に保存します.
while True:(ずっと繰り返す)は書かないでください.
止める手立てがないので,ブラウザごと固まります.
「何回か繰り返す」ときは for i in range(10): のように
回数を決めてください.
「どうなるまで繰り返す」ときは,
while 残高 > 0 and 年 < 50: のように
必ず終わる条件をもう 1 つ付け足してください.
9.1 文字だけで作るプログラム
CUI(Character User Interface)とは,
ユーザへの情報の表示を文字だけで行い,
すべての操作をキーボードで行うユーザインタフェースのことです.
ここまでの回でずっと使ってきた input() と print() が,
そのまま CUI プログラムの道具になります.
| タートルのプログラム | CUI のプログラム | |
|---|---|---|
| 出力 | 画面に絵を描く(fd・lt) | コンソールに文字を出す(print) |
| 入力 | キーやマウス(第 12 章) | キーボードから 1 行(input) |
| 使う道具 | from turtle import * が要る | 何も読み込まなくてよい(乱数のときだけ import random) |
| 向いていること | 形・模様・動き | 計算・判定・集計 |
まずは,いちばん短い CUI プログラムです. 入力を受け取って,そのまま返すだけの「おうむ返し」です.
# おうむ返しのプログラム
print("開始しました")
text = input("好きな言葉を入力してください > ")
print(f"あなたが入力したのは「{text}」ですね")
print("終了しました")
print に注目してください.
今回の課題では,どれも
「開始しました」で始め,「終了しました」で終えることになっています.
絵が出ないプログラムでは,動いたのかどうかが見た目で分かりません.
始まりと終わりを自分で知らせるのは,CUI プログラムの作法です.
このおうむ返しは短いですが,CUI プログラムの骨組みがそのまま入っています. どんなに長い CUI プログラムも,結局は次の 3 つでできています.
- 入力:
input()で,人から値を受け取る - 処理:受け取った値を使って,計算したり条件で分けたりする
- 出力:
print()で,結果を文字にして見せる
おうむ返しには「処理」がほとんどありません.
ここに計算や if を書き足していけば,
BMI 計算にも,占いにも,数あてゲームにもなります.
今回の課題は,すべてこの 3 つを埋める作業だと思ってください.
9.2 ここまでの道具のおさらい
今回の課題で使うのは,第 3 章から第 6 章までに習ったものだけです. 忘れていたら,ここで思い出してください.
| 書き方 | すること | 出てくる回 |
|---|---|---|
input("案内 > ") | キーボードから 1 行受け取る.結果は必ず文字列 | 第 3 章 |
int(input(…)) | 入力を整数として受け取る | 第 3 章 |
float(input(…)) | 入力を小数として受け取る | 第 3 章 |
f"…{x}…" | 文字と数をまぜて表示する | 第 3 章 |
// % | 割った商と余り.お金・個数の計算に使う | 第 3 章 |
int(x * 10 + 0.5) / 10 | 小数第 2 位で四捨五入する | 第 3 章 |
random.randint(a, b) | a 以上 b 以下の整数を 1 つ | 第 3 章 |
if elif else | 条件で処理を分ける | 第 5 章 |
and or not | 条件を組み合わせる | 第 5 章 |
for i in range(n): | n 回繰り返す | 第 6 章 |
break | 繰り返しを途中でやめる | 第 6 章 |
9.2.1 変数の型 — 整数・小数・文字列・真偽値
絵を描いているうちは,変数の中身はほとんど「数」でした. CUI プログラムでは,ここをはっきり区別する必要があります. 変数に入っているデータの種類のことを 型(かた)といいます.
| 型 | 読み | 何を表すか | 書き方の例 |
|---|---|---|---|
int | イント | 整数.人数・個数・年・点数 | 7 -3 2026 |
float | フロート | 小数.身長・体重・利率・平均 | 1.72 0.05 3.0 |
str | ストリング | 文字列.名前・メッセージ | "ももたろう" "開始しました" |
bool | ブール | 真偽値.条件が成り立つかどうか | True False |
4 つめの bool は,第 5 章で習ったものです.
True と False の2 つしか値がありません.
if bmi < 18.5: と書いたときの bmi < 18.5 の部分は,
計算すると True か False になります.
つまり if は,bool 型の値を見て分かれているのです.
型がずれていると,見た目は似ていても結果がまったく違います.
"3" + "4" は "34"(文字をつなげる)ですが,
3 + 4 は 7(足し算)です.
# 型を確かめるプログラム
print("開始しました")
a = 7 # 整数
b = 1.72 # 小数
c = "ももたろう" # 文字列
d = (a > 5) # 真偽値(条件を計算した結果)
print(a, type(a))
print(b, type(b))
print(c, type(c))
print(d, type(d))
print("3 + 4 は", 3 + 4) # 足し算になる
print('"3" + "4" は', "3" + "4") # つながってしまう
print("終了しました")
input() が返すのは,いつでも文字列(str)です.
数を打ち込んだつもりでも,受け取った時点では
"170" という文字の並びでしかありません.
そのまま足し算をすると,つながってしまうか,エラーになります.
そこで,受け取ったあとに型を変えてから使います. 型を変えたいときは,型の名前をそのまま命令として使います.
| 書き方 | すること | 例 |
|---|---|---|
int(x) | 整数に直す.小数部分は切り捨て | int("170") → 170,int(3.9) → 3 |
float(x) | 小数に直す | float("1.72") → 1.72 |
str(x) | 文字列に直す.つなげて表示するときに使う | str(7) → "7" |
sei = int(input("身長を cm で入力してください > ")) # 整数として受け取る
taiju = float(input("体重を kg で入力してください > ")) # 小数として受け取る
namae = input("名前を入力してください > ") # 文字列はそのまま
ただし,どんな文字列でも数に直せるわけではありません.
int() に渡せるのは数として読める文字列だけです.
次の例題は,わざと失敗させてエラーを見るためのものです.
# 型変換が失敗する様子を見るプログラム
print("開始しました")
print(int("170")) # 170 数として読める文字列は整数に直せる
print(float("1.72")) # 1.72 小数も同じ
# ここから下は,わざと失敗させています
# エラーが出るとそこで止まるので,1 行ずつ # を付けたり外したりして試してください
print(int("3.5")) # ← エラー.小数の文字列は int では読めない
print(int("abc")) # ← エラー.数として読めない
print("1" + 1) # ← エラー.文字列と整数は足せない
print("終了しました")
int("3.5") と int("abc") は
ValueError(値がおかしい),
"1" + 1 は
TypeError(型がおかしい)になります.
エラーが出ると,プログラムはその行で止まります.
下の行も見たいときは,上の行を # でコメントにしてから実行してください.
エラーの名前は,どこを直せばよいかの手がかりです.
ValueError なら入力された中身を,
TypeError なら変数の型を疑ってください.
"3.5" のような小数の文字列を整数にしたいときは,
int(float("3.5")) と 2 段階で直します.
try)は第 20 章で扱います.
int() は四捨五入ではなく切り捨てです.
int(3.9) は 4 ではなく 3 になります.
四捨五入したいときは,先に 0.5 を足してから切り捨てます.
小数第 1 位までにしたいなら int(x * 10 + 0.5) / 10 です.
float)には誤差があります.
0.1 を 10 回足しても,ぴったり 1.0 にはなりません.
コンピュータが 2 進法で計算しているためで,Python に限った話ではありません.
お金や個数は整数で扱う,
小数どうしを == で比べないと覚えておいてください.
9.2.2 乱数を出す
10 から 20 までの整数を,実行するたびに違う値で出します.
乱数を使うときは,プログラムの先頭に import random と書きます.
random のように,便利な命令をひとまとめにした箱を
モジュールといいます.
Python には初めからたくさんのモジュールが用意されていて,
import モジュール名 と書くとその箱が使えるようになります.
箱の中の命令を呼ぶときは random.randint(…) のように,
「箱の名前.命令の名前」と書きます.
random. を書き忘れると
NameError(そんな名前は知りません)になるので気をつけてください.
random の箱には randint 以外の道具も入っています.
random.random() は 0.0 以上 1.0 未満の小数を返すので,
if random.random() < 0.3: と書けば
「30% の確率で起こること」が作れます.
いくつか並べたものから 1 つ選ぶ random.choice や,
順番をまぜる random.shuffle もありますが,
これらはリストを習ってから使うので,第 16 章で扱います.
import の 3 つの書き方(from ○○ import △△ など)は
第 20 章で整理します.
# 乱数を出すプログラム
import random
print("開始しました")
d1 = random.randint(10, 20) # 10 以上 20 以下
print(f"1 つめの数は {d1} です")
d2 = random.randint(0, 10) + 10 # こう書いても同じ範囲になる
print(f"2 つめの数は {d2} です")
print("終了しました")
random.randint(10, 20) は
10 以上 20 以下(両端を含む)ですが,
random.randrange(10, 20) は
10 以上 20 未満(20 を含まない)です.
端をどこまで含むかは命令によって違うので,
そのつど確かめる習慣をつけてください.
9.2.3 数を数えながら判定する
for と % を組み合わせると,
「3 の倍数のときだけ何かする」といったことができます.
このあとの課題 7「世界の○○」のもとになる例題です.
# 3 の倍数と 5 の倍数に印をつけながら数える
print("開始しました")
for i in range(1, 16):
kotae = str(i) # 数を文字列にする
if i % 3 == 0:
kotae = kotae + " バカ"
if i % 5 == 0:
kotae = kotae + " 犬っぽく"
print(kotae)
print("終了しました")
if を並べるか elif にするか
if を 2 つ並べて書いているところがみそです.
elif にしてしまうと,15 のように
3 の倍数でも 5 の倍数でもある数のときに,
片方しか付きません.
「どちらも起こりうる」ときは if を並べ,
「どれか 1 つだけ」のときは elif を使います.
身長と体重を受け取ります.どちらも 170.5 のような
小数で入力されます.
____ に入る命令は
int・float・str のどれでしょうか.
print("開始しました")
# 身長は cm,体重は kg.どちらも小数で受け取る
height = ____(input("身長を cm で入力してください > "))
weight = ____(input("体重を kg で入力してください > "))
print(f"身長 {height} cm,体重 {weight} kg ですね")
print("終了しました")
BMI 指数の値で,体型を 4 つに分けます.
18.5 未満=やせ,18.5 以上 25 未満=標準,
25 以上 35 未満=肥満,35 以上=高度肥満です.
____ を埋めてください.
bmi >= 18.5 and bmi < 25 と書かなくてよい理由も考えてみましょう.
bmi = float(input("BMI 指数を入力してください > "))
if bmi ____ 18.5:
print("やせています")
____ bmi < 25:
print("標準的です")
____ bmi < 35:
print("肥満です")
____:
print("高度肥満です")
入力された数まで数え,3 の倍数のときだけ印をつけます.
____ を埋めてください.
range の終わりの値に注意してください.
range(1, n) では n が出てきません.
print("開始しました")
n = int(input("いくつまで数えますか > "))
for i in range(1, ____): # n まで数えたい
kotae = str(i)
if i ____ 3 == 0: # 3 で割った余りが 0 なら 3 の倍数
kotae = kotae + " バカ"
print(kotae)
print("終了しました")
さいころを 1 回振り,出た目が 1・2・3 のときは「当たり」,
それ以外のときは「はずれ」と表示します.
____ を埋めてください.
目は 1 から 6 までです.me == 1 or me == 2 or me == 3 と
書かなくても済む条件を考えてみましょう.
import random
print("開始しました")
me = random.____(1, 6) # 1 以上 6 以下の整数を 1 つ
print(f"さいころの目は {me} です")
if me ____ 3: # 1・2・3 なら当たり
print("当たり")
else:
print("はずれ")
print("終了しました")
9.2.4 文字列を数に変える
名前などの文字列から数を作ると,占いのプログラムが書けます.
Python では ord() という命令で,
1 文字を数(文字コード)に変えることができます.
for c in 文字列: と書くと,
文字列の中身を1 文字ずつ取り出せます.
print(ord("A")) # 65
print(ord("a")) # 97
print(ord("あ")) # 12354
for c in "かめ":
print(c, ord(c))
hash() は占いに使えない
Python には hash() という似た命令がありますが,
文字列に対する hash() は
実行するたびに違う値を返すことがあります
(セキュリティ上の理由でそうなっています).
占いは同じ名前なら必ず同じ結果でなければ興ざめですから,
今回は hash() ではなく ord() を使います.
入力された名前を 1 文字ずつ数に直して足し合わせ, 最後に 0 〜 99 の範囲に収めます. ____ を埋めてください. 「ある範囲に収める」ときに使う演算子は何でしたか.
name = input("名前を入力してください > ")
value = 0
for c in name:
value = value + ____(c) # 1 文字を数に直して足す
print(f"{name} の数は {value} です")
print(f"0 〜 99 に収めると {value ____ 100} です")
9.3 仕様書の読み方
ここから先の課題は,すべて仕様書の形で書いてあります. 4 つの見出しには,それぞれ役割があります.
| 見出し | 何が書いてあるか | 読むときに考えること |
|---|---|---|
| 概要 | そのプログラムが何をするものか,一言で | 誰が,どんなときに使うのか |
| 機能 | 入力・処理・出力の中身.いちばん大事 | 受け取るのは何個か.どの型か.何を計算するのか |
| エラー処理 | 変な入力が来たときにどうするか | 「行っていない」と書いてあれば,考えなくてよい |
| プログラム設計条件 | 作り方の約束ごと | 使う命令が指定されていないか |
- 入力:何を,いくつ,どの型で受け取るか(
int?float? 文字列?) - 処理:受け取った値から何をどう計算するか(式を日本語で書いてみる)
- 出力:何を,どんな文で表示するか
9.4 基本課題
入力を受け取り,計算し,条件で分けて表示する——という CUI プログラムの基本形を身につけます.
■ 概要
このプログラムは,身長と体重の入力を実数で受け付け, その入力をもとに BMI 指数と, その値から評価されたコメントを出力します.
■ 機能
- プログラムの起動時および終了時に,その旨をユーザに伝えるメッセージを出力する.起動時出力:「開始しました」,終了時出力:「終了しました」(適宜変えてよい).
- 身長と体重の入力を受け取り,BMI 指数と,その値から評価されたコメントを出力する.
入力:体重(kg) と身長(cm) の実数値
出力:BMI 指数(小数第 2 位で四捨五入することが望ましい),およびコメント - BMI 指数は体重(kg) を身長(m) の 2 乗で割った数値である(身長の単位に注意.入力は cm なので,100 で割って m に直す).
- BMI 指数から体型を次のように評価し,コメントとする(18.5 未満=やせ,18.5 以上 25 未満=標準,25 以上 35 未満=肥満,35 以上=高度肥満).
■ エラー処理
文字など処理不可能な値が入力されたときの処理は,行っていない.入力欄には素直に数を書くこと.
■ プログラム設計条件
- 入出力は起動したコンソールから行う(CUI プログラムである).
- 身長と体重の入力には
float(input(…))を使用する. - コメントの文面は各自工夫してよい.
int() が切り捨てであることを利用して,
int(bmi * 10 + 0.5) / 10 と書くと小数第 2 位で四捨五入できます.
条件の分け方は虫食い 9-B が答えそのものです.
発展:標準体重(BMI が 22 になる体重)も計算して, 「あと何 kg」と表示してみましょう. 身長を m ではなく cm のまま計算するとどうなるかも,一度試してみてください.
■ 概要
このプログラムは,男女の名前を入力すると, その恋愛成就確率を百分率で判定し,コメント付きで出力します.
■ 機能
- プログラムの起動時および終了時に,その旨をユーザに伝えるメッセージを出力する.起動時出力:「開始しました」,終了時出力:「終了しました」(適宜変えてよい).
- 男女の名前の入力を受け取り,恋愛成就確率をコメント付きで出力する.
入力:男女の名前(姓名をつなげたもの)
出力:恋愛成就確率(0 〜 100%.実数でも整数でもよい),コメント - 成就確率を求める手順は自由でよいが,必ず 0 〜 100 の範囲に収まるようにする.
- コメントも自由でよい.楽しめるように工夫すること.
- 同じ名前を入れたら,何度実行しても同じ結果になること(乱数で決めてはいけない.占いにならないため).
■ エラー処理
文字など処理不可能な値が入力されたときの処理は,行っていない.入力欄には素直に数を書くこと.
■ プログラム設計条件
- 入出力は起動したコンソールから行う(CUI プログラムである).
- 男女の名前の入力には
input(…)を使用する. - 文字列を数に直すには
ord()を使う(9.2.4 を参照).
% 101 とすれば,どんなに大きな数でも 0 〜 100 になります.
「100 より大きい間,10 で割り続ける」といった手もありますが,
% を使えば 1 行で済みます.
発展:名前の長さ(len(name))や,
2 人の名前に同じ文字が含まれるかどうかも混ぜて,
もっと「それらしい」占いにしてみましょう.
相性の段階に応じて,アドバイスの文も変えてみてください.
■ 概要
このプログラムは,あなたの単位取得状況の入力を受け取り, それを評価し,卒業するためのコメントを出力します.
■ 機能
- プログラムの起動時および終了時に,その旨をユーザに伝えるメッセージを出力する.起動時出力:「開始しました」,終了時出力:「終了しました」(適宜変えてよい).
- 経過した学期数と現在取得した単位数の入力を受け取り,その値から評価されたコメントを出力する.
入力:経過した学期数(0 〜 7)の整数値,取得済みの単位数の整数値
出力:今後 1 学期あたりにとらねばならない単位数(CPS:Credit Per Semester),およびコメント - 最終的に取得すべき単位数などの規則は学則に従うものとする(自分の学科の卒業要件単位数を調べて書くこと).
- CPS =(卒業に必要な単位数 − 取得済みの単位数)÷(残りの学期数).4 年間の学期数は 8 とする.
- コメントは自由に考えてよい.
■ エラー処理
文字など処理不可能な値が入力されたときの処理は,行っていない.入力欄には素直に数を書くこと.
■ プログラム設計条件
- 入出力は起動したコンソールから行う(CUI プログラムである).
- 単位数・学期数の入力には
int(input(…))を使用する.
sotsugyo = 124 のように
変数にして先頭に書いておくと,
学科によって数が違っても 1 か所直すだけで済みます.第 3 章でやったとおりです.
8 を入れると,残りの学期数が 0 になり,
0 で割ることになってエラー(ZeroDivisionError)になります.
仕様では「エラー処理は行っていない」ことになっていますが,
if で先に確かめて「もう卒業です」と出すようにできれば上出来です.
発展:1 学期にとれる単位数には上限(履修登録の上限)があります. CPS がその上限を超えていたら「このままでは卒業できません」と警告しましょう. 取得済み単位数が卒業要件を超えている場合の表示も考えてみてください.
9.5 発展課題
ここからは繰り返しが入ってきます. 仕様も長くなりますが,あわてずに「入力」「処理」「出力」に分けて読んでください.
■ 概要
ユーザが計算問題を解くことで脳を鍛えるソフトウェアである. このプログラムは,足し算の計算問題を自動生成して 何問か出題し,そのつど答えあわせをします.
■ 機能
- プログラムの起動時および終了時に,その旨をユーザに伝えるメッセージを出力する.起動時出力:「開始しました」,終了時出力:「終了しました」(適宜変えてよい).
- 足し算の計算問題を生成する.
出力:問題(例:3 + 4 = ?)
各数字の桁数は1 桁の整数である(答えは任意の桁数の整数とする). - 出題し,答えあわせをする.
入力:回答
出力:答えあわせの結果(正解か,不正解か.不正解のときは正答を添える) - 2) と 3) を連続で 10 回行い,最後に正答率を出力する.
■ エラー処理
文字など処理不可能な値が入力されたときの処理は,行っていない.入力欄には素直に数を書くこと.
■ プログラム設計条件
- 入出力は起動したコンソールから行う(CUI プログラムである).
- 回答の入力には
int(input(…))を使用する. - 繰り返しには
for i in range(10):を使う(while True:は使わないこと).
seikai)を,
繰り返しの外で 0 にしておくのを忘れないでください.
中で 0 にすると,毎回リセットされてしまいます.
10 問なので,正答率は 正解数 * 10 でパーセントになります.
発展:足し算だけでなく,引き算・かけ算も乱数で選んで出題する, 2 桁の問題にする,正答率によって「段位」を出す, 何問目でつまずいたかを表示する,などを考えてみましょう.
■ 概要
マイホームローンの返済計算を行うプログラムである. ユーザは家を買うときに利用することを想定する. 家の値段と利率,月々の返済金額を入力として受け取り, 返済が終わるまでにかかる期間と総返済金額を計算し, コメントとともに出力します.
■ 機能
- プログラムの起動時および終了時に,その旨をユーザに伝えるメッセージを出力する.起動時出力:「開始しました」,終了時出力:「終了しました」(適宜変えてよい).
- 家の値段,利率,月々の返済金額を入力として受け取り,返済が終わるまでにかかる期間,総返済金額を計算し,コメントとともに出力する.
入力:家の値段(整数.万円単位だと使いやすい),利率(百分率の実数),月々の返済金額(整数)
出力:かかる期間(○年),総返済金額,コメント - 返済方法は元利均等方式(借入元金と借入利息を合わせて,月々同じ金額を返済する方式)とし,利息は年単位で複利計算を行う.
たとえば 10000 円を利率 5% で借り,月々の返済金額が 100 円の場合,1 年目の返済が終了すると10000 + 500 − 1200 = 9300円の借入元金が残る. - 1 円未満は切り捨てとする(利息は小数で計算して,1 年ごとに
int()で切り捨てる). - コメントは各自工夫してよい(100 万円:ちょっと安すぎる家では? 50 年:長すぎるのでは? など).
■ エラー処理
文字など処理不可能な値が入力されたときの処理は,行っていない.入力欄には素直に数を書くこと.
■ プログラム設計条件
- 入出力は起動したコンソールから行う(CUI プログラムである).
- 家の値段・月々の返済金額の入力には
int(input(…)),利率の入力にはfloat(input(…))を使用する. - 返せない場合は繰り返しが終わらなくなるので,事前に確かめること.また
whileには「50 年まで」のような必ず終わる条件を必ず付け足すこと.
zandaka = int(zandaka * (100 + riritsu) / 100) # 利息がつく(1 円未満切り捨て) zandaka = zandaka - maitsuki * 12 # 1 年ぶん返す
if で確かめておく必要があります.
発展:月単位で計算する, 「あと何年で返し終わるか」を 5 年ごとに途中経過として表示する, 利率を変えると総返済額がどれだけ変わるかを比べる,などを試してみましょう.
■ 概要
このプログラムは「数あてゲーム」である. システムはまず,1 〜 1000 までの整数をランダムに選ぶ(表示しない). ユーザはこの数をなるべく少ない回答で当てるのが目的である. ユーザは推測した数を入力し,システムは数が当たっていたら 当たったことを知らせて終了,外れていたら 大きすぎるのか,小さすぎるのかを知らせて再入力を求めます.
■ 機能
- プログラムの起動時および終了時に,その旨をユーザに伝えるメッセージを出力する.起動時出力:「開始しました」,終了時出力:「終了しました」(適宜変えてよい).
- 整数をランダムに選ぶ.
1 〜 1000 までのランダムな整数を 1 つ選び,画面には出さない. - 回答の入力を受けつけ,答えあわせをする.
プロンプト:「私が選んだ数を当ててみてね」
入力:回答(整数)
正解時:「正解です.おめでとう!」と出力して終了する.
不正解時:「ちがいます」の後,大きすぎるか,小さすぎるかを出力する. - 回答は10 回までとし,10 回で当たらなければ正解を教えて終わる.
■ エラー処理
文字など処理不可能な値が入力されたときの処理は,行っていない.入力欄には素直に数を書くこと.
■ プログラム設計条件
- 入出力は起動したコンソールから行う(CUI プログラムである).
- 回答の入力には
int(input(…))を使用する. while True:は使わないこと.for i in range(10):で 10 回に限り,正解したらbreakで抜ける.
発展:何回で当てたかによって「天才」「まあまあ」などと評価する, 範囲(1 〜 1000)を最初に入力してもらう, 「残りあと何回」を毎回表示する, 入力が範囲の外だったら注意する,などを加えてみましょう.
■ 概要
このプログラムは,芸人のマネをするソフトウェアである. 任意の自然数を受け取り,その数だけ数を数える.
■ 機能
- プログラムの起動時および終了時に,その旨をユーザに伝えるメッセージを出力する.起動時出力:「開始しました」,終了時出力:「終了しました」(適宜変えてよい).
- 自然数の入力を受け取り,その数まで数える.3 の倍数のときにバカになり,5 の倍数のときには犬っぽくなる(数えるごとに改行すること).
- 出力例:
123(;.゚Д゚.;)ノ45^U)┬┬~6(;.゚Д゚.;)ノ7 - 3 がつく数のときもバカになるとなおよい(が,これを作るのは結構難しい).
■ エラー処理
文字など処理不可能な値が入力されたときの処理は,行っていない.入力欄には素直に数を書くこと.
■ プログラム設計条件
- 入出力は起動したコンソールから行う(CUI プログラムである).
- 入力には
int(input(…))を使用する. - 繰り返しには
for i in range(1, n + 1):を使う.
elif ではなく,
if を2 つ並べて書いてください(例題 T-5 を参照).
「3 がつく数」は,1 の位だけなら i % 10 == 3 で調べられます.
10 の位なら i // 10 % 10 == 3 です.
すべての位を調べるには,数を文字列にして
if "3" in str(i): と書く手もあります.
発展:7 の倍数では別のことをする, 100 まで数えても飽きないように途中で合いの手を入れる, 何回バカになったかを最後に集計する,などを加えてみましょう.
■ 概要
このプログラムは,入力された整数を素因数分解し,
得られた素因数をすべて出力します.
60 と入力したら 60 = 2 × 2 × 3 × 5 と表示する,
というものです.
■ 機能
- プログラムの起動時および終了時に,その旨をユーザに伝えるメッセージを出力する.起動時出力:「開始しました」,終了時出力:「終了しました」(適宜変えてよい).
- 整数の入力を受け取り,その数の素因数をすべて出力する.
入力:2 以上の整数
出力:素因数を小さい順に並べたもの - 同じ素因数が何回も出てくるときは,その章数だけ出力する(
8なら2 × 2 × 2,12なら2 × 2 × 3). - 入力された数が素数のときは,その数自身が 1 つだけ出力される(
13なら13).
■ エラー処理
文字など処理不可能な値が入力されたときの処理は,行っていない.入力欄には素直に数を書くこと.
■ プログラム設計条件
- 入出力は起動したコンソールから行う(CUI プログラムである).
- 入力には
int(input(…))を使用する. - 割る数を 2 から 1 つずつ大きくしていき,割り切れるあいだは同じ数で割り続けること.
- 繰り返しには
whileを使う.while True:は使わないこと.割る数が残りの数を超えたら終わる,という条件にする.
- 割る数
waruを2から始める. - 割り切れたら,その
waruは素因数なので書きとめ,残りの数をwaruで割った値に更新する(割る数はそのまま.同じ数で何度でも割れるから). - 割り切れなかったら,割る数を 1 つ大きくする.
- 割る数が残りの数より大きくなったら終わり.
60 でたどってみましょう.
60 ÷ 2 = 30,30 ÷ 2 = 15,
15 は 2 で割れないので割る数を 3 にして 15 ÷ 3 = 5,
5 は 3 でも 4 でも割れず,割る数が 5 になって 5 ÷ 5 = 1.
こうして 2, 2, 3, 5 が得られます.
割り算は //(商)を使ってください.
/ だと答えが小数になってしまいます.
while True: を使わなくてよいのは,このためです.
ただし,大きすぎる数を入れると時間がかかります.
2 から順に試していくので,7 桁の素数などを入れると待たされます.
はじめは 60 や 360 のような 2 〜 3 桁で試してください.
発展:素因数が 1 つだけだったら「この数は素数です」と表示する,
2 × 2 × 2 ではなく 2 の 3 乗 の形でまとめて表示する,
2 から 100 までの数を順に素因数分解して並べる,などを考えてみましょう.
■ 概要
独自の観点で,CUI プログラムを作りなさい. 何を作るかは自由です. ただし,自分で仕様書を書いてから作ること.
■ 機能
- プログラムの起動時および終了時に,その旨をユーザに伝えるメッセージを出力する.起動時出力:「開始しました」,終了時出力:「終了しました」(適宜変えてよい).
- 入力・処理・出力がそろっていること.入力を 1 つ以上受け取り,それを使って何かを計算し,結果を表示する.
- 条件分岐(
if)か繰り返し(for)のどちらかを必ず使うこと. - プログラムの先頭に,自分で書いた仕様書をコメントで入れること(概要・機能・エラー処理・設計条件の 4 つ).
■ エラー処理
処理不可能な値が入力されたときの処理を行うかどうかは,各自で決めて仕様書に書くこと.
■ プログラム設計条件
- 入出力は起動したコンソールから行う(CUI プログラムである).
- 入力には
input(…)・int(input(…))・float(input(…))のいずれかを使用する. while True:は使わないこと.- ファイルの先頭のコメントに,題名・氏名・日付を書くこと.
- おつり計算機:代金と預かり金から,硬貨の枚数を
//と%で求める(出発点のプログラムはこれです) - おみくじ:名前を入れると運勢が出る(
ordを使えば同じ名前で同じ結果になる) - 西暦・和暦の変換:西暦を入れると和暦を返す
- 九九の練習:乱数で問題を出して,10 問答えあわせ(課題 4 の応用)
- 身長から適正体重:いくつかの計算式で比べて表示する(課題 1 の応用)
- アルバイト代の計算:時給と時間と深夜割増から給料を求める
- カロリー計算:食べたものを何個か入力して,合計と運動時間に換算する
- 暦の計算:西暦を入れると,うるう年かどうかを判定する(4 で割り切れ,かつ 100 で割り切れない.ただし 400 で割り切れればうるう年)
9.6 作品にするときのきまりと見直しの観点
どの課題も,仕様を満たしていることがいちばん大事です. そのうえで,次の点を見ます.
| 観点 | 見るところ |
|---|---|
| 仕様の充足 | 「機能」に書かれたことが,すべてできているか |
| 入力の型 | 整数は int(input(…)),小数は float(input(…)) になっているか |
| 変数名 | a・x ではなく,意味の分かる名前がついているか |
| コメント | 先頭に題名・氏名・日付があり,処理の区切りに説明があるか |
| 表示 | f 文字列を使い,読んで意味の分かる文になっているか |
| 独自の工夫 | 仕様にない工夫(コメントの文面,追加の表示,発展課題)があるか |
まとめ
- CUI プログラムは,文字だけで入出力するプログラム.
input()とprint()があれば作れる. - 課題は仕様書の形で与えられる.「概要」「機能」「エラー処理」「プログラム設計条件」を全部読んでから書き始める.
- 仕様を読んだら,「入力」「処理」「出力」の 3 つに分けて整理する.
- 変数の型は
int(整数)・float(小数)・str(文字列)・bool(真偽値)の 4 つ.int()・float()・str()で型を変えられる. - 数として読めない文字列を
int()に渡すとValueError,型の違うものを+でつなぐとTypeErrorになる. input()が返すのは必ず文字列.入力の型を間違えないこと.整数はint(input(…)),小数はfloat(input(…)).int()は切り捨て.小数には誤差があるので,お金や個数は整数で扱う.- モジュールは,便利な命令をまとめた箱.
import randomで箱を開け,random.randint(a, b)のように「箱の名前.命令の名前」で呼ぶ. - 割り切れるあいだ同じ数で割り続けると,素因数分解ができる.割る数か残りの数のどちらかが必ず近づくので,繰り返しはいつか終わる.
- 範囲で分けるときは
if・elif・else.両方起こりうるときはifを並べる. - ある範囲に収めたいときは
%が使える.x % 101は必ず 0 〜 100 になる. while True:は書かない.回数を決めたforか,必ず終わる条件を付けたwhileにする.- 始まりと終わりを
printで知らせるのは,CUI プログラムの作法.
今回の課題は,絵が出ない代わりに,
「書いてあるとおりに作る」「自分で仕様を決める」という,
プログラミングのもう一つの側面を練習するものです.
タートルの回で身につけた if・for・変数は,
そのままここでも働きます.道具は同じで,使い道が違うだけです.
次の回からは,またタートルに戻ります.
今度は絵を動かします.
ontimer という命令を使って
「少し動かして,少し待って,また少し動かす」を繰り返させると,
第 8 章までに描いた絵がアニメーションになります.