149 lines
3.8 KiB
Python
149 lines
3.8 KiB
Python
"""
|
||
Card module for poker game
|
||
"""
|
||
|
||
from enum import Enum
|
||
from typing import List, Tuple, Optional
|
||
|
||
|
||
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 __lt__(self, other):
|
||
if not isinstance(other, Rank):
|
||
return NotImplemented
|
||
return self.numeric_value < other.numeric_value
|
||
|
||
def __le__(self, other):
|
||
if not isinstance(other, Rank):
|
||
return NotImplemented
|
||
return self.numeric_value <= other.numeric_value
|
||
|
||
def __gt__(self, other):
|
||
if not isinstance(other, Rank):
|
||
return NotImplemented
|
||
return self.numeric_value > other.numeric_value
|
||
|
||
def __ge__(self, other):
|
||
if not isinstance(other, Rank):
|
||
return NotImplemented
|
||
return self.numeric_value >= other.numeric_value
|
||
|
||
|
||
class Card:
|
||
def __init__(self, rank: Rank, suit: Suit):
|
||
self.rank = rank
|
||
self.suit = suit
|
||
|
||
def __str__(self):
|
||
return f"{self.rank}{self.suit}"
|
||
|
||
def __repr__(self):
|
||
return f"Card({self.rank}, {self.suit})"
|
||
|
||
def __eq__(self, other):
|
||
if not isinstance(other, Card):
|
||
return False
|
||
return self.rank == other.rank and self.suit == other.suit
|
||
|
||
def __hash__(self):
|
||
return hash((self.rank, self.suit))
|
||
|
||
def __lt__(self, other):
|
||
if not isinstance(other, Card):
|
||
return NotImplemented
|
||
return self.rank.numeric_value < other.rank.numeric_value
|
||
|
||
@classmethod
|
||
def create_card(cls, card_str: str) -> 'Card':
|
||
"""
|
||
从字符串创建Card对象,例如 "As", "Kh", "2c"
|
||
"""
|
||
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 = None
|
||
for r in Rank:
|
||
if r.symbol == rank_char:
|
||
rank = r
|
||
break
|
||
|
||
if rank is None:
|
||
raise ValueError(f"Invalid rank: {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: str) -> List['Card']:
|
||
"""
|
||
从字符串解析多张牌,例如 "AsKs AhAdAc6s7s"
|
||
"""
|
||
cards_str = cards_str.strip()
|
||
if 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}")
|
||
result = []
|
||
for card_str in card_strings:
|
||
card_tmp = cls.create_card(card_str)
|
||
result.append(card_tmp)
|
||
return result |