206 lines
5.7 KiB
Python
206 lines
5.7 KiB
Python
from functools import total_ordering
|
|
from enum import Enum
|
|
from typing import List, Tuple, Optional, Union, Any
|
|
|
|
|
|
class Suit(Enum):
|
|
SPADES = 's' # 黑桃
|
|
HEARTS = 'h' # 红桃
|
|
DIAMONDS = 'd' # 方块
|
|
CLUBS = 'c' # 梅花
|
|
|
|
def __str__(self):
|
|
return self.value
|
|
|
|
class Rank(Enum):
|
|
TWO = (2, '2')
|
|
THREE = (3, '3')
|
|
FOUR = (4, '4')
|
|
FIVE = (5, '5')
|
|
SIX = (6, '6')
|
|
SEVEN = (7, '7')
|
|
EIGHT = (8, '8')
|
|
NINE = (9, '9')
|
|
TEN = (10, 'T')
|
|
JACK = (11, 'J')
|
|
QUEEN = (12, 'Q')
|
|
KING = (13, 'K')
|
|
ACE = (14, 'A')
|
|
|
|
def __new__(cls, value, symbol):
|
|
obj = object.__new__(cls)
|
|
obj._value_ = value
|
|
obj.numeric_value = value
|
|
obj.symbol = symbol
|
|
return obj
|
|
|
|
def __str__(self):
|
|
return self.symbol
|
|
|
|
def __eq__(self, other):
|
|
if isinstance(other, Rank):
|
|
return self.numeric_value == other.numeric_value
|
|
return NotImplemented
|
|
|
|
def __lt__(self, other):
|
|
if isinstance(other, Rank):
|
|
return self.numeric_value < other.numeric_value
|
|
return NotImplemented
|
|
|
|
def __hash__(self):
|
|
return hash(self.numeric_value)
|
|
|
|
|
|
@total_ordering
|
|
class ShortDeckRank(Enum):
|
|
"""
|
|
shortdeck不包含2,3,4,5点数
|
|
"""
|
|
SIX = (6, '6')
|
|
SEVEN = (7, '7')
|
|
EIGHT = (8, '8')
|
|
NINE = (9, '9')
|
|
TEN = (10, 'T')
|
|
JACK = (11, 'J')
|
|
QUEEN = (12, 'Q')
|
|
KING = (13, 'K')
|
|
ACE = (14, 'A')
|
|
|
|
def __new__(cls, value, symbol):
|
|
obj = object.__new__(cls)
|
|
obj._value_ = value
|
|
obj.numeric_value = value
|
|
obj.symbol = symbol
|
|
return obj
|
|
|
|
def __str__(self):
|
|
return self.symbol
|
|
|
|
def __eq__(self, other):
|
|
if isinstance(other, ShortDeckRank):
|
|
return self.numeric_value == other.numeric_value
|
|
return NotImplemented
|
|
|
|
def __lt__(self, other):
|
|
if isinstance(other, ShortDeckRank):
|
|
return self.numeric_value < other.numeric_value
|
|
return NotImplemented
|
|
|
|
def __hash__(self):
|
|
return hash(self.numeric_value)
|
|
|
|
|
|
@total_ordering
|
|
class Card:
|
|
"""
|
|
通用卡片类,支持标准扑克和短牌扑克
|
|
"""
|
|
|
|
def __init__(self, rank: Union[Rank, 'ShortDeckRank'], suit: Suit):
|
|
self.rank = rank
|
|
self.suit = suit
|
|
|
|
def get_rank(self) -> Union[Rank, 'ShortDeckRank']:
|
|
return self.rank
|
|
|
|
def get_suit(self) -> Suit:
|
|
return self.suit
|
|
|
|
def is_short_deck(self) -> bool:
|
|
return isinstance(self.rank, ShortDeckRank)
|
|
|
|
def __str__(self):
|
|
return f"{self.rank}{self.suit}"
|
|
|
|
def __eq__(self, other):
|
|
if isinstance(other, Card):
|
|
self_value = getattr(self.rank, 'numeric_value', self.rank.value)
|
|
other_value = getattr(other.rank, 'numeric_value', other.rank.value)
|
|
return self_value == other_value and self.suit == other.suit
|
|
return NotImplemented
|
|
|
|
def __lt__(self, other):
|
|
if isinstance(other, Card):
|
|
self_value = getattr(self.rank, 'numeric_value', self.rank.value)
|
|
other_value = getattr(other.rank, 'numeric_value', other.rank.value)
|
|
|
|
if self_value != other_value:
|
|
return self_value < other_value
|
|
return self.suit.value < other.suit.value
|
|
return NotImplemented
|
|
|
|
@staticmethod
|
|
def _find_rank(rank_char, is_short_deck):
|
|
if is_short_deck:
|
|
# 在ShortDeckRank中查找
|
|
for r in ShortDeckRank:
|
|
if r.symbol == rank_char:
|
|
return r
|
|
else:
|
|
# 在Rank中查找
|
|
for r in Rank:
|
|
if r.symbol == rank_char:
|
|
return r
|
|
return None
|
|
|
|
@classmethod
|
|
def create_card(cls, card_str, is_short_deck=False) -> 'Card':
|
|
"""创建卡片,支持标准扑克和短牌扑克"""
|
|
if len(card_str) != 2:
|
|
raise ValueError(f"Invalid card string: {card_str}")
|
|
|
|
rank_char = card_str[0]
|
|
suit_char = card_str[1].lower()
|
|
|
|
# 查找rank
|
|
rank = cls._find_rank(rank_char, is_short_deck)
|
|
if rank is None:
|
|
rank_type = "short deck" if is_short_deck else "standard"
|
|
raise ValueError(f"Invalid rank for {rank_type}: {rank_char}")
|
|
|
|
# 查找suit
|
|
suit = None
|
|
for s in Suit:
|
|
if s.value == suit_char:
|
|
suit = s
|
|
break
|
|
|
|
if suit is None:
|
|
raise ValueError(f"Invalid suit: {suit_char}")
|
|
|
|
return cls(rank, suit)
|
|
|
|
@classmethod
|
|
def parse_cards(cls, cards_str, is_short_deck=False) -> List['Card']:
|
|
"""
|
|
从字符串拆解多张牌,支持标准扑克和短牌扑克
|
|
例如: "AsKs AhAdAc6s7s"
|
|
"""
|
|
cards_str = cards_str.strip()
|
|
if not cards_str:
|
|
return []
|
|
|
|
# 将字符串分割成单独的牌
|
|
card_strings = []
|
|
i = 0
|
|
while i < len(cards_str):
|
|
if cards_str[i].isspace():
|
|
i += 1
|
|
continue
|
|
|
|
if i + 1 < len(cards_str):
|
|
card_str = cards_str[i:i+2]
|
|
card_strings.append(card_str)
|
|
i += 2
|
|
else:
|
|
raise ValueError(f"Invalid card format at position {i}")
|
|
|
|
return [cls.create_card(card_str, is_short_deck) for card_str in card_strings]
|
|
@classmethod
|
|
def parseLongCards(cls, cards_str) -> List['Card']:
|
|
return cls.parse_cards(cards_str, is_short_deck=False)
|
|
|
|
@classmethod
|
|
def parse_short_deck_cards(cls, cards_str) -> List['Card']:
|
|
return cls.parse_cards(cards_str, is_short_deck=True)
|
|
|