自己紹介
Python大好きwhile-true-ifです。
対象者
- Python好きな人
- Python初心者
- Pythonでじゃんけんのコンソールアプリを作りたい人
この記事を読む前に
- この記事では効率化という言葉が使われます。ここでいう効率化とは、「コードを書く効率」です。処理時間ではありません。
- あくまでもこの記事は2人のじゃんけんに特化した勝敗判定となっています。3人以上は想定していません。
- この記事に出てくる「よりよいコード」とはだいたい同じくらいの処理時間(差が1000ms以内)であり、コードが短くなることを意味します。
じゃんけんとは
グーとチョキとパーがあります。
下の表は左側のグー・チョキ・パーが自分の出した手で、上側のグー・チョキ・パーが相手の出した手です。
グー | チョキ | パー | |
---|---|---|---|
グー | △ | ○ | × |
チョキ | × | △ | ○ |
パー | ○ | × | △ |
○は自分が勝ったことを表し、△は引き分け・あいこであることを表し、×は負けたことを表します。
じゃんけんのルールの説明はこれで終わりにして、Pythonでじゃんけんの勝敗判定をしていきたいと思います。
じゃんけんの勝敗判定
経緯
友達がPythonを使ってじゃんけんのコンソールアプリを作っていました。
そのときに、友達の書いた勝敗判定が下のコードです。
ここでは、0がグー、1がチョキ、2がパーとします。
友達のコード
# 0:グー 1:チョキ 2:パー
a,b=map(int,input().split())
if a==0:
if b==0:
print("draw")
elif b==1:
print("win")
else:
print("lose")
elif a==1:
if b==0:
print("lose")
elif b==1:
print("draw")
else:
print("win")
else:
if b==0:
print("win")
elif b==1:
print("lose")
else:
print("draw")
友達のコードの説明
まず、1行目がコメントなので、スルーしてOKです。
次に、2行目でaとbという変数に半角スペース区切りのint型で2つの変数に代入します。つまり、1 2
という入力が与えられたとき、a=1
、b=2
となります。
そこから下の行は条件分岐で、すべてのパターン(32=9(通り))を試して、win
、draw
、lose
を出力しています。
このコードを見て、わかりにくいと思いました。そのため、修正していきたいと思います。
じゃんけんの勝敗判定の効率的なつけ方
0をグー、1をチョキ、2をパーにしたとき、
(自分の出した手 - 相手の出した手 + 3) mod 3
この式に自分の出した手と相手の出した手に代入します。
次に、その式の値をnとおいたときに、n=0だったら引き分け・あいこ、n=1だったら負け、n=2だったら勝ちとなります。
ちなみに、modというのはあまりです。
つまり、(自分の出した手 - 相手の出した手 + 3)mod3
は
(自分の出した手 - 相手の出した手 + 3)から3で割った時のあまりです。
たとえば、
10 mod 3 = 1
となります。
+3ってなんなの?
一応、負の数 mod 3
に対処するため、付け加えました。
Pythonで
print(-1%3)
を実行したところ、2
と出力されました。これが自分の想定している出力です。
しかし、自分もあまり知りませんが、他の言語で1
と出力されたら、困るので、+3
を付けたさせていただきました。
少なくとも、Pythonでは+3
を付け足さなくても、ちゃんとした勝敗判定が出ます。
じゃんけんの勝敗判定を効率的に行ったコード
# 0:グー 1:チョキ 2:パー
def result(my_hand, opponent_hand):
key = (my_hand - opponent_hand + 3) % 3
if key == 0:
return 1
elif key == 1:
return 0
else:
return 2
result_output = ["lose", "draw", "win"]
my_hand, opponent_hand = map(int, input().split())
output_key = result(my_hand, opponent_hand)
print(result_output[output_key])
自分のコードの説明
1行目はコメントなのでスルーしてOKです。
2~9行目はさっきの方法で、じゃんけんの勝敗判定を効率的に行っています。
10行目はなにもないのでスルーしてOKです。
11行目はresult_output
というlistに、lose
、draw
、win
という要素を格納しています。
12行目ではmy_hand
とopponent_hand
という変数に半角スペース区切りでint型のものを代入しています。
13行目では2~9行目のコードを実行して、output_key
という変数に返された値を代入しています。
14行目ではresult_output
からoutput_key
番目の値を出力しています。
※ここでは、0番目スタートであるとします。
より良いコード
これは@shiracamus(しらかみゅ)さんからいただいたコードです。
# 0:グー 1:チョキ 2:パー
def janken(my_hand, opponent_hand):
return ("draw", "lose", "win")[(my_hand - opponent_hand) % 3]
print(janken(*map(int, input().split())))
よりよいコードの説明
1行目はコメントなのでスルーしてOKです。
2,3行目で自分のコードの2~9,11,13行目を行っています。
そして、3行目はなにもないのでスルーしてOKです。
4行目は入力されたものをjanken
という関数に通して、出力しています。自分のコードだと、12,14行目にあたります。
自分のコードより洗練されています。
おわりに
美しいコードを心がけて、Pythonのコードを書いていきたいと思います。
いいねとフォローをお願いします。
フォローされたらフォロー返しします。