Poker

/*
 * ポーカー(ジョーカーは含みません)
 */
class Cardsポーカー is subclass of Cards

types
public 役型 = <ノーペア> | <ワンペア> | <ツーペア> | <スリーカード> | 
        <ストレート> | <フラッシュ> | <フルハウス> | <フォーカード> |
        <ストレートフラッシュ> | <ロイヤルフラッシュ>;

functions
 -- 同一の役があれば、強い方になる。
役を求める: set of カード型 -> 役型
役を求める(hand) ==
    if isロイヤルフラッシュ(hand) then
        <ロイヤルフラッシュ>
    else if isストレートフラッシュ(hand) then
        <ストレートフラッシュ>
    else if isフォーカード(hand) then
        <フォーカード>
    else if isフルハウス(hand) then
        <フルハウス>
    else if isフラッシュ(hand) then
        <フラッシュ>
    else if isストレート(hand) then
        <ストレート>
    else if isスリーカード(hand) then
        <スリーカード>
    else if isツーペア(hand) then
        <ツーペア>
    else if isワンペア(hand) then
        <ワンペア>
    else
        <ノーペア>
pre
    card hand = 5;  -- 手札は5枚

 -- ワンペア 同一ランク(数字)のカード2枚のペア一組。(残り3枚は何でもよい)。  1/2.366 
isワンペア: set of カード型 -> bool
isワンペア(hand) ==
    exists
        c1, c2 in set hand &
        c1 <> c2 and c1.番号 = c2.番号
pre
    card hand = 5;  -- 手札は5枚

 -- ツーペア 同一ランク(数字)のカード2枚からなるペアが二つ。(残り1枚は何でもよい)。  1/21.0 
isツーペア: set of カード型 -> bool
isツーペア(hand) ==
    exists
        c1, c2, c3, c4 in set hand &
        c1 <> c2 and c1 <> c3 and c1 <> c4 and
                     c2 <> c3 and c2 <> c4 and
                                  c3 <> c4 and
        c1.番号 = c2.番号 and c3.番号 = c4.番号 and c1.番号 <> c3.番号
pre
    card hand = 5;  -- 手札は5枚

 -- スリーカード 同一ランク(数字)のカード3枚。(残り2枚は何でもよい)。1/47.3 
isスリーカード: set of カード型 -> bool
isスリーカード(hand) ==
    exists
        c1, c2, c3 in set hand &
        c1 <> c2 and c1 <> c3 and
                     c2 <> c3 and
        c1.番号 = c2.番号 and c1.番号 = c3.番号
pre
    card hand = 5;  -- 手札は5枚

 -- フォーカード 同一ランク(数字)のカード4枚。(残り1枚は何でもよい)。 1/4165 
isフォーカード: set of カード型 -> bool
isフォーカード(hand) ==
    exists
        c1, c2, c3, c4 in set hand &
        c1 <> c2 and c1 <> c3 and c1 <> c4 and
                     c2 <> c3 and c2 <> c4 and
                                  c3 <> c4 and
        c1.番号 = c2.番号 and c1.番号 = c3.番号 and c1.番号 = c4.番号
pre
    card hand = 5;  -- 手札は5枚

 -- ペア一組とスリーカード 1/694 
isフルハウス: set of カード型 -> bool
isフルハウス(hand) ==
    exists
        c1, c2, c3, c4, c5 in set hand &
        c1 <> c2 and c1 <> c3 and c1 <> c4 and c1 <> c5 and
                     c2 <> c3 and c2 <> c4 and c2 <> c5 and
                                  c3 <> c4 and c3 <> c5 and
                                               c4 <> c5 and
        c1.番号 = c2.番号 and c1.番号 = c3.番号 and c4.番号 = c5.番号
pre
    card hand = 5;  -- 手札は5枚


 -- ストレート 5枚のカードのランクが連続していること。1/255
 -- Aは2とKのどちらにつくこともできる。が、J,Q,K,A,2はダメ
isストレート: set of カード型 -> bool
isストレート(hand) ==
    let
        ns = { c.番号 | c in set hand }
    in
        ns in set {
            { 1, 2, 3, 4, 5 },
            { 2, 3, 4, 5, 6 },
            { 3, 4, 5, 6, 7 },
            { 4, 5, 6, 7, 8 },
            { 5, 6, 7, 8, 9 },
            { 6, 7, 8, 9, 10 },
            { 7, 8, 9, 10, 11 },
            { 8, 9, 10, 11, 12 },
            { 9, 10, 11, 12, 13 },
            { 10, 11, 12, 13, 1 }
        }
pre
    card hand = 5;  -- 手札は5枚

 -- フラッシュ 5枚全てが同じスート。1/509 
isフラッシュ: set of カード型 -> bool
isフラッシュ(hand) ==
    card { c.マーク | c in set hand } = 1
pre
    card hand = 5;  -- 手札は5枚

 -- ストレートフラッシュ ストレートでかつフラッシュ。1/72193.3 
isストレートフラッシュ: set of カード型 -> bool
isストレートフラッシュ(hand) ==
    isストレート(hand) and isフラッシュ(hand)
pre
    card hand = 5;  -- 手札は5枚

 -- ロイヤルフラッシュ 10・ジャック・クイーン・キング・エースの組み合わせでかつフラッシュ。 1/649740 
