if と別れる50の方法《03》ジャンケン問題, double-dispatch

記事一覧if 篇for 篇配列 篇

Python.use(better) # OOP への道 《Python3.1, Jython2.5.0, IronPython2.6.x》
ジャンケン問題, double-dispatch

《著》真樹育未・後藤いるか・小粒ちゃん《監修》小泉ひよ子とタマゴ倶楽部
第0版♪1988/10/12 ● 第1版♪1993/05/23 ● 第2版♪2003/05/25

■ 概要

if/switch 文は多くの問題を抱え、OOP を実践するときの「障害」になります。

伝統的なC言語風の for 文や悪名高い switch 文、配列の呪縛から解かれ、オブジェクト指向プログラミング〔OOP〕の醍醐味を堪能するための準備を行います。

ジャンケン問題とは

《Note》n人が3つの手(石/鋏/紙)の中からひとつを出したときに、その勝敗(引分を含む)を判定します。

じゃん拳大辞林 第二版 (三省堂
  • 二人以上の人が片手で石(ぐう)・はさみ(ちょき)・紙(ぱあ)の形をつくり、どの形を出したかで勝負を決めること。また、その遊び。石ははさみに、はさみは紙に、紙は石に勝つ。いしけん。じゃんけんぽん。
じゃん拳 ¶ 新英和中辞典第6版 (研究社)
  • the game of ‘paper, stone and scissors.'

OOP による解法を示す前に、まず伝統的な SP による解法を示します。

SP による解法

まず「テストケース」を提示します。

def ex():
    p1 = Player("A")
    p2 = Player("B")
    for e in range(9):
        print(">>>", p1.next(), p2.next())
        print(judge(p1, p2))

2人のプレーヤー p1,p2 が出した手 next() を比較して、勝敗を判定 judge します。

from random import randint
R,P,S = 0,1,2

class Player(object):
    def __init__(self, id):
        self.id = id
    def __repr__(self):
        return "%s(%s)"%(self.__class__.__name__, self.id)
    def next(self):
        self.hand = randint(0, 2)
        return self.hand
■ 多重 if 文
def judge(p1, p2):
    if p1.hand == R:
        if p2.hand == R: return None
        if p2.hand == P: return p1
        if p2.hand == S: return p2
    if p1.hand == P:
        if p2.hand == R: return p2
        if p2.hand == P: return None
        if p2.hand == S: return p1
    if p1.hand == S:
        if p2.hand == R: return p1
        if p2.hand == P: return p2
        if p2.hand == S: return None

2人で対戦する場合には、入れ子になった2重の if 文が必要になります。すると、3人で対戦する場合には3重の if 文が、そして、n人で対戦する場合にはn重の if 文が必要になります。

■ 多重論理式
def judge(p1, p2):
    if *1:
        return None
    if *2:
        return p1
    if *3:
        return p2

2人で対戦する場合には、2重の論理式が必要になります。すると、3人で対戦する場合には3重の論理式が、そして、n人で対戦する場合にはn重の論理式が必要になります。

Tips

》作業中です《

Last updated♪2009/07/11

*1:p1.hand == R and p2.hand == R) or (p1.hand == P and p2.hand == P) or (p1.hand == S and p2.hand == S

*2:p1.hand == R and p2.hand == P) or (p1.hand == P and p2.hand == S) or (p1.hand == S and p2.hand == R

*3:p1.hand == R and p2.hand == S) or (p1.hand == P and p2.hand == R) or (p1.hand == S and p2.hand == P