12
7

友達のじゃんけんの勝敗判定のコードを効率化&わかりやすくしてみた

Last updated at Posted at 2024-03-27

自己紹介

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=1b=2となります。

そこから下の行は条件分岐で、すべてのパターン(32=9(通り))を試して、windrawloseを出力しています。

このコードを見て、わかりにくいと思いました。そのため、修正していきたいと思います。

じゃんけんの勝敗判定の効率的なつけ方

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に、losedrawwinという要素を格納しています。
12行目ではmy_handopponent_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のコードを書いていきたいと思います。


いいねとフォローをお願いします。

フォローされたらフォロー返しします。

12
7
10

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
7