isロイヤルフラッシュ: set of カード型 -> bool
isロイヤルフラッシュ(hand) ==
    isフラッシュ(hand) and { c.番号 | c in set hand } = { 10, 11, 12, 13, 1 }
pre
    card hand = 5;  -- 手札は5枚

public test0: () -> 役型
test0() ==
    役を求める({    -- ノーペア
            mk_ジョーカーを除くカード型( <ハート>,      1 ),
            mk_ジョーカーを除くカード型( <スペード>,    3 ),
            mk_ジョーカーを除くカード型( <ハート>,      5 ),
            mk_ジョーカーを除くカード型( <クラブ>,      7 ),
            mk_ジョーカーを除くカード型( <ダイヤ>,      13 )
        });

public test1: () -> 役型
test1() ==
    役を求める({    -- ワンペア
            mk_ジョーカーを除くカード型( <ハート>,      5 ),
            mk_ジョーカーを除くカード型( <スペード>,    3 ),
            mk_ジョーカーを除くカード型( <ハート>,      3 ),
            mk_ジョーカーを除くカード型( <クラブ>,      7 ),
            mk_ジョーカーを除くカード型( <ダイヤ>,      13 )
        });

public test2: () -> 役型
test2() ==
    役を求める({    -- ツーペア
            mk_ジョーカーを除くカード型( <ハート>,      13 ),
            mk_ジョーカーを除くカード型( <スペード>,    3 ),
            mk_ジョーカーを除くカード型( <ハート>,      3 ),
            mk_ジョーカーを除くカード型( <クラブ>,      7 ),
            mk_ジョーカーを除くカード型( <ダイヤ>,      13 )
        });

public test3: () -> 役型
test3() ==
    役を求める({    -- スリーカード
            mk_ジョーカーを除くカード型( <ハート>,      13 ),
            mk_ジョーカーを除くカード型( <スペード>,    3 ),
            mk_ジョーカーを除くカード型( <ハート>,      3 ),
            mk_ジョーカーを除くカード型( <クラブ>,      3 ),
            mk_ジョーカーを除くカード型( <ダイヤ>,      5 )
        });

public test4: () -> 役型
test4() ==
    役を求める({    -- ストレート
            mk_ジョーカーを除くカード型( <ハート>,      1 ),
            mk_ジョーカーを除くカード型( <スペード>,    2 ),
            mk_ジョーカーを除くカード型( <ハート>,      3 ),
            mk_ジョーカーを除くカード型( <クラブ>,      4 ),
            mk_ジョーカーを除くカード型( <ダイヤ>,      5 )
        });

public test5: () -> 役型
test5() ==
    役を求める({    -- フラッシュ
            mk_ジョーカーを除くカード型( <ハート>, 1 ),
            mk_ジョーカーを除くカード型( <ハート>, 3 ),
            mk_ジョーカーを除くカード型( <ハート>, 5 ),
            mk_ジョーカーを除くカード型( <ハート>, 7 ),
            mk_ジョーカーを除くカード型( <ハート>, 9 )
        });

public test6: () -> 役型
test6() ==
    役を求める({    -- フルハウス
            mk_ジョーカーを除くカード型( <ハート>,      5 ),
            mk_ジョーカーを除くカード型( <スペード>,    3 ),
            mk_ジョーカーを除くカード型( <ハート>,      3 ),
            mk_ジョーカーを除くカード型( <クラブ>,      3 ),
            mk_ジョーカーを除くカード型( <ダイヤ>,      5 )
        });
public test7: () -> 役型
test7() ==
    役を求める({    -- フォーカード
            mk_ジョーカーを除くカード型( <ハート>,      13 ),
            mk_ジョーカーを除くカード型( <スペード>,    3 ),
            mk_ジョーカーを除くカード型( <ハート>,      3 ),
            mk_ジョーカーを除くカード型( <クラブ>,      3 ),
            mk_ジョーカーを除くカード型( <ダイヤ>,      3 )
        });

public test8: () -> 役型
test8() ==
    役を求める({    -- ストレートフラッシュ
            mk_ジョーカーを除くカード型( <ハート>, 1 ),
            mk_ジョーカーを除くカード型( <ハート>, 2 ),
            mk_ジョーカーを除くカード型( <ハート>, 3 ),
            mk_ジョーカーを除くカード型( <ハート>, 5 ),
            mk_ジョーカーを除くカード型( <ハート>, 4 )
        });

public test9: () -> 役型
test9() ==
    役を求める({    -- ロイヤルフラッシュ
            mk_ジョーカーを除くカード型( <ハート>, 1 ),
            mk_ジョーカーを除くカード型( <ハート>, 10 ),
            mk_ジョーカーを除くカード型( <ハート>, 11 ),
            mk_ジョーカーを除くカード型( <ハート>, 12 ),
            mk_ジョーカーを除くカード型( <ハート>, 13 )
        });
public test: () -> seq of 役型
test() == [ test0(), test1(), test2(), test3(), test4(), 
            test5(), test6(), test7(), test8(), test9() ];

end Cardsポーカー
/*
参考 http://ja.wikipedia.org/wiki/%E3%83%9D%E3%83%BC%E3%82%AB%E3%83%BC
http://www.kumamotokokufu-h.ed.jp/kokufu/math/game_p.html
ロイヤル・フラッシュ     4/2598960
ストレート・フラッシュ  36/2598960
 */