ゲーム開発で学ぶメリット
ゲーム開発を通してプログラミングの技術とアルゴリズムを学びます。「なぜゲーム開発なの?」という疑問に対する答えはずばり、ゲームを開発しながら学べば、楽しみながらアルゴリズムに関する知識を身に付けることができるからです。
アルゴリズム
アルゴリズムとは、規則やルールに従って繰り返す動きのことです。プログラミングの設計で非常に重要な考え方です。
アルゴリズムやプログラミングという言葉だけを聞くと、「難しそう」「手を出しにくい」と考える方もいらっしゃるでしょう。一方、ゲーム開発と聞くと、「難しそうだけれど興味はある」「自分にできるならやってみたい」とお考えになる方が多いと思います。
もちろん高度なゲームを作るには高い技術力が必要であり、そのようなプログラミング技術は一朝一夕には身に付きません。ですが簡単なゲームであれば、プログラミングの基礎知識を学べば誰もが作れるようになります。
シンプルなミニゲームを制作し、プログラミングに慣れながら初歩的なアルゴリズムを学びます。そして徐々に高度な内容に進んでいきます。
楽しみながら学ぶことでアルゴリズムやプログラミング技術を自然と身に付けることができます。楽しいことなら長続きすることは言うまでもなく、学習を継続的に行うことができれば、カは着実に伸びていきます。
初学者にやさしいPython
Python は各種の命令が判りやすく、記述の仕方がシンプルで、短いプログラムで処理を記述できます。Python を用いれば気軽にプログラムを組んで動作を確認できるのです。Python は初心者がプログラミングやアルゴリズムを学ぶのにうってつけだと確信をもって言えます。
Python でプログラミングの基礎を身に付ければ、C系言語やJavaなどの言語にも挑戦しやすくなります。ハードもソフトも高度複雑化の一途をたどる情報処理の世界で、Pythonという学びやすい言語の人気が高まり、広く普及したのです。
私は子供のときからコンピュータ・ゲームが大好きです。自分でゲームソフトを作りたいという気持ちからプログラミングを学び始めました。最初のうちは思うようにゲームを作れるようになりませんでした。ですが諦めずにコツコツ学ぶうちに、やがて簡単なミニゲームが作れるようになりました。そしてプログラミングを続けると、少しずつ複雑なゲームが作れるようになっていきました。
技術が未熟なうちは何でこんなこともできないのだろうと考えたこともありますが、プログラミングを学んだ過程全体を思い返せば、楽しみながら学ぶことができました。それは自分の力でオリジナルゲームを作るという夢があったからです。そのような気持ちでプログラミングを続けられたことは幸せだったと思います。
みなさんの中にはプログラミングを習得しようと、すでに苦労された方もいらっしゃるでしょう。Python の入門書を読んだけれど自分のものになった気がしないという方もおられるのではないでしょうか。
「継続は力なり」ということわざの通り、続けるうちにカが付いてきます。技術力がぐっと伸びたと自信を持っていただけるはずです。
IDLEの使い方
Python 付属のIDLE という統合開発環境を使って、プログラムの入力と動作確認を行います。統合開発環境とはソフトウェア開発を支援するツールのことをいいます。
上のURLにアクセスしてインストールしてください。
使い慣れたテキストエディタや統合開発環境でPython のプログラミングをしている方は、もちろんそれを、そのままお使いいただいてかまいません。その場合はこの節は飛ばして先へ進みましょう。
IDLEのシェルウィンドウとエディタウィンドウ
IDLEの使い方を説明します。IDLEを起動すると次のような画面になります。この画面をShell ウィンドウといいます(以下、カタカナで「シェルウィンドウ」とします)。
Hellloプログラムを実行しよう
手始めに文字列を出力する print()命令を記述して動作を確認します。
FileからNewFileを開きます。
そして開いたファイルに次のように入力します。
print()命令
print(s)
プログラムを入力したら、エディタウィンドウのメニューバーにある【File】 → 【SaveAs…】を選び、適切なファイル名を付けて保存します。一度保存すれば、その後は【File】【Save】 を選ぶか、 Ctrl+Sキーで上書き保存できます。
プログラムを保存したら、エディタウィンドウのメニューバーの【Run】→【Run Module】
を選んで実行します。F5]キー(ファンクションボタンがあるキーボードでは[Fn]+[F5])でも実行できます。
このプログラムは print()で文字列を出力しています。文字列を扱うときは、文字列の前後をダブルクォート( ” )でくくります。Pythonではシングルクォートを用いることもできますが、今回は基本的にダブルクォートで統一します。
IDLEの使い方をまとめると、次のようになります。
1、IDLEを起動するとシェルウィンドウが開く
2、エディタウィンドウを開いて、プログラムを入力する
3、ファイル名を付けてプログラムを保存する
4、Run Module で実行し、シェルウィンドウに出力される結果を確認する
では、もう一度やってみましょう。
IDLEを起動して、メニューバーの【File】 → 【New File] を選び、エディタウィンドウ(テキストエディタ)を開きましょう。
エディタウィンドウに次のプログラムを入力してください。1行でできたプログラムです。
入力したら名前を付けて保存し、メニューバーの【Run】 →【Run Module】
を選んで実行しましょう。
print.py
実行結果
プログラミングを始めよう!
正しく動作しないときは、print() にスペルミスがないか確認してください。
プログラミングでは大文字と小文字を区別するので、例えば、print のPを大文字にしたらエラーになって動きません。
変数の値を出力してみよう
次は変数の値を出力するプログラムで、print() 命令の使い方に慣れていきます。変数とは数や文字列を入れる箱のようなものです。
次のプログラムを入力して名前を付けて保存し、実行して動作を確認しましょう。
hensu.py
print(a)
実行結果
100
このプログラムは1行目で変数aに数を代入し、2行目でその値を出力しています。
input()命令を使ってみる
Pythonでは input() という命令で文字列を入力します。次のプログラムで input()の使い方を確認します。
このプログラムを実行すると、シェルウィンドウに「あなたの名前は?」と表示され、カーソルキーが点滅します。そこに何か文字列を入れて Enterキー(Macは、returnキー)を押すと、Pythonが「○○さん、名前を教えてくれてありがとう」と返します。
name.py
print(name+”さん、名前を教えてくれてありがとう“)
input()命令で入力した文字列を変数に代入し、文字列を+でつなぎ出力しています。
実行結果
あなたの名前は? HaChi
HaChiさん、名前を教えてくれてありがとう
変数 = input(メッセージ)と記述すると、シェルウィンドウにメッセージが出力され、入力を受け付ける状態になります。何かを入力して「Enterキー」を押すと、入力した文字列が変数に代入されます。
2行目では、変数name の中身と、「さん、名前を教えてくれてありがとう」という文字列を、プラスの記号でつないで出力しています。Python では文字列同士を+を用いてつなぐことができます。
このプログラムでは変数名を name としています。変数名はa、s、xなどのアルファベット1文字だけでなく、名付け方のルールを守れば、任意の名称にすることができます。
printと inputの使い方を覚えておいてください。
input()で半角数字も入力できるけど、Pythonのinput() は数を入力しても文字列として扱われます。
input()で入力した文字列を数にするには、int() やfloat() という命令で整数や小数に変換します。
プログラミングの記述ルール
コンピュータのプログラムにはいくつかの記述ルールがあり、それを守る必要があります。ここでPythonの主なルールを説明します。一度に覚えることは難しいかもしれないので、一通り目を通したら先へ進み、実際にプログラムを入力しながら身に付けていきましょう。
①プログラムは半角文字で入力し、大文字、小文字を区別する
②文字列を扱うときはダブルクォートかシングルクォート)でくくる
変数に文字列を代入する print() で文字列を出力するときなど、前後を ” か ’ でくくります。
③スペースの有無について[その1]
変数の宣言、値の代入、命令の()内の半角スペースは、あってもなくてもかまいません。
④スペースの有無について[その2]
命令の後ろに必ず半角スペースを入れる箇所があります。
if、for、rangeなどの命令を他のアルファベットにくっ付けてしまうと、Python はそれらが命令であると判らなくなります。
⑤プログラムの中にコメントを入れられる
コメントとはプログラム中に書くメモのことです。難しい命令の使い方や、処理の内容をコメントとして記しておくと、プログラムを見直すときなどに役に立ちます。Pythonでは#を用いてコメントします。
#以降、改行するまでの記述が実行時に無視されます。
例えば #print(“こんにちは“)とすると、print() 命令が実行されなくなります。これをコメントアウトするといいます。実行したくない命令を残しておきたいときにもコメントアウトを用いてください。
変数
変数で数や文字列を扱う方法を学びます。
変数とは
変数とはコンピュータのメモリ上に用意された、データを入れる箱のようなものです。次の図はxという名の箱(変数)に 10 という数を、sという箱に Python という文字列を代入するイメージです。
hensu.py
s = “Python”
print(“x の値は“, x)
print(“s の値は“, s)
意味
変数xに値を代入
変数sに値を代入、
「xの値は」という文字列と、xの値を出力
「sの値は」という文字列と、sの値を出力
実行結果
Xの値は 10
sの値は Python
このプログラムは変数xとsに値を代入し、それらの値を出力しています。Pythonのprint()命令は()の中に複数の文字列や変数をコンマで区切って記すことができます。
変数名の付け方
変数はプログラムを組む人が名称を決めて用意します。変数名はアルファベット、数字、_アンダースコア)を組み合わせて付けます。変数名の付け方には次のルールがあります。
・アルファベットとアンダースコア(_)を組み合わせ、任意の名称にできる。
例 score = 10000 my name=”Python”
数字を含めることができるが、数字から始めてはいけない
○ data1 = 20 × 1data = 20
予約語は使えない
例 × if = 0 × for = 5
予約語とは、コンピュータに基本的な処理を命じるための語です。
Pythonには、if elif else and or for while break continue def import False True などの予約語があります。
Python の変数名は小文字で付けることが推奨されております。ただし理由があるなら大文字を用いてかまいません。大文字と小文字は区別されるので、例えば book と Book は別の変数になります。
変数の値を変更する
Pythonではイコール() を用いて変数に最初の値(初期値)を代入した時点から、その変数が使えるようになります。これを変数の宣言といい、値を入れる=を代入演算子といいます。
変数の値はいつでも入れ直すことができます。変数 = の後に計算式を記述して値を変更す
ることもできます。
変数宣言時の初期値を、別の値に変更するプログラムを確認します。
hensu2.py
print(“nの初期値“,n)
n=n+20
print(nに20を足すと”、n,”になる”)
n=500
print(“nに新たな“, n,”を代入”)
意味
nという変数を宣言し、初期値を代入
nの値を出力
nの値に20を足し、nに代入
nの値を出力
nに新たな値を代入
nの値を出力
実行結果
nの初期値 10
nに20を足すと30 になる
nに新たな500 を代入
解説
1行目で変数nを宣言し、初期値を代入して、2行目でその値を出力しています。
3行目ではnの値に20を足したものをnに代入し、4行目でその値を出力しています。
5行目でnに新たな値を代入し、6行目でその値を出力しています。
プログラミング言語のイコールは変数に値を代入するために用いるのですね。
数学で左右の式が等しいという意味で使うイコールとは違います。
演算子について
hensu2.pyの3行目の n = n + 20 は、「nに 20を足した値をnに代入する」という意味です。これを n += 20 と記述することもできます。
足し算、引き算、掛け算、割り算を行う記号を演算子といいます。掛け算は*(アスタリスク)、割り算は/(スラッシュ)で記述します。
四則算の演算子
足し算 +
引き算 –
掛け算 *
割り算 /
これらの他に、累乗を求める演算子、割り算の商を求める演算子、割り算の余り(剰余)を求める演算子があります。
累乘 **
割り算の商 //
割り算の余り %
商は 20//18 で求められる
余りは 20%8 で求められる
文字列⇔数の変換
int() と float)という命令で文字列を数に変換できます。int( ) は文字列や小数を整数にfloat( ) は文字列や整数を小数にします。
int() の使い方を確認します。文字列を整数に変えるプログラムで、出力される777777は文字列、1554が数になります。
print(“文字列の足し算“, s + s)
i = int(s)
print(“数の足し算“, i+i )
解説
変数sに文字列777を代入
sとsの値を+でつないで出力
sの値を整数に変換して変数iに代入
iとiの値を+で足して出力
実行結果
文字列の足し算777777
数の足し算 1554
数を文字列に変換するには str()命令を用います。その使い方を確認します。
mojiretu.py
s=“円周率は” + str(f)
print(s)
意味
変数を宣言し、小数を代入
「円周率は」と、文字列にしたfの値をつなぎ、sに代入の値を出力
実行結果
円周率は3.14159
解説
「円周率の値は」という文字列と、3.14159 という数をつなぐには、2行目のように str()命令を用います。 s = “円周率は” + f と記述するとエラーになるので注意しましょう。
if文の書式
if を用いて記述する処理をif文といいます。Python の if文は、次のように記述します。
Pythonのif文
if n < 0
print(“nの値は負の数です“)
if と条件式の間に半角スペースを入れます。
条件成立時に行う処理を字下げ(インデント)して記述します。字下げした部分はブロックと呼ばれる“処理のまとまり”になります。Python には字下げによりブロックを構成する決まりがあります。
Python の字下げは、通常、半角スペース4文字分とします。
if を用いたプログラム
if文を記述したプログラムを確認します。
jouken.py
if n>0:
print(“nは0より大きい”)
if n<0:
print(“nは0より小さい”)
if n==0:
print(“nの値は0”)
意味
nが0より大きいなら
「nの値は0より大きい」と出力
nが0より小さいなら
「nの値は0より小さい」と出力
nが0なら
「nの値は0」と出力
実行結果
nの値は0
解説
1行目で変数nに0を代入しています。2行目のn>0と、4行目のn<0 という条件式は成り立たず、6行目のn==0 という条件式が成り立ちます。そのため、7行目の処理が実行されます。変数がある数と等しいかを調べるには、6行目のようにイコールを2つ並べて記述します。
このプログラムの1行目をn = -10 とすると、どうなると思いますか?
2行目のn>0は成り立たず、4行目のn<0 が成り立って、「nの値は0より小さい」と出力されるのです。
条件式について
条件式の書き方を覚えましょう。条件式は次のように記述します。
条件式
a == b aとbの値が等しいかを調べる
a !=b aとbの値が等しくないかを調べる
a>baはbより大きいかを調べる
a<b aはbより小さいかを調べる
a >= b aはb以上かを調べる
a <= b aはb以下かを調べる
Pythonでは条件式が成り立つときはTrue、成り立たないときはFalse になります。Trueと False は論理型と呼ばれる値です。ここではif文は条件式がTrueのとき、ブロックに記述した処理が行われると頭に入れておきましょう。
条件分岐はの他に、if else と、if eliff else という書き方があります。それらを順に見ていきます。
if else
if ~ else という記述で条件式が成り立たったときと、成り立たなかったときに、別の処理を行うことができます。
if_2.py
if n > 0:
print(“nは0より大きな値“)
else:
print(“nは0以下の値“)
意味
変数nに値を代入
nの値が0より大きいなら「nは0より大きな値」と出力
そうでなければ「nは0以下の値」と出力
実行結果
nは0以下の値
このプログラムは1行目でnに負の数を代入しており、2行目の条件式は成り立たず、elseのブロックに記述した5行目が実行されます。
elseを用いるときは、else の後ろのコロンを忘れないようにしましょう。
elif.py
if n = 0 :
print(“nは0です“)
elif n > 0:
print(“nは正の数です“))
else:
print(“nは負の数です“)
意味
nに値を代入
nが0なら
「nは0です」と出力
そうでなく0より大きいなら
「nは正の数です」と出力
いずれの条件も成り立たないなら
「nは負の数です」と出力
実行結果
nは正の数です
1行目でnに1000 を代入したので、4行目の条件式が成り立ち、5行目が実行されます。
このプログラムは elf を1つだけ記述しましたが、if ~elif ~ … ~elif~ elseというように、elifを2つ以上記述し、複数の条件を順に判定できます。
andとor
and や orを用いて if文に複数の条件式を記述できます。and は“かつ”、orは“もしくは”の意味です。and とorを用いたプログラムを順に確認します。
if_and.py
y=2
if x>0 and y>0:
print(“変数xとyはどちらも正の値“)
意味
変数xに値を代入
変数yに値を代入
xが0より大きく、かつ、yが0より大きいなら「変数xとyはどちらも正の値」と出力
実行結果
変数xとyはどちらも正の値
解説
x、yともに0より大きな数を代入したので、3行目の and を用いた条件式が成り立ち、4行目が実行されます。xやyを0や負の数にすると3行目が成り立たなくなり、何も出力されないことを確認してください。
if_or.py
w=0
if v==0 or w==0:
print(“vとwのどちらかは0″)
意味
変数vに値を代入
変数wに値を代入
vが0、もしくは、wが0なら「vとwのどちらかは0」と出力
実行結果
vとwのどちらかは0
解説
vに 10、wに0を代入しており、3行目の or を用いた条件式が成り立つので、4行目が実行されます。vとw ともに0以外の数を代入すると、3行目が成り立たなくなり、何も出力されないことを確認しましょう。
繰り返し
繰り返しとは、コンピュータに一定回数、反復して処理を行わせることです。
繰り返しを理解する
繰り返しは for や while という命令で行います。繰り返しを言葉で表すと、次のようになります。
・forを使った繰り返し → 変数の値をある範囲で変化させ、その間、処理を繰り返す。
・whileを使った繰り返し → ある条件が成り立つ間、処理を繰り返す。
for文の書式
forを用いて記述した繰り返しをfor文といいます。
range() という命令で変数の値の範囲を指定します。range() には次の書き方があります。
range(繰り返す回数)
変数の値は0から始まり、指定回数、繰り返す
range(初期値, 終値)
変数の値は初期値から始まり、1ずつ増えながら、終値の1つ手前まで繰り返す
range(初期値, 終値,いくつずつ変化させるか)
初期値から終値の1つ手前まで指定の値ずつ変数を変化させながら繰り返す
※マイナスの値も指定できます。
range() は指定した範囲の数の並びを意味します。
例えば range(1, 5) は 1, 2, 3, 4 という数の並びになります。
終値の5は入らない点に注意しましょう。
for文の動作を確認します。繰り返しに使う変数は慣例的に i とすることが多く、このプログラムでもiを用いています。
for_1.py
print(i)
意味
繰り返しiは0から始まり10回繰り返す
iの値を出力
実行結果
0
1
2
3
4
5
6
7
8
9
iの値は最初0で、1ずつ増えながら9になるまで、2行目の処理を繰り返します。
最後の値は range() の引数の10でないことに注意しましょう。
range()の範囲を理解する
range(初期値, 終値)で指定する繰り返しを確認します。range() の引数の範囲を理解しましょう。
for_2.py
print(i)
意味
繰り返しiは1から始まり、5まで1ずつ増えるiの値を出力
実行結果
1
2
3
4
5
変数の最後の値は終値の1つ手前になるので、このプログラムで6は出力されません。
次は range(初期値, 終値,いくつずつ変化させるか)の記述で、値を減らしていく繰り返しを確認します。
for_3.py
print(i)
意味
繰り返しiは12から始まり、6まで1ずつ減る
iの値を出力
実行結果
12
11
10
9
8
7
6
range(12, 5, -1)の範囲指定で値は 12 から始まり、1ずつ減りながら、終値の1つ手前の6まで出力されます。
for の面白い使い方もあります。
次のように記述して実行してみてください。
print(i)
P、y、t、h、o、nと一文字ずつ出力されます。
Pythonのfor は範囲に文字列を指定し、その文字列から一文字ずつ取り出すことができます。
こんなこともできるという豆知識の1つです。
breakとcontinue
break という命令で繰り返しを中断したり、continue という命令で繰り返しの先頭に戻ることができます。
break と continue の使い方を順に確認します。break と continue は if と組み合わせて使います。
for_break.py
if i==5:
break
print(i)
意味
繰り返しiは0から始まり、10回繰り返すiの値が5であればbreakで繰り返しを抜ける。iの値を出力する。
実行結果
0
1
2
3
4
解説
1行目で繰り返し範囲を range(10) とし、10回繰り返すように指定しています。しかし、2行目の条件式でiの値が5になったとき、その if文に記した breakで繰り返しを中断するので、5以上の数は出力されません。
if i < 5:
continue
print(i)
意味
繰り返しiは0から始まり、10回繰り返す
iの値が5未満であれば
continueで繰り返しの先頭に戻る
実行結果
5
6
7
8
9
このプログラムも10回繰り返すように指定していますが、2~3行目のif文で、 の値が5未満ならcontinueで繰り返しの先頭に戻しています。そのためiが5未満の間は4行目の処理には入らず、iが5以上になると continue は行われずに print(i) が実行されます。
while による繰り返しを説明します。while の処理の流れは、次のようになります。
whileの繰り返し
Pythonでは while文を次のように記述します。
Pythonのwhile 文
次のプログラムでwhile の動作を確認します。繰り返しに用いる変数は、whileの前で宣言します。
while_1.py
n=1
while n <= 128:
print(n, "→", end=" ")
n*=2
意味
繰り返しに使う変数nに初期値1を代入
whileの条件式をn<=128とし、繰り返す
nの値を出力
nの値を2倍し、nに代入
(4行目のn*2はn=n*2と同じ意味です。)
実行結果
1行目でwhile文の処理に使う変数nを宣言しています。2行目の条件式をnが128以下の間とし、3~4行目の処理を繰り返しています。
print() 命令には複数の引数を指定できます。このプログラムではnの値と「→」を出力し、end=“ ” と指定することで出力の最後を半角スペースとし、改行せずに数を横に並べています。
print() で出力する文字列や数を改行したくないなら end=の指定を用います。
たくさんのデータを出力するときに役立つので、覚えておきましょう。
while Trueの繰り返し
while True と記述すると常に条件式が成り立ち、処理が延々と繰り返されます。
while True の動作を次のプログラムで確認します。
while_2.py
while True:
s=input("文字列を入力してください")
print(s)
if s==" " or s=="end":
break
意味
whileの条件式をTrueとし、無限に繰り返す
入力した文字列を変数sに代入
sの値を出力
何も入力しないか、endと入力したら
whileを抜ける
実行結果
文字列を入力してください Python
Python
文字列を入力してくださいプログラミング
プログラミング
文字列を入力してください アルゴリズム
アルゴリズム
文字列を入力してください end
>>>
このプログラムは、入力した文字列をそのまま出力することを繰り返します。
何も入力せずに[Emura (return)]キーを押すか、end と入力すると、4~5行目の if と break で繰り返しを抜けて処理を終了します。
プログラムの強制中断
プログラムの記述ミスなどで処理が延々と続いてしまうとき、Windowsパソコンではctrl+ cキー、Macでは、control+cキーでプログラムを強制終了できます。このプログラムを再度、実行し、万が一のときのためにctrlキーによるプログラムの中断を確認しておきましょう。
同じ処理を延々と繰り返すことを無限ループといいます。記述ミスで無限ループに入るようなプログラムはNGだけど、もし入ってしまったときのために中断方法を覚えておきましょう。
forの多重ループ
for文中に別のfor文を入れることができます。for の中に for を記述することを、forを入れ子にするや、ネストすると表現します。
forを3つ入れ子にする、4つ入れ子にするなど、for文内に別のforをいくつも入れることができ、それらをまとめてfor の多重ループといいます。for の中にもう1つのforを入れる二重ループは特によく使われます。
多重ループでさまざまな繰り返し処理ができます。
次の例は、二重ループのfor文で九九の式を出力するプログラムです。
kuku.py
for y in range(1, 4):
print("--- ", y, "の段---")
for x in range(1, 10):
print(y , ”x”, x , "=", y*x)
意味
繰り返しyは1から3まで1ずつ増える
区切り線と◯の段を出力
繰り返しxは1から9まで1ずつ増える
y×x=y*xの値を出力
—1の段 —
1×1=1
1×2=2
1×3=3
・・・
このプログラムで1行目のyの値は1から始まります。yが1のとき、xは1→2→3→4→5→6→7→8→9と1ずつ増えながら、4行目の print)命令で一の段の式を出力します。
次にyの値は2になり、xは再び1→2→3→4→5→6→7→8→9と1ずつ増えて、この段の式が出力されます。同様にyが3になり、三の段が出力されると、全ての繰り返しが終わります。
関数
関数とはコンピュータが行う処理を1つのまとまりとして記述したものです。何度も行う処理があれば、それを関数として定義することで、無駄がなく、判読しやすいプログラムを組むことができます。
関数のイメージ
関数には引数でデータを与え、関数内でそのデータを加工し、加工した値を戻り値として返す機能を持たせることができます。
引数(ひきすう)と戻り値
引数は関数に渡す値のこと。
戻り値は関数で処理した値のこと。
ともに必須なものではなく、それらを持たない関数も定義できます。
関数を定義する
Pythonでは defで関数を定義します。
def hello():
print("こんにちは")
関数名には () を記述します。関数で行う処理は、 if や for と同様に字下げしたブロックに記述します。
引数も戻り値もない関数
function_1.py
def hello():
print("こんにちは")
hello()
意味
hello()という関数を定義
print()で文字列を出力
定義した関数を呼び出す
実行結果
関数名の付け方のルールは、変数名の付け方と一緒です。このプログラムでは1~2行目でhello() という関数を定義し、4行目でhello() を呼び出しています。関数は定義しただけでは働かず、呼び出して実行します。
このプログラムの1~2行目だけでは何も動作しません。
試しに4行目を削除するか、 #hello() と コメントアウトして実行すると、何も起きないことが判ります。
引数あり、戻り値なしの関数
次は引数あり、戻り値なしの関数を確認します。引数を持たせるときは、関数名の()内に引数となる変数を記述します。
function_2.py
def even_or_odd(n):
if n%2==0:
print(n, "は偶数です")
else:
print(n, "は奇数です")
even_or_odd(2)
even_or_odd(7)
意味
even_or_odd()という関数を定義
引数nの値が2で割り切れるなら「nは偶数です」と出力
そうでなければ「nは奇数です」と出力
引数2を与えて関数を呼び出す
引数7を与えて関数を呼び出す
実行結果
7は奇数です
1~5行目で引数の値が偶数か奇数かを判断する関数を定義しています。2行目のifで、余りを求める%演算子を用いて、引数の値が2で割り切れるかを調べています。
この関数を実際に働かせているのが7行目と8行目です。引数を設けた関数なので、引数を与えて呼び出しています。
関数は一度定義すれば、何度でも呼び出すことができます。
引数あり、戻り値ありの関数
関数に戻り値を持たせるには、関数内のブロックに
return 戻り値
と記述します。戻り値は変数名や計算式、あるいはTrueやFalseなどの値を記述します。戻り値に変数名を記述すればその値が返り、計算式を記述すればその計算結果が返ります。
長方形の幅と高さを引数で与え、面積を返す関数を定義します。その関数の動作を確認しながら、引数と戻り値を理解していきましょう。
長方形の面積を求める
function_3.py
def area_rect(w, h):
return w * h
a = area_rect(20, 10)
print("幅20cm,高さ10cmの長方形の面積は", a,"㎠")
print("幅12cm,高さ30cmの長方形の面積は", area_rect(12,30), "㎠")
意味
area_rect()という関数を定義
引数wとhを掛けた値を戻り値として返
関数で求めた20×10の長方形の面積をaに代入
print()でその値を出力
print() の引数に area_rect()を記述し、12×30の長方形の面積を出力
実行結果
幅12cm,高さ30cmの長方形の面積は360㎠
解説
1~2行目で定義した area_rect()関数は、引数で幅と高さを受け取り、計算した面積を戻り値として返します。
4行目でこの関数に引数を与えて呼び出し、戻り値を変数aに代入し、5行目でaの値を出カしています。
6行目では、定義した関数を printの()内に記述しています。このようにして関数の戻り値を変数に代入せず、直接、扱うこともできます。
プログラミングでは長方形を矩形(くけい)と呼ぶことがあります。
矩形を意味する英単語は rectangleで、rect と略して用いることがあります。
変数の有効範囲について
変数はグローバル変数とローカル変数に分かれ、それぞれ使える範囲が違います。
関数の定義では、変数の有効範囲の決まりごとを知っておく必要があるので、ここで説明します。
・グローバル変数とは関数の外部で宣言した変数
・ローカル変数とは関数の内部で宣言した変数
変数の有効範囲をスコープといいます。
グローバル変数は、それを宣言したプログラムのどの位置でも使うことができます。
一方、ローカル変数は、それを宣言した関数内でのみ使うことができます。
if や forのブロック内で宣言した変数もローカル変数です。それらはそのブロック内でのみ使うことができます。
変数はそれを宣言したブロック内で使えると覚えておきましょう。
global宣言を用いる
Python には、関数内でグローバル変数の値を変更するなら、その関数内で変数名をglobal宣言する決まりがあります。
global宣言する
次のプログラムで、変数のスコープとglobal の使い方を確認します。1行目の total という変数がグローバル変数で、4行目の loops がローカル変数です。
global_local.py
total = 0
def kasan():
global total
loops = 11
for i in range (loops):
total+=i
print("totalの初期値", total)
kasan()
print("関数実行後のtotalの値", total)
意味
totalという変数を宣言し初期値0を代入
kasan() という関数を定義
totalをグローバル変数として扱うと宣言
loopsというローカル変数に11を代入
for文でloops回、繰り返す
totalにiの値を足し、totalに代入
totalの初期値を出力
kasan()を呼び出す
関数実行後のtotalの値を出力
実行結果
関数実行後のtotalの値 55
関数の外側の1行目の宣言した totalがグローバル変数です。この変数の値を関数内で変更するので、3行目でglobal total とグローバル宣言しています。
4行目の loops が関数内で宣言したローカル変数です。 loops はこの関数内でのみ使えます。
kasan()関数を実行すると、5~6行目の for文で0+1+2+3+4+5+6+7+8+9+10 という計算が行われ、total の値は55になります。
8行目でtotalの値を出力し、9行目でkasan() を呼び出し、10行目で再び totai の値を出力しています。kasan() を実行すると total が55になるので、10行目でその値が出力されます。
何度も行う処理を関数にすれば、無駄のないプログラムになります。
無駄がなければ、プログラムの誤動作も起きにくいです。
配列(リスト)
配列とは複数のデータをまとめて管理するために用いる、番号の付いた変数のことです。
Pythonには配列と同じ機能を持ち、配列よりも柔軟にデータを扱えるリストというものが用意されています。
配列とリストについて
配列とPythonのリストは厳密には別のものですが、リストはC言語などの配列に相当するものと考えてかまいません。アルゴリズムをはじめて学ぶ方や、他のプログラミング言語で配列を学んだ方は、配列とリストを区別する必要はなく、リスト⇒配列と考えて学習を進めて支障はありません。
リストを理解する
ここから先は Pythonの用語に合わせ、リストという語で説明します。
リストとは変数に番号を付けてデータを管理するものです。
例えば、aという名の箱がn個あるとします。このaがリストです。
a[0] から a[n-1]の箱の1つ1つを要素といい、箱がいくつあるかを要素数といいます。例えば10個の箱があれば、そのリストの要素数は10です。
箱を管理する番号を添え字(インデックス)といいます。添え字は0から始まり、箱がn個あるなら、最後の添え字はn-1になります。
リストの宣言
リストは次のように記述して宣言し、初期値を代入します。Pythonではこう記した時点。
から箱 [0]、箱[1]、箱 [2] … が使えるようになります。
リストへの初期値の代入
[ ]でくくる
コンマで区切り、データを記述する
Python ではこの書式でリストを用意する他に、リスト名 = [] と記述して空のリストを用意し、そこに append() 命令などで後から要素を追加することができます。append()はリストにデータを付け加えたいときにつかいます。
複数のデータを扱う
リストで複数のデータを扱うプログラムを確認します。次のプログラムには item と priceという2つのリストが記されています。
リスト名の付け方のルールは、変数名の付け方と一緒です。
array_1.py
item= ["薬草", "毒消し","たいまつ", "短剣", "木の盾"]
price = [10, 20, 40, 200, 120]
for i in range(5):
print(item[i], "の値段は", price[i])
意味
itemというリストを宣言し、文字列を代入
priceというリストを宣言し、数を代入
繰り返しiは0から4まで5回繰り返す
item[i]とprice[i]の値を出力
実行結果
毒消しの値段は20
たいまつの値段は 40
短剣の値段は 200
木の盾の値段は120
1~2行目で定義したデータを、3~4行目の for と print() で出力しています。
リストと for はセットで使うことが多いので、このプログラムでその使い方をつかんでおきましょう。
二次元リスト
itemとprice はそれぞれ一次元のリストです。多次元のリストも宣言できます。よく使われる二次元リストについて説明します。
二次元リストは縦方向と横方向に添え字を用いてデータを管理します。
二次元リストのイメージ
a[y軸][x軸]
a[0][0] a[0][1] a[0][2] a[0][3]
a[1][0] a[1][1] a[1][2] a[1][3]
a[2][0] a[2][1] a[2][2] a[2][3]
二次元リストのデータの
といいます。
二次元リストの宣言
Pythonでは次のように記述して二次元リスト宣言し、初期値を代入します。
二次元リストの宣言例
data = [ ← はじまりの [
[ 100, 200, 300, 400, 500], ←各行を , で記述する
[-1 , -2 , -3 , -4 , -5],
[55, 66, 77, 88, 99] ←最後の行の , は不要
] ←終わりの]
二次元リストを用いたプログラム
二次元リストを用いたプログラムを確認します。
array_2.py
data = [
[100, 200, 300, 400, 500),
[ -1, -2, -3, -4, -5],
[ 55, 66, 77, 88, 99]
]
print(data[0][0])
print(data[1][1])
print(data[2][4])
意味
dataという名の二次元リストに初期値を代入
1行目の初期値
2行目の初期値
3行目の初期値
data[0][0]の値を出力
data[1][1]の値を出力
data[2] [ 4]の値を出力
実行結果
-2
99
1~5行目で二次元リストに初期値を代入し、6~8行目で3つの要素の値を出力しています。プログラム自体は難しいものではありませんが、慣れないうちは、リスト名 [y][x]のyとxの値がいくつの箱にどのデータが入っているか、つかみにくいものです。
プログラムを照らし合わせて、添え字の番号を理解しましょう。
二次元リストを理解できるかどうかが1つの山になります。
二次元リストは全く新しい知識ではなく、表やロッカーのように
データや物が管理しやすい仕組みを、コンピュータ内に用意したものです。
それとリストの添え字は0から始まることに注意してください。
Pythonのデータ型
変数やリストのデータ型とは、その箱でどのようなタイプのデータを扱うかという意味です。データ型を単に型ということもあります。
プログラミングを習得するにはデータ型を理解する必要があります。このコラムではPythonのデータ型について説明します。
Python には次のデータ型があります。
・整数型(int型)123 0 50000
・小数型(float型) -5.5 3.14 10.0
※厳密には浮動小数点数型といいます。
・文字列型(string型)Python アルゴリズム
・論理型(bool型) True False
例えばa = 10 と記述するとaは整数型の変数になり、b = 10.0 と記述するとbは小数型の変数になります。c=a+bとすると、cは20.0 という小数型の値になります。
論理型の値はTrue (真)とFalse(偽)の2つです。 if の学習で、条件式が成り立ったときはTrue、成り立たなかったときは Falseになることを学びましたが、変数にTrueやFalse という値を代入することができます。
10は整数ですが、10.0 と記せば小数の扱いになります。また“10”と記せば、それは文字列になります。これは多くのプログラミング言語に共通するルールです。覚えておきましょう。
いよいよIDLEで遊ぶミニゲームを作り、プログラムを入力することに慣れていきます。またゲームのプログラムを組みながら、初歩的なアルゴリズムを学んでいきます。
乱数の使い方
乱数とはサイコロを振って出る目のような、何が出るか判らない、ばらばらに出現する
数をいいます。ゲーム制作では乱数をよく使います。ゲームのプログラミングに入る前に、Pythonで乱数を発生させる方法を説明します。
モジュールについて
乱数はrandom モジュールを用いて発生させます。まずモジュールについて説明します。
変数やリストの使い方、条件分岐や繰り返しの命令などを学びました。変数やコンピュータに基本的な処理を行わせる命令は、特に準備なしに使うことができます。
一方、乱数を発生させたり、三角関数などで高度な計算を行うときは、Pythonに備わっているモジュールを用います。
Python にはさまざまなモジュールが用意されており、必要なモジュールを importすることで、そのモジュールに備わる機能を使うことができます。
次のモジュールを用いてゲームを制作します。
randomモジュール 乱数を発生させる
timeモジュール 日時を取得する、時間の計測を行う
tkinterモジュール 画面にウィンドウを表示し、GUIの部品を配置する
tkinter.messageboxモジュール メッセージボックスを表示する
これらの他に datetime モジュールや calendar モジュールなどもあります。
random モジュールの使い方
乱数を使うには random モジュールをインポートし、乱数を発生させる命令を記述します。
次のプログラムでモジュールの使い方と乱数の作り方を確認します。
このプログラムは、1から6のいずれかの数を10回出力します。
rand.py
import random
for i in range(10):
r = random.randint(1, 6)
print(r)
意味
randonモジュールをインポート
繰り返し10回繰り返す
変数rに1から6の乱数を代入
その値を出力
実行結果
25346165
解説
モジュールを用いるには、1行目のように import モジュール名と記述します。
モジュールに備わる命令(関数)を使うには、3行目のようにモジュール名、そのモジュールに備わった関数名と記述します。このプログラムでは randint()関数で、乱数の最小値と最大値を指定し、乱数を発生させています。
コンピュータが作る乱数は、さいころを振って出る目のような真の乱数ではなく、計算によって作り出される「疑似乱数」と呼ばれるものです。
乱数を発生させる命令
Pythonには乱数を発生させる命令として、次のようなものがあります。
小数の乱数
r=random.random()
rに0以上1未満の小数の乱数が代入される
整数の乱数
r=random.randint(1,6)
rに1から6のいずれかの整数が代入される
整数の乱数2
r=random.randrange(10,20,2)
rに10,12,14,16,18のいずれかが代入される
randrange(start,stop,step)で発生させる乱数は start から stop未満になります。stopの値は入りません。
複数の項目からランダムに選ぶ
r=random.choice([7,8,9])
rに7、8、9のいずれかが代入される
2項目はいくつでも記述できます。choice([“文字列0″,”文字列1″, “文字列2″]) ように文字列を羅列し、いずれかを選ばせることもできます。
おみくじアプリ
random.choice()を使った“おみくじ”のプログラムを紹介します。
omikuji.py
import random
KUJI = ["大大吉", "大吉", "中吉", "小吉", "凶"]
input("おみくじを引きます([Enter]キー)")
print(random.choice(KUJI))
意味
randomモジュールをインポート
おみくじの文字をリストで定義
説明文を表示、Enterキーの入力を待つ
ランダムに文字列を出力
実行結果
おみくじを引きます([Enter]キー)
中吉
解説
このプログラムを実行すると「おみくじをひきます([Enter]キー)」と表示され、 Enterーを押すと、2行目で定義した文字列のいずれかを4行目のchoice() 命令で出力します。3行目の input() は Enterキーが押されるのを待つために使っています。
単語入カゲームを作ろう
いよいよミニゲームの制作を始めます。1本目は「単語入カゲーム」です。まずは十数行程度のプログラムを組むのに慣れることを目標に学習を進めてください。
単語カードをイメージしたゲーム
手製の単語カードを題材にしたミニゲームを作っていきます。ゲームの内容は、リンゴ、本、猫などの日本語を出力するので、その英単語であるapple、book、catなどを入力します。
入力した単語が合っていれば点数を加算し、間違っていれば正しい英単語を表示します。
このゲーム制作で学ぶアルゴリズム
このゲームは「2つの文字列を比較し、同じものかを判断する」「リストで複数のデータを定義し、それらを扱う」という方法を学びながら制作します。3つの段階に分けて処理を組み込み、ゲームを完成させます。
第一段階 文字列を比較する
はじめに、2つの文字列を比較するプログラムを組んでみます。
次のプログラムを入力して名前を付けて保存し、実行して動作を確認してください。
word_game_1.py
s = input("猫の英単語を入力してください ")
if s == "cat":
print("正解です")
else:
print("猫はcatです")
意味
input()で入力した文字列を変数sに代入
sの値がcatなら
「正解です」と出力
catでないなら
「猫はcatです」と出力
実行結果
猫の英単語を入力してください dog
猫はcatです
解説
1行目の input()命令で入力した文字列を変数s に代入しています。2~5行目の if elseの
条件式でsの値が cat かを調べ、cat なら「正解です」、違っていれば「猫は catです」と出力しています。
第二段階 リストで文字列を定義する
第二段階では、複数の単語をリスト(配列)で定義します。ゲームを完成させるときに第一段階で学んだ文字列を比較する処理を入れますが、このプログラムでは文字列の比較は除いてあります。
次のプログラムの動作を確認してください。
word_game_2.py
japanese = ["リンゴ", "本", "猫", "犬", "卵", "魚", "女の子"]
english = ["apple", "book", "cat", "dog", "egg", "fish", "girl"]
n = len(japanese)
for i in range(n):
print(japanese[i], "は", english[i])
意味
リストで日本語の単語を定義
リストで英単語を定義
nにjapaneseの要素数を代入
繰り返し iは0からn-1まで1ずつ増える
日本語と英単語を出力
実行結果
本 は book
猫はcat
犬はdog
卵は egg
魚は fish
女の子 は girl
解説
このプログラムは japanese というリストに複数の日本語を、english というリストに複数の英単語を代入しています。
3行目のlen()はリストの要素数を知る命令です。japanese には7つの単語を定義しているので要素数は7であり、len(japanese)でその7が返り、変数nに代入されます。
4~5行目のfor文でjapanese と english で定義した単語を1つずつ出力しています。
第三段階 単語入力ゲームの完成
第一段階で学んだ文字列の比較と、第二段階のリストによるデータの定義を合わせ、単語入カゲームを完成させます。次の完成版プログラムの動作を確認してください。
word_geme_3.py
japanese = ["リンゴ", "本", "猫", "犬", "卵", "魚", "女の子"]
english = ["apple", "book", "cat", "dog", "egg", "fish", "girl"]
n = len(japanese)
right = 0
for i in range(n):
a = input(japanese[i]+"の英単語は? ")
if a==english[i]:
print("正解です")
right = right + 1
else:
print("違います")
print("正しくは"+english[i])
print("終了です")
print("正解数", right)
print("間違い", n-right)
解説
3行目でlen()を使って代入したnの値が、このゲームの問題数になります。
5~12行目の for と if else の処理で、日本語を1つずつ出力しinput()で入力した英単語が正解ならright の値を1増やしています。
繰り返しが終わると、right の値を正解数として出力し、n-right の値を間違いとして出力しています。nには問題数が入っているので、「n(問題数) – right(正解数)」が間違えた数になります。
ジャンケンゲームを作ろう
二本目はジャンケンゲームを作ります。グー、チョキ、パーのコンピュータの手を決めるのに乱数を用います。乱数の使い方を覚えていきます。
プレイヤーはグー(0)、チョキ(1)、パー(2)を数字で入力し、コンピュータとジャンケンをします。コンピュータが出す手は乱数を使って決めます。三回ジャンケンをして勝敗を決定します。
このゲーム制作で学ぶアルゴリズム
このゲーム制作で大切なことは「乱数の使い方」と「ジャンケンの勝ち負けのルールのプログラミング」です。それらを中心に学んでいきます。
このゲームも3つの段階に分けて処理を組み込み、完成させます。
第一段階、コンピュータの手をランダムに決める
まずコンピュータに「グー」「チョキ」「パー」のいずれかの手を出させます。
次のプログラムを入力して名前を付けて保存し、実行して動作を確認しましょう。
janken_game_1.py
import random
hand = ["グー", "チョキ", "パー"]
for i in range(3):
print("\n", i+1, "回目")
c = random.randint(0, 2)
print("コンピュータの手は"+hand[c])
意味
randomモジュールをインポート
リストでジャンケンの文字列を定義
繰り返し、3回繰り返す
「○回目」と出力
コンピュータの手をランダムに決める
その手を出力
実行結果
1 回目
コンピュータの手はチョキ
2 回目
コンピュータの手はグー
3 回目
コンピュータの手はバー
乱数を使うので1行目でrandom モジュールをインポートします。
2行目でグー、チョキ、パーという文字列をリストで定義しています。hand[0] の値がグー、hand[1]がチョキ、hand[2] がパーになります。このゲームでは3つの手を、グーは0、チョキは1、パーは2という数で管理します。
4~7行目の for文で処理を3回繰り返しています。その処理の内容は、5行目で「○回目」と出力し、6行目で変数cに0、1、2いずれかの数を入れ、7行目でhand[c] を出力するというものです。
・改行コード
5行目の print() の引数に “¥n” という記述があります。¥nは改行コードと呼ばれるもので、print()命令などで用いると、そこで文字列を改行します。今回は出力結果を見やすくするために、この改行コードを用いています。
¥と\(バックスラッシュ)は同じもので、Windowsでは主に¥n、Macでは\nで表示します。Windowsでもテキストエディタによっては、¥nではなく\nで表示します。
例えば
print(“こんにちは。\n今日はよいお天気ですね。“)
とすると、次のように、\nのところで文字列が改行されて出力されます。
こんにちは。
今日はよいお天気ですね。
第二段階 勝ち負けの判定
グーはチョキに強く、チョキはパーに強く、パーはグーに強いという、ジャンケンのルールを組み込みます。
グーは0、チョキは1、パーは2という数で手を管理します。その数で勝ち負けを表現すると、0(グー)は1(チョキ)に強く、1(チョキ)は2(パー)に強く、2(パー)は0(グー)に強いとなります。
プレイヤーが0(グー)を出し、コンピュータが1(チョキ)を出したときを条件分岐の if で表すと、「if プレイヤーの手が0で、コンピュータの手が1なら、プレイヤーの勝ち」となります。
また「if プレイヤーの手の数とコンピュータの手の数が同じなら、あいこ」になります。
次のプログラムは、全ての手の組み合わせを判定し、プレイヤーが勝ったこと、あるいは、コンピュータが勝ったことを出力します。このプログラムを実行すると、プレイヤーの入力を促すメッセージが表示されるので、0、1、2いずれかの数を入力してください。コンピュータはランダムに手を決め、プレイヤーとコンピュータのどちらが勝ったかを判定します。
janken_game_2.py
import random
hand = ["グー", "チョキ", "パー"]
print("コンピュータとじゃんけんをします。")
for i in range(3):
print("¥n", i+1, "回目のじゃんけん")
y = input("あなたは何を出す? ¥n0=3グー 1=チョキ 2=パー ")
y = int(y)
c = random.randint(0, 2)
print("コンピュータの手は"+hand[c])
if y==c:
print("あいこです")
if y == 0:
if c == 1:
print("あなたの勝ち")
if c == 2:
print("コンピュータの勝ち")
if y == 1:
if c == 0:
print("コンピュータの勝ち")
if c == 2:
print("あなたの勝ち")
if y== 2:
if c = 0:
print("あなたの勝ち")
if c == 1:
print("コンピュータの勝ち")
意味
randonモジュールをインポート
リストでジャンケンの文字列を定義
ルールの説明
繰り返し 3回繰り返す
「○回目のじゃんけん」と出力
input()で入力した文字列をyに代入
yの値を数に変換する
コンピュータの手をランダムに決める
コンピュータの手を出力
互いに同じ手なら「あいこです」と出力
Tプレイヤーがグーを出したとき
コンピュータがチョキなら「あなたの勝ち」と出力
コンピュータがパーなら「コンピュータの勝ち」と出力
プレイヤーがチョキを出したときコンピュータがグーなら
「コンピュータの勝ち」と出力
コンピュータがパーなら「あなたの勝ち」と出力
プレイヤーがパーを出したときコンピュータがグーなら
「あなたの勝ち」と出力
コンピュータがチョキなら「コンピュータの勝ち」と出力
実行結果
コンピュータとじゃんけんをします。
1回目のじゃんけん
あなたは何を出す?
0=グー 1=チョキ 2=パー 2
コンピュータの手はグー
あなたの勝ち
2回目のじゃんけん
あなたは何を出す?
0=グー 1=チョキ 2=パー 1
コンピュータの手はチョキ
あいこです
3回目のじゃんけん
あなたは何を出す?
0=グー 1=チョキ 2=パー 0
コンピュータの手はパー
コンピュータの勝ち
解説
7行目の input() 命令でプレイヤーに文字列を入力させて、8行目でそれを数に変換しています。
9行目でコンピュータの手を乱数で決め、変数cに代入します。
yとcの値はグーが0、チョキが1、パーが2です。
11~27行目でyとcの値を比べ、勝ち負けを出力しています。yとcの値が一致したときは、グー同士、チョキ同士、パー同士のいずれかで“あいこ”になるので、if y==c という判定は1回だけ行えばよいものになります。
さて、このプログラムは数字以外を入力したり、何も入力せずに Enterキーを押すと、エラーが発生して処理が止まってしまいます。
ゲームに限らずどのようなソフトウェアでも、このようなエラーが発生してはなりません。そこで「0、1、2以外を入力したら、プレイヤーの負けとする」あるいは「必ず0、1、2いずれかをプレイヤーに入力させる」などの処理を入れる必要があります。
今回は後者の0、1、2いずれかだけを入力する仕組みを入れてゲームを完成させます。
このようなプログラムは文字列と数を対応させて処理を作ることが基本です。
ただし処理の内容によっては、文字列を直接、扱うこともあります。
第三段階 ジャンケンゲームの完成
プレイヤーとコンピュータ、それぞれが勝った回数を数える変数を用意し、ジャンケンゲームを完成させます。三回ジャンケンをして、多く勝ったほうの勝利とします。このゲームはあいこでも1回ジャンケンをしたと数えます。
次の完成版プログラムの動作を確認してください。
janken_game_3.py
import random
hand = ["グー"、"チョキ", "パー"]
you_win = 0
com_win = 0
print("コンピュータとじゃんけんをします。")
print("3回じゃんけんをして勝敗を決めます。")
for i in range(3):
print("\n", i+1, "回目のじゃんけん")
y=" "
while True:
y=input("あなたは何を出す? ¥n0=グー 1=チョキ 2=パー")
if y=="0" or y="1" or y=="2":
break
y = int(y)
c = random.randint(0, 2)
print("コンピュータの手は"+hand[c])
if y==c:
print("あいこです")
if y == 0:
if c == 1:
print("あなたの勝ち")
you_win = you_win+1
if c==2:
print("コンピュータの勝ち")
com_win = com_win+1
if y== 1:
if c==0:
print("コンピュータの勝ち")
com_win = com_win+1
if c== 2:
print("あなたの勝ち")
you_win = you_win+1
if y == 2:
if c == 0:
print("あなたの勝ち")
you_win = you_win+1
if c== 1:
print("コンピュータの勝ち")
com_win = com_win+1
print("---------------")
print("あなたが勝った回数", you_win)
print("コンピュータが勝った回数", com_win)
if you_win>com_win:
print("あなたの勝利!")
elif com_win>you_win:
print("コンピュータの勝利!")
else:
print("引き分け")
解説
3~4行目で宣言したyou_win、com_winという変数に、プレイヤーが勝った回数とコンピュータが勝った回数を代入します。
3回勝負するので、8行目の for文で処理を3回繰り返します。
11~14行目で、while Trueの無限ループを用いて、プレイヤーに0、1、2いずれかを入力させます。この処理の詳細は後述します。
18~40行目で勝ち負けを判定し、プレイヤーが勝ったらyou_winの値を1増やし、コンピュータが勝ったら com_winを1増やしています。
繰り返しが終わったら、you_win と com winの値を出力します。そして45~50行目で、you_win と com_win の大小を比べて、どちらが勝ったか、あるいは引き分けかを出力しています。
決められた文字列だけ入力させる
while True:のプログラムには、プレイヤーに0、1、2のいずれかだけを入力させる仕組みを入れました(11~14行目)。
y=” “
while True:
y= input(“あなたは何を出す?¥no=グー 1=チョキ 2=パー“)
if y==”0″ or y==”1″ or y==”2″:
break
while の条件式を True とすることで、処理が無限に繰り返されます。入力した値が0、1、2のどれかならbreakで無限ループを抜け、次へ進みます(緑矢印の線)。
0、1、2以外を入力したときは、処理が繰り返され、再びinput()が行われる仕組みになっています。
もぐら叩きゲームを作ろう
三本目はもぐら叩きゲームを作ります。ゲームをプレイした時間を計測するという、やや高度な処理を学びます。
読者のみなさんは、ワニをハンマーで叩いて点数を競う業務用のゲーム機をご存知でしょうか。最近はあまり見かけなくなりましたが、以前は多くのゲームセンターに置かれていたので、一度くらいは遊んだことがあるという方もいらっしゃるのではないでしょうか。
私が子供の頃は、穴から顔を出すもぐらをハンマーで叩いて点数を競う「もぐら叩き」というゲーム機がありました。
このゲームを IDLEで遊べるようにします。
コンピュータゲームは自由な発想で考えてよいものですから、ここで作るゲームは、アンダースコアとドット (.) を並べ、そのうちどれか1つを半角のオー (o)にして、穴ともぐら
を表現します。oが穴から顔を出したもぐらです。
記号と文字で、もぐら叩きを表現する
_._
[1 ]
_o_
[ 2 ]
もぐらのいる位置の数字を入力することで、もぐらを倒す設定にします。ただしIDLE はリアルタイムのキー入力ができないので、数字を入れて Enterキーを押す操作で遊ぶものとします。
このゲームはどれだけ早く入力できるかを競うものとし、ゲーム開始から終了までの時間を計測して、もぐらを早く倒すほど高得点となるようにします。
このもぐら叩きは、数を入力しEnterキーを押すことでゲームを進めます。
このゲーム制作で学ぶアルゴリズム
ここでは「プログラムで時間を計る方法」と「機能を待つ関数の作り方」を学びます。このゲームも3つの段階に分けて処理を組み込み、完成させます。
第一段階時間の計測方法を知る
Pythonで時間を計る方法を説明します。時間の計測にはいくつかのやり方がありますが、ここでは timeモジュールを用います。
次のプログラムを入力して名前を付けて保存し、実行して動作を確認してください。
mogura_tataki_1.py
import time
print("========== 計測開始 ==========")
ts = time.time()
print("エポック秒", ts)
input("Enterキーを押すまでの時間を計測します")
te = time.time()
print("エポック秒", te)
print("========== 計測終了 ==========")
print("経過秒数", int(te-ts))
意味
timeモジュールをインポート
計測開始の合図を出力
この時点のエポック秒を変数tsに代入
tsの値を出力
input()でEnterキーが押されるまで待つ
この時点のエポック秒を変数teに代入
teの値を出力
計測終了の合図を出力
te-tsの値を、小数点以下を切り捨て出力
実行結果
===== 計測開始 =====
エポック秒 1606184488.1305816
Enterキーを押すまでの時間を計測します
エポック秒1606184508.4698377
===== 計測終了 =====
経過秒数 20
解説
Pythonでは timeモジュールにあるtime)という関数でエポック秒を取得できます。エポック秒(エポック時間)とは1970年1月1日午前0時0分0秒からの経過秒数のことです。
このプログラムは1行目で time モジュールをインポートし、3行目の ts = time.time() で変数 ts にその時点のエポック秒を代入しています。そして4行目でts の値を出力しています。
5行目の input() 命令により、何か文字列を入力して「Enterキーを押すまで、プログラムの処理は先へは進みませんが、現実の時間であるエポック秒は進んでいきます。
すと処理が6行目に移り、te = time.time() で変数 teにその時点の新たなエポック秒が代入されます。
te から ts を引いた値が、 input() で入力を待った秒数になります(。それをint()で整数にした値を9行目で出力しています。
第二段階 もぐらを表示する関数を作る
もぐらと番号を表示する関数を定義します。このプログラムに時間の計測は入れていません。
次のプログラムの動作を確認しましょう。
mogura_tataki_2.py
def mogura(r):
m = ""
n = ""
for i in range(8):
ana = "."
if i==r:
ana = "O"
m = m + " _" + ana + "_ "
n = n + " [" + str(i) + "] "
print(m)
print(n)
print("mogura()関数を引数1で呼び出す")
mogura(1)
print("")
print("mogura()関数を引数5で呼び出す")
mogura(5)
意味
モグラを表示する関数の定義
変数mに空の文字列を代入
変数nに空の文字列を代入
繰り返し 変数iを用いて8回繰り返す
変数anaにドットを代入
iが引数rの値なら
anaにオーを代入
アンダースコアとanaをつなげていく
[と、iの値と、]をつなげていく
mの値(穴ともぐら)を出力
nの値(穴の番号)を出力
「関数を引数1で呼び出す」と出力
mogura(1)を呼び出す
改行するために空の文字列を出力
「関数を引数5で呼び出す」と出力
mogura(5)を呼び出す
実行結果
mogura()関数を引数1で呼び出す
mogura()関数を引数5で呼び出す
解説
1~11行目が、もぐらと番号を出力する mogura()関数の定義です。この関数には引数r を設けており、rの値で、もぐらがどこに顔を出すかを指定します。
もぐらの穴を表す文字列の作り方ですが、2行目と3行目で空の文字列を初期値とした変数m とnを用意します。4~9行目の繰り返しで、mにアンダースコア(_)とドット(.)をつなげていきます。このとき、rの位置にはドットの代わりにオー(o)を置きます。nには[番号]という文字列をつなげていきます。その際、iに入っている数値を文字列にするために str() を用いています。
こうしてもぐらの穴と番号を表す文字列を作り、10~11行目で出力しています。
この関数を実際に働かせているのは、14行目と17行目です。関数は定義しただけでは動かず、プログラム内の必要な箇所で呼び出して実行します。
文字だけで、もぐらの穴と、顔を出すもぐらを表現している点がポイントです。
コンピュータゲームは自由にアイデアを考えられるところがいいですね。
第三段階 もぐら叩きゲームの完成
第一段階で学んだ時間の計り方と、第二段階でプログラミングしたもぐらを表示する関数を使い、他にゲームとしての処理を加え、もぐら叩きゲームを完成させます。
次の完成版プログラムの動作を確認してください。
mogura_tataki_3.py
import time
import random
def mogura(r):
m = ""
n = ""
for i in range(8):
ana = "."
if i==r:
ana = "O"
m = m + " _" + ana + "_ "
n = n + " [" + str(i) + "] "
print(m)
print(n)
print("========== ゲームスタート! ==========")
hit = 0
ts = time.time()
for i in range(10):
r = random.randint(0, 7)
mogura(r)
p = input("モグラはどこ? ")
if p == str(r):
print("HIT!")
hit = hit + 1
else:
print("MISS")
t = int(time.time()-ts)
bonus = 0
if t<60:
bonus = 60-t
print("========== ゲームエンド ==========")
print("TIME", t, "sec")
print("HIT", hit, "× BONUS", bonus)
print("SCORE", hit*bonus)
意味
timeモジュールをインポート
randomモジュールをインポート
モグラを表示する関数の定義
変数mに空の文字列を代入
変数nに空の文字列を代入
繰り返しiを用いて8回繰り返す
変数anaにドットを代入
iが引数rの値なら
anaにオーを代入
アンダースコアとanaをつなげていく
[と、iの値と、]をつなげていく
mの値(穴ともぐら)を出力
nの値(穴の番号)を出力
ゲーム開始の合図を出力
変数hitに0を代入
この時点のエポック秒をts代入
繰り返しiを用いて10回繰り返す
rに0から7の乱数を代入
rを引数としmogura()関数を呼び出す
input()で、もぐらは何番かを入力
もぐらの位置と一致すれば
HIT!と出力
hitの値を1増やす
そうでなければ
MISSと出力
終了までに掛かった秒数をtに代入
変数bonusに0を代入
60秒未満で終了した場合
bonusの値を60-掛かった秒数とする
ゲーム終了の合図を出力
掛かった秒数を出力
何匹叩いたかとbonusの値を出力
スコアを出力
用いている主な変数
hit もぐらを叩いた数
ts.、t プレイ時間の計測
bonus ボーナスポイントの計算用
解説
19~27行目の for文がゲームのメイン部分の処理です。forで10回繰り返す中で、乱数でもぐらの位置を決めて変数 rに代入し、mogura()関数でもぐらと番号を出力します。そしてinput() で入力した値がrの値と一致すれば、変数hit の値を1増やしています。
このfor の直前の18行目で ts=time.time() とし、ゲーム開始時のエポック秒を変数 ts に代入しています。そして繰り返しが終わった直後の28行目でt=int(time.time()-ts) とし、ゲームをプレイするのに掛かった秒数をtに代入しています。
29~31行目でボーナスポイントの値を計算しています。この値はプレイするのに掛かった時間が60秒未満なら、60-掛かった秒数とします。60秒以上掛かったときは bonusを0とします。
33~35行目で、掛かった時間、もぐらを叩いた数、bonusの値、スコアを出力しています。スコアの値を hit × bonus とすることで、正確に、できるだけ素早く叩くとスコアが伸びる計算になっています。またスコアをhit × bonusとしたのは、プレイ時間を最短にしようと何も入力せずに[Enter]キーだけを押し続けた場合、叩いた回数(hit の値)は0であり、そのようなプレイではスコアを0とすることが妥当だからです。けっこう熱くなりますね。
日時を扱ってみよう
もぐら叩きゲームでは time モジュールを用いて時間を計りました。Python には他にも日時を扱う色々な命令やモジュールが備わっています。
・timeモジュールで現在の日時を取得
timeモジュールのもう少し詳しい使い方から説明します。
次のプログラムはtimeモジュールを用いて現在の日付と時刻を出力する例です。
time_1.py
import time
tt = time.localtime()
print(t)
d=time.strftime("%Y/%m/%d %A", t)
h = time.strftime("%H:%M:%S", t)
print(d)
print(h)
意味
timeモジュールをインポート
localtime()の値をtに代入
その値を出力
strftime()で年月日と曜日の文字列を用意する
strftime()で時分秒の文字列を用意する
年月日と曜日を出力
時分秒を出力
実行結果
time.struct_time(tm_year=2020, tm_mon=11, tm_mday=22, tm_hour=14, tm_min=4, tm_s
ec%3D23, tm_wday=6, tm_yday=327, tm_isdst=0)
2020/11/22 Sunday
14:04:23
解説
2行目のt=time.localtime()でローカル時間のデータを変数tに代入しています。3行目で確認用にその値を出力していますが、そのままでは日時として使えないことが判ります。
そこでstrftime()関数を用いて、ローカル時間のデータを4~5行目で自由なフォーマットで日付や時刻に変えています。strftime()の第一引数には次の記号を記し、第二引数に localtime() を代入した変数を記述します。
strftime()の引数の記号
%Y 西暦4桁の10進表記
%y 西暦下2桁の10進表記
%m 月の10進表記
%d 日の10進表記
%A 曜日名
%a 短縮した曜日名
%H 時の24時間表記
%l 時の12時間表記
%M 分の10進表記
%S 秒の10進表記
・datetimeモジュールを用いる
datetimeモジュールを用いて、シンプルな記述で日時を取得できます。次のプログラムは実行時の日付と時刻を出力し、時、分、秒の値を個別に取り出す例です。
date_time_1.py
import datetime
n = datetime.datetime.now()
print(n)
print("時を取り出す", n.hour)
print("分を取り出す", n.minute)
print("秒を取り出す", n.second)
意味
datetimeモジュールをインポート
datetime.now()の値をnに代入
その値を出力
時の値を取り出して出力
分の値を取り出して出力
秒の値を取り出して出力
実行結果
2020-11-22 14:12:48.412685
時を取り出す 14
分を取り出す 12
秒を取り巨す 48
datetime.datetime.now()の値を代入した変数に .hour を付けて、「時」の値を取り出すことができます。同様に.minute「分」、.secondで「秒」を取り出せます。年月日を取り出すには、.year、.month、.dayを用います。calendarモジュールを用いる
calendar モジュールでカレンダーを出力できます。次のプログラムは指定した年月のカレンダーを表示します。
calender_1.py
import calendar
print(calendar.month(2021,3))
意味
calendarモジュールをインポート
引数の年月のカレンダーを出力
実行結果
March 2021
Mo Tu We Th Fr Sa Su
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Pythonには日時データを扱う機能が豊富にあります。time モジュール、datetime モジュール、calendarモジュールには他にも
色々な関数が用意されています。
calendar モジュールの month()関数で西暦と月を指定し、カレンダーを出力できます。calendar.prcal() という命令を用いると、一年分のカレンダーを出力できます。2行目をprint(calendar.prcal(2021))などに書き換え、確認してみましょう。
キャンバスに図形を描こう
今回はPythonが持つ機能でウィンドウを表示して、そこに色々な図形を描きます。またウィンドウ内をクリックしたことや、マウスポインタの動きを取得する方法を学びます。
ここで学んだ知識を使い、グラフィックを用いた本格的なゲームを制作します。
この学習では、いくつかの画像ファイルを使用します。それらの画像は、ご自身で近いものをご用意ください。
PythonのGUI(グラフィカルユーザインタフェース)の部品の1つであるCanvas(キャンバス)の使い方を説明します。
https://www.youtube.com/watch?v=B07a0xhEkrAGUIについて
GUI (Graphical User Interface)とは、コンピュータ画面にボタン
やテキスト入力部などが配置された操作系を指す言葉です。例えばインターネットを閲覧するブラウザ、文書作成ソフト、表計算ソフトなどがGUIで構成されたソフトウェアです。
GUI の例として、Windowsに付属する「ペイント」というお絵描きソフトを挙げます。「ペイント」は次のような画面構成になっています。
Windows付属の「ペイント」
このソフトウェアには、絵を描くキャンバス、色を選ぶパレット、どのような図形を描くかを指定するアイコンなどが配置されています。ユーザーはそれらをマウスでクリックして絵を描くことができます。
GUIの部品を適宜、配置すれば、どのような操作を行えばよい
か判りやすいソフトウェアを作ることができます。
Pythonでウィンドウを表示する
GUIで構成されるソフトウェアを制作するには、コンピュータ画面にウィンドウを表示する必要があります。Pythonでは tkinter というモジュールを用いてウィンドウを作り、そこに絵を描くキャンバスや入力用のボタンなどを配置できます。
まず tkinter を用いてウィンドウを表示します。次のプログラムを入力して実行し、動作を確認してください。
window_1.py
import tkinter
root = tkinter.Tk()
root.title(“ウィンドウのタイトル“)
root.mainloop()
意味
tkinterモジュールをインポート
ウィンドウのオブジェクトを準備
ウィンドウのタイトルを指定
ウィンドウの処理を開始
実行結果
解説
tkinterモジュールを用いるには、1行目のように import tkinter と記述します。
2行目の変数 = tkinter. Tk()でウィンドウとなる部品(オブジェクト)を用意します。
3行目の title()でウィンドウのタイトルバーに表示するタイトルを指定します。
4行目の root.mainloop()でウィンドウの処理を開始します。
このプログラムはウィンドウのサイズを指定していないので、小さなウィンドウが表示され、タイトルバーの文字が一部しか見えませんが、マウスでウィンドウを横に広げれば3行目で指定した文字列が表示されます。
Pythonではウィンドウを作るときの変数名をroot とすることが多く、このプログラムもrootを用いています。最後の行の root.mainloop() を難しく捉える必要はありません。ウィンドウを用いたソフトウェアの処理を始める決まり文句と考えましょう。
この章で学ぶことは次章からのゲーム制作の準備になりますが、GUIを用いると操作しやすいビジネスソフトなども作ることができます。つまりみなさんはこの章で幅広いソフトウェア開発に応用できる知識を学びます。
ウィンドウにキャンバスと呼ばれる部品を配置し、そこに図形を描いてみます。図形を描くにはコンピュータ画面の座標について知る必要があるので、はじめにそれを説明します。
コンピュータの座標について
コンピュータの画面は左上の角を原点(0, 0)とし、横方向がX軸、縦方向がY軸になりま
す。コンピュータ画面に表示される個々のウィンドウも、ウィンドウ内の左上角が原点で、横方向がX軸、縦方向がY軸です。
Y軸
コンピュータはY軸の向きが数学の図と逆で、下にいくほどYの値が大きくなります。画面に図形を描くときは原点の位置とY軸の向きに注意します。
キャンバスを配置する
tkinter にキャンバス(Canvas)という部品が用意されています。キャンバスに文字列を書く、図形を描く、画像ファイルを読み込んで表示することができます。
文字列、図形、画像ファイルの表示を順に確認します。まずウィンドウにキャンバスを配置し、そこに文字列を表示します。次のプログラムの動作を確認してください。
canvas.py
import tkinter
root = tkinter.Tk()
root.title("キャンバスに文字列を表示")
cs = tkinter.Canvas (width=600, height=400, bg="white")
cvs.create_text(300, 200, text="Python", font= (“Times New Roman", 40))
cvs.pack().
root.mainloop()
意味
tkinterモジュールをインポート
ウィンドウのオブジェクトを準備
ウィンドウのタイトルを指定
キャンバスの部品を用意
キャンバスに文字列を表示
キャンバスをウィンドウに配置
ウィンドウの処理を開始
実行結果
解説
4行目でキャンバスの部品を作っています。キャンバスを用意する書式は次のようになります。
キャンバスの変数名 = tkinter.canvas(width=幅, height=高さ, bg=背景色)
このプログラムでは変数名を canvasの英単語を略した cvs としています。
キャンバスの背景色は bg=で指定します。この指定は省略することもできます。色を指定するなら bg=の後に red green blue black white などの英単語か、16進法で色の値を記します。
キャンバスに文字列を書くには、5行目のようにキャンバスの変数に対しcreate_text()命令を用います。この命令の引数で、X座標、Y座標、text=文字列、fill=文字の色、font-(フォントの種類、サイズ)を指定します。X座標とY座標は文字列の中心位置になります。
このプログラムでは、フォントの種類をWindowsとMac共通で使える Times New Romanとしています。
6行目の pack()でキャンバスをウィンドウに配置しています。pack() を用いて配置すると、ウィンドウはキャンバスの大きさに合わせて広がります。このプログラムではキャンバスの幅を600ドット、高さを400ドットとしており、ウィンドウはそれより少し大きなサイズになります。
16進法の色の値は#RRGGBB という書式で、RRに赤、GGに緑、
に青の光の強さを指定します。例えば赤は#ff0000、緑は#00c000、
紫は#8000c0、白は#fffff、黒は#3000000になります。
Pythonの色指定
色を指定する英単語の例をサンプルプログラムで紹介します。このプログラムは、COLというリストに定義した英単語の色で文字列を表示します。
color_sample.py
import tkinter
root = tkinter.Tk()
root.title("色を指定する英単語")
cvs = tkinter.Canvas(width=360, height=480, bg="black")
COL = [
"maroon", "brown", "red", "orange", "gold",
"yellow", "lime", "limegreen", "green", "skyblue",
"cyan", "blue", "navy", "indigo", "purple",
"magenta", "white", "lightgray", "silver", "gray",
"olive", "pink"
]
FNT = ("Times, New Roman", 24);
x = 120
y = 40
for c in COL:
cvs.create_text(x, y, text=c, fill=c, font=FNT)
y += 40
if y>=480:
y = 40
x += 120
cvs.pack()
root.mainloop()
実行結果
図形を描く
キャンバスに、線、矩形(くけい)※長方形のこと、円、多角形を描きます。次のプログラムの動作を確認してください。
canvas_figure.py
import tkinter
root = tkinter.Tk()
root.title("キャンバスに図形を描く")
cvs = tkinter.Canvas(width=720, height=400, bg="black")
cvs.create_line(20, 40, 120, 360, fill="red", width=8)
cvs.create_rectangle(160, 60, 260, 340, fill="orange", width=0)
cvs.create_oval(300, 100, 500, 300, outline="yellow", width=12)
cvs.create_polygon(600, 100, 500, 300, 700, 300, fill="green", outline="lime", width=16)
cvs.pack()
root.mainloop()
実行結果
意味
tkinterモジュールをインポート
ウィンドウのオブジェクトを準備
ウィンドウのタイトルを指定
キャンバスの部品を用意
Tリストで色の英単語を定義
フォントの種類と大きさを定義
文字列を表示するX座標
文字列を表示するY座標
forでCOLの値を1つずつ抜き出す
キャンバスに英単語を表示
y座標の値を40増やす
480以上になったら
y座標を40にし
x座標を120増やして右にずらす
キャンバスをウィンドウに配置
ウィンドウの処理を開始
解説
7行目の create_oval() が楕円の接する枠の左上角と右下角の座標を指定して楕円を描く命
令です。このプログラムでは円の接する枠の幅と高さを等しい値で指定し、正円を描いています。
8行目の create_polygon)が複数の点を指定して、それらを結んだ多角形を描く命令です。
このプログラムでは (600, 100)、(500,300)、(700,300)という3つの点を指定し、三角形を描いています。
これらの命令の引数は、fill=で塗り潰す色、outline=で周りの線の色、width=で線の太さを
指定します。塗り潰す色を指定しなければ、7行目の create_oval)で描いた月のように、線だけで図形が表示されます。
図形の描画命令の使い方をまとめます。
図形の描画命令
線
(x1,y1)
create_line (x1, y1, x2, y2, fill=色, width=線の太さ)
※複数の点を指定できる
3点以上指定しsmooth=Trueとすると曲線になる
矩形
create_rectangle(x1, y1, x2, y2, fill=塗り色,outline=枠線の色, width=線の太さ)
楕円
create_oval(x1,y1, x2, y2, fill=塗り色,outline=外周の線の色, width=線の太さ)
多角形
create_polygon(x1,y1, x2, y2, x3, y3, . . , fill=塗り色, outline=線の色, width=線の太さ)
※複数の点を指定できる
円弧
create_arc(x1, y1, x2, y2, fill=塗り色,outline=線の色, start=開始角度, extent=何度描くか, style=tkinter.*)
※角度は度(degree)の値で指定
style=の記述は省略可。
画像ファイルを表示する
画像ファイルを読み込んで表示する方法を説明します。次のプログラムは、プログラムと同一フォルダにある hachi.png というファイルを読み込んで表示します。
image.py
import tkinter
root = tkinter.Tk()
root.title("キャンバスに画像を表示")
cvs = tkinter.Canvas(width=740, height=920)
cat = tkinter.PhotoImage(file="js.png")
cvs.create_image(570, 260, image=cat)
cvs.pack()
root.mainloop()
実行結果
意味
tkinterモジュールをインポート
ウィンドウのオブジェクトを準備
ウィンドウのタイトルを指定
キャンバスの部品を用意
変数dogに画像を読み込む
キャンバスに画像を表示
キャンバスをウィンドウに配置
ウィンドウの処理を開始
解説
この写真の幅は740ドット、高さは920ドットです。キャンバスをCanvas(width=740,height=920) として、写真の大きさに合わせて用意しています。
5行目のPhotolmage()命令の引数 file=で画像のファイル名を指定し、変数に画像を読み込みます。画像を表示するには6行目のように、キャンバスの変数に対しcreate_image)を用いて、X座標、Y座標、image=画像を読み込んだ変数を引数で指定します。
create_image() の座標指定で注意すべきことがあります。それは引数のX座標とY座標が画像の中心位置になることです。例えばこの指定を create_image(0, 0, image=dog) とすると、画像が左上角に寄ってしまい、1/4だけしか表示されません。create_image() の引数の値を変更し、表示位置が変わることを確認しておいてください。
画像を自動的に動かす
tkinterを用いて作ったウィンドウで、指定した時間が経過したら関数を呼び出す命令を使い、リアルタイムに処理を進めることができます。ここではキャンバスに描いた画像を自動的に動かし、その命令の使い方を学びます。
リアルタイム処理について
時間軸に沿って進む処理をリアルタイム処理といいます。リアルタイム処理はゲーム開発に欠かせない技術の1つです。Pythonでは tkinterで用意したウィンドウで、after)という命令を使ってリアルタイム処理を行うことができます。
https://www.youtube.com/watch?v=GboxH1yxdTU数を数えるプログラム
まず、自動的に数をカウントするプログラムでリアルタイム処理のイメージをつかみましょう。次のプログラムを実行すると、表示された数字が1秒ごとに増えていきます。
cout_number.py
import tkinter
F = ("Times New Roman", 100)
n = 0
def counter():
global n
n = n + 1
cvs.delete("all")
cvs.create_text(300, 200, text=n, font=F, fill="blue")
root.after(1000, counter)
root = tkinter.Tk()
root.title("リアルタイム処理1")
cvs = tkinter.Canvas(width=600, height=400, bg="white")
cvs.pack()
counter()
root.mainloop()
実行結果
意味
tkinterモジュールをインポート
フォントの定義を変数Fに代入
初期値0の変数nを用意
リアルタイム処理を行う関数の定義
nをグローバル変数として扱う
nの値を1増やす
キャンバスに描いたものを全て削除
nの値を表示
ウィンドウのオブジェクトを準備
ウィンドウのタイトルを指定
キャンバスの部品を用意
キャンバスをウィンドウに配置
counter()関数を呼び出す
ウィンドウの処理を開始
解説
5~10行目でcounter() という関数を定義しています。この関数でリアルタイム処理を行
います。
数をカウントするために、counter() の外側でn=0と宣言した変数を、関数内でglobalとしてグローバル宣言します。そして7行目のようにn= n+1 と し、関数を実行するとnの値を1ずつ増やしています。8行目の cvs.delete(“all”)でキャンバスに描いたものを全て消
してから、9行目の create text()でnの値を表示しています。
16行目でcounter()関数を呼び出しています。counter() が実行されると、10行目のafter() 命令で1000ミリ秒後(1秒後)に再び counter() が呼び出されます。after()の引数は“何ミリ秒後”に“どの関数を実行するか”です。after() の引数の関数名は () を付けずに記述します。
after() を用いたリアルタイム処理の流れは、次のようになります。
グローバル変数の値はプログラムが終了するまで保持されますが、関数内のローカル変数の値は、その関数を呼び出すたびに初期値
になります。これはプログラミングの大切なルールの1つなので、しっかり頭に入れておきましょう。
画像を動かす
次は画像を自動的に動かします。次のプログラムは、表示された飛行機が右端に達すると左へ、左端に達すると右へ向きを変えて、ウィンドウ内を移動し続けます。
real_time.py
import tkinter
x = 300
y = 100
xp = 10
def animation():
global x, xp
x = x + xp
if x <= 30: xp = 5
if x >= 770: xp = -5
cvs.delete("all")
cvs.create_image(400, 200, image=bg)
if xp<0:
cvs.create_image(x, y, image=ap1)
if xp>0:
cvs.create_image(x, y, image=ap2)
root.after(50, animation)
root = tkinter.Tk()
root.title("リアルタイム処理2")
cvs = tkinter.Canvas(width=800, height=400)
cvs.pack()
ap1 = tkinter.PhotoImage(file="airplane1.png")
ap2 = tkinter.PhotoImage(file="airplane2.png")
bg = tkinter.PhotoImage(file="bg.png")
animation()
root.mainloop()
実行結果
意味
tkinterモジュールをインポート
変数xに初期値を代入
変数yに初期値を代入
変数xpに初期値を代入
リアルタイム処理を行う関数の定義
xとxpをグローバル変数として扱う
xにxpの値を加える
xが30以下になったらxpを5にする
xが770以上になったらxpを-5にする
キャンバスに描いたものを全て削除
背景画像を表示する
xpがマイナスの値なら
左向きの飛行機を描く
xpがプラスの値なら
右向きの飛行機を描く
50ミリ秒後にanimation()を実行
ウィンドウのオブジェクトを準備
ウィンドウのタイトルを指定
キャンバスの部品を用意
キャンバスをウィンドウに配置
左向きの飛行機の画像を読み込む
右向きの飛行機の画像を読み込む
背景画像を読み込む
animation()関数を呼び出す
ウィンドウの処理を開始
解説
3~4行目で飛行機の座標を管理する変数x、yを、5行目でX軸方向の移動量を管理する数xpを用意しています。
6~17行目で飛行機を自動的に動かす animation()関数を定義しています。この関数の中でX座標とX軸方向の移動量を変化させるので、変数x、xpを7行目のようにグローバル宣言しています。変数y は関数内で値を変えないのでグローバル宣言は不要です。
8~10行目が飛行機のX座標を変化させる計算です。xにxpの値を加え、xが30以下になったら(左端に達したら) xp の値を5にします。xpを正の数にすればxの値は増えていくので、飛行機は右に移動するようになります。またxが770 以上になったら(右端に達したら)
xpを-5にし、今度は左に移動するようにしています。
11行目の cvs.delete(“all”)でキャンバスに描いたものを全て消し、12行目で背景画像を表示しています。また13~14行目でxpが負の値なら左向きの飛行機を、15~16行目でxpが正の値なら右向きの飛行機を表示しています。
if文を1行で書く
このプログラムでは9行目と10行目のif文を、次のように1行で記述しています。
if x <= 30: xp = 5
if x >= 770: xp = -5
Python は本来、ブロックの処理を改行して字下げし、次のように記述するプログラミング言語です。
if x<=30:
xp=5
if x >=770:
xp=-5
もちろんこの記述が正しいですが、9行目や10行目のような、ごく短い if文は改行しないほうがプログラムがすっきりすることがあります。そこでこのプログラムは、それら2つの行を改行せずに記述しています。
マウスボタンのクリックを取得する
ウィンドウでマウスボタンをクリックしたり、マウスポインタを動かしたことを知る命令があります。
イベントについて
ユーザーがソフトウェアに対してキーやマウスを操作することをイベントといいます。
例えばウィンドウをクリックすると、ウィンドウに対しクリックイベントが発生します。
どのようなイベントが発生したかを知ることを、そのイベントを「受け取る」や「取得する」と表現します。
bind()命令を使う
イベントを受け取るには bind() という命令を用います。bind() を使うにはイベントが発生したときに実行する関数を用意し、
bind(“<イベント“, 実行する関数名)と記述します。
bind()の引数の関数名は()を付けずに記述します。
bind() で取得できる主なイベントは次のようになります。
bind()で取得するイベント
<Button>マウスボタンを押した
<ButtonRelease>マウスボタンを離した
<Motion>マウスポインタを動かした
<Key>キーを押した
<KeyRelease>キーを離した
マウスのクリックを受け取る
キャンバスをクリックすると図形が変化するプログラムで、イベントを受け取る仕組みを学びます。次のプログラムの動作を確認しましょう。ウィンドウ内をクリックするごとに、表示された図形が矩形 → 三角形→円→再び矩形と変化します。
event_button.py
import tkinter
n = 0
def click(e):
global n
n = n + 1
if n==3: n = 0
cvs.delete("all")
if n==0:
cvs.create_oval(200, 100, 400, 300, fill="green")
if n==1:
cvs.create_rectangle(200, 100, 400, 300, fill="gold")
if n==2:
cvs.create_polygon(300, 100, 200, 300, 400, 300, fill="red")
root = tkinter.Tk()
root.title("マウスクリックの取得")
root.bind("<Button>", click)
cvs = tkinter.Canvas(width=600, height=400, bg="white")
cvs.create_text(300, 200, text="クリックしてください")
cvs.pack()
root.mainloop()
実行結果
意味
tkinterモジュールをインポート
変数nに0を代入
クリック時に働く関数の定義
nをグローバル変数として扱う
nの値を1増やす
nが3になったら0にする
キャンバスに描いたものを全て削除
nが0なら
円を表示
nが1なら
矩形を表示
nが2なら
三角形を表示
ウィンドウのオブジェクトを準備
ウィンドウのタイトルを指定
イベント時に実行する関数を指定
キャンバスの部品を用意
キャンバスをウィンドウに配置
ウィンドウの処理を開始
解説
4~14行目でマウスボタンをクリックしたときに働く関数を定義しています。このプログラムではその関数名をclick()としています。
click()関数の処理は、グローバル宣言した変数nの値を1増やし、nが3になったら0にします。つまりマウスボタンをクリックするたびにnは0→1→2→再び0と変化します。9~14行目でnの値が0のときに円、1のときに矩形、2のときに三角形を描いています。
マウスボタンが押されたときに click()関数が呼び出されるように、18行目でroot bind(“<Button>”, click)としています。
click(e)の引数eについて
click()関数の引数eは、イベントを受け取る関数に記述するものです。このプログラムではeを用いていませんが、次のマウスポインタの動きを知るプログラムで、引数eを用いてポインタの座標を取得します。
マウスポインタの動きを取得する
マウスポインタの動き(ポインタの座標)を取得する方法を学びます。
座標を取得する
マウスポインタの動きもクリックの取得と同じ手順で受け取ります。ポインタを動かしたときに実行する関数を用意し、bind)でその関数を指定します。マウスポインタの動きを知るには、bind)の引数のイベントの種類に<Motion> と記述します。
マウスポインタの座標を取得するプログラムを確認します。このプログラムは、ポインタの座標をキャンバスに表示します。
event_motion.py
import tkinter
FNT = ("Times New Roman", 40)
def move(e):
cvs.delete("all")
s = "({}, {})".format(e.x, e.y)
cvs.create_text(300, 200, text=s, font=FNT)
root = tkinter.Tk()
root.title("マウスポインタの座標")
root.bind("<Motion>", move)
cvs = tkinter.Canvas(width=600, height=400)
cvs.create_text(300, 200, text="ウィンドウ内でマウスポインタを動かしてください")
cvs.pack()
root.mainloop()
実行結果
意味
tkinterモジュールをインポート
フォントの定義
マウスを動かしたときに働く関数の定義
キャンバスに描いたものを全て削除
ポインタの座標を入れた文字列を用意
その文字列をキャンバスに表示
ウィンドウのオブジェクトを準備
ウィンドウのタイトルを指定
イベント時に実行する関数を指定
キャンバスの部品を用意
説明文を表示
キャンバスをウィンドウに配置
ウィンドウの処理を開始
解説
4~7行目でマウスポインタを動かしたときに実行する関数を定義しています。このプログラムではその関数名を move() としています。move) 関数に設けた引数eはイベントを受け取るための変数で、e.x と e.yがマウスポインタの座標になります。
イベントを受け取る引数名は、例えば move(event)のように任意の名称にできます。
event としたときは event. x、event.yがポインタの座標になります。
format()命令の使い方
6行目でマウスポインタの座標を文字列として変数sに代入しています。それを行うのにformat() という関数を用いています。
format() は次のように文字列内の{}を変数の値に置き換える命令です。複数の変数を一度に文字列に置き換えるときなどに便利です。
format()の機能
s = “({}, {})”.format(e.x, e.y)
format()の引数はいくつでも記述できます。例えば format() に5つの引数を記述するなら、文字列内に{}を5つ記述します。
マウスを追い掛ける風船プログラム
ウィンドウ(キャンバス上)に表示した風船がマウスポインタを追い掛け、ウィンドウ内をクリックすると風船の色が変わるプログラムを制作します。(風船の画像は適当なものを用意してください)
複数の処理を組み合わせる
これから確認する内容は、この章で学んだことの総仕上げになります。このプログラムに
はリアルタイム処理、マウスボタンのクリックとポインタの動き(座標)を取得する処理が
組み込まれています。風船は図形を描画する命令を組み合わせて表現しています。
次のプログラムの動作を確認しましょう。
move_balloon.py
import tkinter
COL = ["red", "orange", "yellow", "lime", "cyan", "blue", "violet"]
bc = 0
bx = 0
by = 0
mx = 0
my = 0
def click(e):
global bc
bc = bc + 1
if bc==7: bc=0
def move(e):
global mx, my
mx = e.x
my = e.y
def main():
global bx, by
if bx < mx: bx += 5
if mx < bx: bx -= 5
if by < my: by += 5
if my < by: by -= 5
cvs.delete("all")
cvs.create_oval(bx-40, by-60, bx+40, by+60, fill=COL[bc])
cvs.create_oval(bx-30, by-45, bx-5, by-20, fill="white", width=0)
cvs.create_line(bx, by+60, bx-10, by+100, bx+10, by+140, bx, by+180, smooth=True)
root.after(50, main)
root = tkinter.Tk()
root.title("リアルタイムに風船を動かす")
root.bind("<Button>", click)
root.bind("<Motion>", move)
cvs = tkinter.Canvas(width=900, height=600, bg="skyblue")
cvs.pack()
main()
root.mainloop()
実行結果
意味
tkinterモジュールをインポート
風船の色をリストで定義
風船をどの色で描くかを管理する変数
風船のX座標を代入する変数
風船のY座標を代入する変数
マウスポインタのX座標を代入する変数
マウスポインタのY座標を代入する変数
クリック時に実行する関数の定義
bcをグローバル変数として扱う
bcの値を1増やす
bcが7になったら0にする
マウスを動かしたときに働く関数の定義
これらをグローバル変数として扱う
mxにポインタのX座標を代入
myにポインタのY座標を代入
メイン処理を行う関数の定義
これらをグローバル変数として扱う
bxがmxより小さいならbxを5増やす
mxがbxより小さいならbxを5減らす
byがmyより小さいならbyを5増やす
myがbyより小さいならbyを5減らす
キャンバスに描いたものを全て削除
千円と線を描く命令で風船を表示
風船はCOL[ bc]の色とする
50ミリ秒後にmain()を呼び出す
ウィンドウのオブジェクトを準備
ウィンドウのタイトルを指定
ボタンクリック時に実行する関数を指定
マウスを動かしたときに実行する関数を指定
キャンバスの部品を用意
キャンバスをウィンドウに配置
main()関数を呼び出す
ウィンドウの処理を開始
解説
10~13行目がマウスボタンをクリックしたときに働く click()関数の定義です。風船を描く色の番号を管理する bc という変数をこの関数の外側で宣言し、関数内でglobal bc としています。マウスボタンをクリックすると、関数内でbcの値を1増やし、7になったら0に戻しています。
15~18行目がマウスポインタを動かしたときに働くmove()関数の定義です。マウスポインタの座標を代入するmx、myという変数を関数の外側で宣言し、関数内でmx と my に ポインタの座標を代入しています。
20~30行目がリアルタイム処理を行う main()関数の定義です。風船の座標を管理する bx、byという変数を関数の外側で宣言しています。main()関数内で風船とマウスポインタの座標の値を比べ、ポインタに近付くように風船の座標を変化させています。風船は
create_oval() と create_line()で描いています。
次に風船をマウスポインタに近付ける計算方法を説明します。
風船がマウスポインタに向かうアルゴリズム
風船がマウスポインタに向かう仕組みを、次のようにX座標だけで考えてみます。
bxの値を増やす・・・bx < mx
bxの値を減らす・・・mx < bx
風船が左、マウスポインタが右(この図の上の状態)にあるとき、bx とmxの値はbx<mxという関係にあります。その場合は風船を右に移動させるとマウスポインタに近付くので、bxの値を増やします。また風船が右、マウスポインタが左(図の下の状態)にあるとき
は、2つの変数の大小関係はmx<bx です。その場合はbxの値を減らし風船を左に移動させます。その判定と計算を22~23行目で行っています。
Y軸方向に対しても24~25行目のように同様の計算を行うことで、風船をマウスポインタの方に向かわせることができます。22~25行目を抜き出して確認します。
if bx < mx: bx += 5
if mx < bx:bx = 5
if by < my: by += 5
if my < by: by -= 5
bx += 5 は bx = bx + 5、bx -= 5 は bx = bx – 5と同じ意味です。このプログラムでは1回の計算で風船の座標がX軸方向、Y軸方向にそれぞれ5ドットずつ変化します。その値を変更すれば風船の移動速度が変わります。
after() の引数のミリ秒数を変えることでも風船の速さが変わります。
ただし引数の値を小さくし過ぎると、風船が描かれる前に処理が進み、風船の一部が切れて表示されるかもしれません。
フレームレートについて
このプログラムは root. after (50, main)として 50ミリ秒ごとに main() 関数を実行しています。これにより1秒間におおよそ20回の計算と描画が行われています。
ゲームソフトで1秒間に画面を描き変える回数をフレームレートといいます。家庭用ゲーム機やパソコン用のゲームソフトは、一般的に1秒間に30回もしくは60回の描画が行われています。
スマートフォンはパソコンやゲーム機よりも処理能力が低い機種があるため、1秒間に15~20回程度の回数でゲーム画面を描画するアプリもあります。