diff --git a/README.md b/README.md index b9e221e..ae37565 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,6 @@ -# Poker Hand Evaluation Program +# Poker Task1 -一个用Python实现的扑克牌手牌评估程序,能够从7张牌中找出最佳的5张牌组合并返回手牌排名。 - -## 功能特性 - -- **完整的数据结构**:实现了Card、Deck、HandRanking等核心类 -- **字符串解析**:支持从字符串格式解析扑克牌(如 "AsKs AhAdAc6s7s") -- **手牌评估**:支持所有标准扑克手牌类型的识别和排名 -- **最佳组合选择**:从7张牌中自动选择最佳的5张牌组合 -- **全面测试**:包含完整的单元测试套件 +实现从7张牌中找出最佳的5张牌组合并返回handranking。 ## 支持的手牌类型 @@ -23,8 +15,6 @@ 9. **一对** (One Pair) - 一个对子 10. **高牌** (High Card) - 没有组合的单张高牌 -## 安装和使用 - ### 环境要求 - Python 3.13+ - uv 包管理器 @@ -53,8 +43,6 @@ python main.py "JsJhJdQcQs2h3d" - 第一个字符是点数:`2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `T`, `J`, `Q`, `K`, `A` - 第二个字符是花色:`s`(黑桃), `h`(红桃), `d`(方块), `c`(梅花) -牌之间可以用空格分隔,也可以连续书写。 - ### 运行测试 ```bash @@ -65,113 +53,11 @@ python run_tests.py pytest tests/ -v ``` -## 项目结构 - -``` -poker_emd_task/ -├── poker/ # 核心模块 -│ ├── __init__.py # 模块初始化 -│ ├── card.py # Card、Rank、Suit类 -│ ├── deck.py # Deck类 -│ ├── hand_ranking.py # HandRanking、HandType类 -│ └── hand_evaluator.py # HandEvaluator类(核心算法) -├── tests/ # 测试文件 -│ ├── test_card.py -│ ├── test_deck.py -│ ├── test_hand_ranking.py -│ ├── test_hand_evaluator.py -│ └── test_integration.py -├── main.py # 主程序入口 -├── run_tests.py # 简化的测试运行器 -├── pyproject.toml # 项目配置 -└── README.md # 项目说明 -``` - -## 设计特点 - -### 核心数据结构 - -- **Card类**:表示单张扑克牌,包含点数和花色 -- **Rank枚举**:定义牌的点数,支持比较操作 -- **Suit枚举**:定义牌的花色 -- **HandType枚举**:定义所有手牌类型及其强度 -- **HandRanking类**:表示手牌评估结果,包含类型和关键牌 -- **Deck类**:表示一副标准52张牌 -- **HandEvaluator类**:核心算法,评估手牌并选择最佳组合 - -### 算法实现 - -1. **穷举法**:从7张牌中穷举所有可能的5张牌组合(21种) -2. **模式识别**:对每个5张牌组合识别手牌类型 -3. **排名比较**:选择强度最高的手牌组合 -4. **特殊处理**:正确处理A-2-3-4-5轮子顺子等特殊情况 - -### 错误处理 - -- 输入验证:检查牌数是否为7张 -- 格式验证:验证每张牌的格式是否正确 -- 范围验证:确保点数和花色在有效范围内 -- 友好错误信息:提供清晰的错误提示 - -## 示例用法 - -```python -from poker.hand_evaluator import HandEvaluator -from poker.card import Card, Rank, Suit - -# 方式1:从字符串评估 -ranking = HandEvaluator.evaluate_from_input("AsKs AhAdAc6s7s") -print(ranking) # Quad(A) - -# 方式2:从Card对象评估 -cards = [ - Card(Rank.ACE, Suit.SPADES), - Card(Rank.KING, Suit.SPADES), - # ... 更多牌 -] -ranking = HandEvaluator.evaluate_hand(cards) -print(ranking) -``` - -## 测试覆盖 - -项目包含全面的测试套件,覆盖: -- 所有核心类的功能测试 -- 各种手牌类型的识别测试 -- 边界条件和错误情况测试 -- 集成测试和端到端测试 - -运行测试确保所有功能正常工作: - -```bash -python run_tests.py -``` - -预期输出: -``` -Running poker hand evaluation tests... - -Testing Card functionality... -✓ Card tests passed -Testing hand parsing... -✓ Hand parsing tests passed -Testing hand evaluation... -✓ Hand evaluation tests passed -Testing wheel straight... -✓ Wheel straight test passed -Testing deck functionality... -✓ Deck tests passed -Testing error handling... -✓ Error handling tests passed - -Test Results: 6 passed, 0 failed -All tests passed! 🎉 -``` ## 技术栈 - **语言**:Python 3.13 -- **包管理**:uv / poetry +- **包管理**:uv - **测试**:自定义测试框架(也支持pytest) - **开发环境**:VS Code diff --git a/main.py b/main.py index cf88e25..a30118d 100644 --- a/main.py +++ b/main.py @@ -1,31 +1,17 @@ #!/usr/bin/env python3 -""" -Poker hand evaluation program -Takes 7 cards as string input and outputs the best HandRanking -""" - import sys from poker.hand_evaluator import HandEvaluator def main(): if len(sys.argv) != 2: - print("Usage: python main.py \"<7 cards>\"") print("Example: python main.py \"AsKs AhAdAc6s7s\"") sys.exit(1) cards_str = sys.argv[1] - try: - # 评估手牌 - hand_ranking = HandEvaluator.evaluate_from_input(cards_str) - - # 输出结果 - print(hand_ranking) - - except Exception as e: - print(f"Error: {e}") - sys.exit(1) + hand_ranking = HandEvaluator.evaluateFromInput(cards_str) + print(hand_ranking) if __name__ == "__main__": diff --git a/poker/card.py b/poker/card.py index 70aadfa..023f28b 100644 --- a/poker/card.py +++ b/poker/card.py @@ -1,7 +1,4 @@ -""" -Card module for poker game -""" - +from functools import total_ordering from enum import Enum from typing import List, Tuple, Optional @@ -15,7 +12,6 @@ class Suit(Enum): def __str__(self): return self.value - class Rank(Enum): TWO = (2, '2') THREE = (3, '3') @@ -41,12 +37,21 @@ class Rank(Enum): 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 not isinstance(other, Rank): - return NotImplemented - return self.numeric_value < other.numeric_value + if isinstance(other, Rank): + 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: Rank, suit: Suit): self.rank = rank @@ -55,22 +60,20 @@ class Card: def __str__(self): return f"{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 + if isinstance(other, Card): + return self.rank == other.rank and self.suit == other.suit + return NotImplemented def __lt__(self, other): - if not isinstance(other, Card): - return NotImplemented - return self.rank.numeric_value < other.rank.numeric_value + if isinstance(other, Card): + if self.rank != other.rank: + return self.rank < other.rank + return self.suit.value < other.suit.value + return NotImplemented @classmethod - def create_card(cls, card_str: str) -> 'Card': - """ - 从字符串创建Card对象,例如 "As", "Kh", "2c" - """ + def createCard(cls, card_str) -> 'Card': if len(card_str) != 2: raise ValueError(f"Invalid card string: {card_str}") @@ -100,9 +103,9 @@ class Card: return cls(rank, suit) @classmethod - def parse_cards(cls, cards_str: str) -> List['Card']: + def parseCards(cls, cards_str) -> List['Card']: """ - 从字符串解析多张牌,例如 "AsKs AhAdAc6s7s" + 从字符串拆解多张牌, "AsKs AhAdAc6s7s" """ cards_str = cards_str.strip() if not cards_str: @@ -122,8 +125,4 @@ class Card: 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 \ No newline at end of file + return [cls.createCard(card_str) for card_str in card_strings] \ No newline at end of file diff --git a/poker/hand_evaluator.py b/poker/hand_evaluator.py index 88878de..de9491e 100644 --- a/poker/hand_evaluator.py +++ b/poker/hand_evaluator.py @@ -1,7 +1,3 @@ -""" -Hand evaluator module for poker game -""" - from typing import List, Tuple, Dict from collections import Counter from itertools import combinations @@ -10,14 +6,10 @@ from .hand_ranking import HandRanking, HandType class HandEvaluator: - """ - 手牌评估器类,用于评估扑克手牌 - """ - @staticmethod - def evaluate_hand(cards: List[Card]) -> HandRanking: + def evaluateHand(cards) -> HandRanking: """ - 从7张牌中评估出最好的5张牌组合 + 从7张牌中找出最好的5张牌组合 """ if len(cards) != 7: raise ValueError(f"Expected 7 cards, got {len(cards)}") @@ -25,23 +17,19 @@ class HandEvaluator: best_ranking = None best_cards = None - # 尝试所有可能的5张牌组合 + # 所有可能的5张牌组合 for five_cards in combinations(cards, 5): - ranking = HandEvaluator._evaluate_five_cards(list(five_cards)) + ranking = HandEvaluator.evaluate5Cards(list(five_cards)) if best_ranking is None or ranking > best_ranking: best_ranking = ranking best_cards = list(five_cards) - # 更新最佳ranking的cards best_ranking.cards = best_cards return best_ranking @staticmethod - def _evaluate_five_cards(cards: List[Card]) -> HandRanking: - """ - 评估5张牌的手牌类型 - """ + def evaluate5Cards(cards) -> HandRanking: if len(cards) != 5: raise ValueError(f"Expected 5 cards, got {len(cards)}") @@ -54,11 +42,11 @@ class HandEvaluator: rank_counts = Counter(ranks) count_values = sorted(rank_counts.values(), reverse=True) - # 检查是否是同花 + # 同花 is_flush = len(set(suits)) == 1 - # 检查是否是顺子 - is_straight, straight_high = HandEvaluator._is_straight(ranks) + # 顺子 + is_straight, straight_high = HandEvaluator._isStraight(ranks) # 根据牌型返回相应的HandRanking if is_straight and is_flush: @@ -102,10 +90,7 @@ class HandEvaluator: return HandRanking(HandType.HIGH_CARD, ranks, sorted_cards) @staticmethod - def _is_straight(ranks: List[Rank]) -> Tuple[bool, Rank]: - """ - 检查是否是顺子,返回(是否是顺子, 最高牌) - """ + def _isStraight(ranks) -> Tuple[bool, Rank]: # 排序点数值 values = sorted([rank.numeric_value for rank in ranks], reverse=True) @@ -125,16 +110,13 @@ class HandEvaluator: break return True, highest_rank - # 检查A-2-3-4-5的特殊顺子(轮子) + # A-2-3-4-5特殊顺子 if values == [14, 5, 4, 3, 2]: # A, 5, 4, 3, 2 - return True, Rank.FIVE # 在轮子中,5是最高牌 + return True, Rank.FIVE # 5是最高牌 return False, None @staticmethod - def evaluate_from_input(cards_str: str) -> HandRanking: - """ - 从字符串评估手牌,例如 "AsKs AhAdAc6s7s" - """ - cards = Card.parse_cards(cards_str) - return HandEvaluator.evaluate_hand(cards) \ No newline at end of file + def evaluateFromInput(cards_str) -> HandRanking: + cards = Card.parseCards(cards_str) + return HandEvaluator.evaluateHand(cards) \ No newline at end of file diff --git a/poker/hand_ranking.py b/poker/hand_ranking.py index 199321b..6e50ae8 100644 --- a/poker/hand_ranking.py +++ b/poker/hand_ranking.py @@ -1,16 +1,11 @@ -""" -Hand ranking module for poker game -""" - from enum import Enum +from functools import total_ordering from typing import List, Tuple from .card import Card, Rank +@total_ordering class HandType(Enum): - """ - 手牌类型枚举,按强度排序 - """ HIGH_CARD = (1, "High Card") ONE_PAIR = (2, "Pair") TWO_PAIR = (3, "Two Pair") @@ -33,40 +28,26 @@ class HandType(Enum): return self.type_name def __lt__(self, other): - if not isinstance(other, HandType): - return NotImplemented - return self.strength < other.strength + if isinstance(other, HandType): + return self.strength < other.strength + return NotImplemented - def __le__(self, other): - if not isinstance(other, HandType): - return NotImplemented - return self.strength <= other.strength + def __eq__(self, other): + if isinstance(other, HandType): + return self.strength == other.strength + return NotImplemented - def __gt__(self, other): - if not isinstance(other, HandType): - return NotImplemented - return self.strength > other.strength - - def __ge__(self, other): - if not isinstance(other, HandType): - return NotImplemented - return self.strength >= other.strength + def __hash__(self): + return hash(self.strength) class HandRanking: - """ - 手牌排名类,包含手牌类型和关键牌 - """ - def __init__(self, hand_type: HandType, key_ranks: List[Rank], cards: List[Card]): self.hand_type = hand_type self.key_ranks = key_ranks # 用于比较的关键点数 - self.cards = cards # 组成这个排名的5张牌 + self.cards = cards # 组成这个ranking的5张牌 def __str__(self): - """ - 返回手牌排名的字符串表示 - """ if self.hand_type == HandType.FOUR_OF_A_KIND: return f"Quad({self.key_ranks[0].symbol})" elif self.hand_type == HandType.FULL_HOUSE: @@ -91,35 +72,18 @@ class HandRanking: else: # HIGH_CARD return f"High Card({self.key_ranks[0].symbol})" - def __repr__(self): - return f"HandRanking({self.hand_type}, {[r.symbol for r in self.key_ranks]})" - def __eq__(self, other): if not isinstance(other, HandRanking): return False - return (self.hand_type == other.hand_type and - self.key_ranks == other.key_ranks) + return (self.hand_type == other.hand_type and self.key_ranks == other.key_ranks) def __lt__(self, other): if not isinstance(other, HandRanking): return NotImplemented - - # 首先比较手牌类型 if self.hand_type != other.hand_type: return self.hand_type < other.hand_type - - # 如果手牌类型相同,比较关键点数 + # 手牌类型相同比较点数 for self_rank, other_rank in zip(self.key_ranks, other.key_ranks): if self_rank != other_rank: return self_rank < other_rank - - return False # 完全相等 - - def __le__(self, other): - return self == other or self < other - - def __gt__(self, other): - return not self <= other - - def __ge__(self, other): - return not self < other \ No newline at end of file + return False \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 8ad3197..ed7c748 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,13 +8,6 @@ dependencies = [ "pytest>=8.4.2", ] -[project.optional-dependencies] -dev = ["pytest>=7.0.0"] - -[build-system] -requires = ["setuptools", "wheel"] -build-backend = "setuptools.build_meta" - [tool.pytest.ini_options] testpaths = ["tests"] python_files = ["test_*.py"] diff --git a/run_tests.py b/run_tests.py index 5a861aa..8a07862 100644 --- a/run_tests.py +++ b/run_tests.py @@ -19,7 +19,7 @@ def test_basic_card_functionality(): assert str(card) == "As", f"Expected 'As', got '{str(card)}'" # Test card parsing - parsed_card = Card.from_string("Kh") + parsed_card = Card.createCard("Kh") assert parsed_card.rank == Rank.KING assert parsed_card.suit == Suit.HEARTS @@ -35,7 +35,7 @@ def test_hand_parsing(): """Test hand parsing from string""" print("Testing hand parsing...") - cards = Card.parse_cards("AsKs AhAdAc6s7s") + cards = Card.parseCards("AsKs AhAdAc6s7s") assert len(cards) == 7, f"Expected 7 cards, got {len(cards)}" assert str(cards[0]) == "As" assert str(cards[6]) == "7s" @@ -61,7 +61,7 @@ def test_hand_evaluation_examples(): ] for cards_str, expected_str, expected_type in test_cases: - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) actual_str = str(ranking) assert ranking.hand_type == expected_type, f"Wrong hand type for {cards_str}: expected {expected_type}, got {ranking.hand_type}" @@ -75,7 +75,7 @@ def test_wheel_straight(): print("Testing wheel straight...") cards_str = "As2h3d4c5h7s8s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.STRAIGHT assert ranking.key_ranks[0] == Rank.FIVE, "In wheel straight, 5 should be the high card" @@ -90,14 +90,14 @@ def test_error_handling(): # Test invalid card string try: - Card.from_string("Xx") + Card.createCard("Xx") assert False, "Should have raised ValueError for invalid card" except ValueError: pass # Expected # Test wrong number of cards try: - HandEvaluator.evaluate_from_input("AsKh") + HandEvaluator.evaluateFromInput("AsKh") assert False, "Should have raised ValueError for wrong number of cards" except ValueError: pass # Expected diff --git a/tests/test_card.py b/tests/test_card.py index 2edf9c6..91b18df 100644 --- a/tests/test_card.py +++ b/tests/test_card.py @@ -5,37 +5,19 @@ Tests for Card, Rank, and Suit classes import pytest from poker.card import Card, Rank, Suit - +# card.py测试 class TestRank: """Test cases for Rank enum""" - + def test_rank_values(self): """Test rank numeric values""" assert Rank.TWO.numeric_value == 2 assert Rank.ACE.numeric_value == 14 - assert Rank.KING.numeric_value == 13 - assert Rank.JACK.numeric_value == 11 def test_rank_symbols(self): """Test rank symbols""" assert Rank.TWO.symbol == '2' assert Rank.ACE.symbol == 'A' - assert Rank.KING.symbol == 'K' - assert Rank.TEN.symbol == 'T' - - def test_rank_comparison(self): - """Test rank comparison operations""" - assert Rank.TWO < Rank.THREE - assert Rank.KING < Rank.ACE - assert Rank.JACK > Rank.TEN - assert Rank.ACE >= Rank.KING - assert Rank.TWO <= Rank.TWO - - def test_rank_str(self): - """Test string representation""" - assert str(Rank.ACE) == 'A' - assert str(Rank.KING) == 'K' - assert str(Rank.TWO) == '2' class TestSuit: @@ -47,11 +29,7 @@ class TestSuit: assert Suit.HEARTS.value == 'h' assert Suit.DIAMONDS.value == 'd' assert Suit.CLUBS.value == 'c' - - def test_suit_str(self): - """Test string representation""" - assert str(Suit.SPADES) == 's' - assert str(Suit.HEARTS) == 'h' + class TestCard: @@ -71,60 +49,42 @@ class TestCard: card2 = Card(Rank.KING, Suit.HEARTS) assert str(card2) == 'Kh' - def test_card_equality(self): - """Test card equality""" - card1 = Card(Rank.ACE, Suit.SPADES) - card2 = Card(Rank.ACE, Suit.SPADES) - card3 = Card(Rank.ACE, Suit.HEARTS) - - assert card1 == card2 - assert card1 != card3 - - def test_card_comparison(self): - """Test card comparison (by rank)""" - ace_spades = Card(Rank.ACE, Suit.SPADES) - king_hearts = Card(Rank.KING, Suit.HEARTS) - two_clubs = Card(Rank.TWO, Suit.CLUBS) - - assert two_clubs < king_hearts - assert king_hearts < ace_spades - assert not (ace_spades < king_hearts) def test_from_string_valid(self): """Test creating card from valid string""" - card = Card.from_string("As") + card = Card.createCard("As") assert card.rank == Rank.ACE assert card.suit == Suit.SPADES - - card2 = Card.from_string("Kh") + + card2 = Card.createCard("Kh") assert card2.rank == Rank.KING assert card2.suit == Suit.HEARTS - - card3 = Card.from_string("2c") + + card3 = Card.createCard("2c") assert card3.rank == Rank.TWO assert card3.suit == Suit.CLUBS - - card4 = Card.from_string("Td") + + card4 = Card.createCard("Td") assert card4.rank == Rank.TEN assert card4.suit == Suit.DIAMONDS def test_from_string_invalid(self): """Test creating card from invalid string""" with pytest.raises(ValueError): - Card.from_string("A") # Too short + Card.createCard("A") # Too short with pytest.raises(ValueError): - Card.from_string("Asx") # Too long + Card.createCard("Asx") # Too long with pytest.raises(ValueError): - Card.from_string("Xs") # Invalid rank + Card.createCard("Xs") # Invalid rank with pytest.raises(ValueError): - Card.from_string("Ax") # Invalid suit + Card.createCard("Ax") # Invalid suit def test_parse_cards_valid(self): """Test parsing multiple cards from string""" - cards = Card.parse_cards("AsKs AhAdAc6s7s") + cards = Card.parseCards("AsKs AhAdAc6s7s") assert len(cards) == 7 assert str(cards[0]) == "As" assert str(cards[1]) == "Ks" @@ -133,23 +93,23 @@ class TestCard: def test_parse_cards_with_spaces(self): """Test parsing cards with various spacing""" - cards = Card.parse_cards("As Ks Ah Ad Ac 6s 7s") + cards = Card.parseCards("As Ks Ah Ad Ac 6s 7s") assert len(cards) == 7 assert str(cards[0]) == "As" assert str(cards[6]) == "7s" def test_parse_cards_empty(self): """Test parsing empty string""" - cards = Card.parse_cards("") + cards = Card.parseCards("") assert len(cards) == 0 - - cards = Card.parse_cards(" ") + + cards = Card.parseCards(" ") assert len(cards) == 0 def test_parse_cards_invalid(self): """Test parsing invalid card strings""" with pytest.raises(ValueError): - Card.parse_cards("AsKs A") # Incomplete card - + Card.parseCards("AsKs A") # Incomplete card + with pytest.raises(ValueError): - Card.parse_cards("AsKs Ax") # Invalid suit \ No newline at end of file + Card.parseCards("AsKs Ax") # Invalid suit \ No newline at end of file diff --git a/tests/test_hand_evaluator.py b/tests/test_hand_evaluator.py index 9f1d721..0c0b2f0 100644 --- a/tests/test_hand_evaluator.py +++ b/tests/test_hand_evaluator.py @@ -14,7 +14,7 @@ class TestHandEvaluator: def test_royal_flush(self): """Test royal flush detection""" cards_str = "AhKhQhJhTh2c3c" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.ROYAL_FLUSH assert str(ranking) == "Royal Flush" @@ -22,7 +22,7 @@ class TestHandEvaluator: def test_straight_flush(self): """Test straight flush detection""" cards_str = "2h3h4h5h6h7s8s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.STRAIGHT_FLUSH assert str(ranking) == "Straight Flush(6 high)" @@ -30,7 +30,7 @@ class TestHandEvaluator: def test_four_of_a_kind(self): """Test four of a kind detection""" cards_str = "AsKs AhAdAc6s7s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.FOUR_OF_A_KIND assert str(ranking) == "Quad(A)" @@ -38,7 +38,7 @@ class TestHandEvaluator: def test_full_house(self): """Test full house detection""" cards_str = "AsAhAd KsKh6s7s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.FULL_HOUSE assert "Full House(A over K)" in str(ranking) @@ -46,7 +46,7 @@ class TestHandEvaluator: def test_flush(self): """Test flush detection""" cards_str = "AhKh6h4h2h7s8s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.FLUSH assert "Flush(A high)" in str(ranking) @@ -54,7 +54,7 @@ class TestHandEvaluator: def test_straight(self): """Test straight detection""" cards_str = "As2h3d4c5h7s8s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.STRAIGHT assert str(ranking) == "Straight(5 high)" # A-2-3-4-5 wheel @@ -62,7 +62,7 @@ class TestHandEvaluator: def test_straight_ace_high(self): """Test straight with ace high""" cards_str = "AsTsJhQdKh7s8s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.STRAIGHT assert str(ranking) == "Straight(A high)" @@ -70,7 +70,7 @@ class TestHandEvaluator: def test_three_of_a_kind(self): """Test three of a kind detection""" cards_str = "AsAhAd6s7h8s9s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.THREE_OF_A_KIND assert str(ranking) == "Three of a Kind(A)" @@ -78,7 +78,7 @@ class TestHandEvaluator: def test_two_pair(self): """Test two pair detection""" cards_str = "AsAh6d6s7h8s9s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.TWO_PAIR assert "Two Pair(A and 6)" in str(ranking) @@ -86,7 +86,7 @@ class TestHandEvaluator: def test_one_pair(self): """Test one pair detection""" cards_str = "AsAh6d4s2h3cJd" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.ONE_PAIR assert str(ranking) == "Pair(A)" @@ -94,7 +94,7 @@ class TestHandEvaluator: def test_high_card(self): """Test high card detection""" cards_str = "As6h4d8s9hJdKc" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.HIGH_CARD assert str(ranking) == "High Card(A)" @@ -102,7 +102,7 @@ class TestHandEvaluator: def test_wheel_straight(self): """Test A-2-3-4-5 straight (wheel)""" cards_str = "As2h3d4c5h7s8s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.STRAIGHT assert ranking.key_ranks[0] == Rank.FIVE # 5 is high in wheel @@ -110,21 +110,21 @@ class TestHandEvaluator: def test_invalid_input_not_seven_cards(self): """Test error handling for wrong number of cards""" with pytest.raises(ValueError): - HandEvaluator.evaluate_from_input("AsKh") + HandEvaluator.evaluateFromInput("AsKh") with pytest.raises(ValueError): - HandEvaluator.evaluate_from_input("AsKhQdJc9h8s7d6c") + HandEvaluator.evaluateFromInput("AsKhQdJc9h8s7d6c") def test_invalid_card_format(self): """Test error handling for invalid card format""" with pytest.raises(ValueError): - HandEvaluator.evaluate_from_input("AsKhQdJcXh8s7d") + HandEvaluator.evaluateFromInput("AsKhQdJcXh8s7d") def test_seven_cards_best_five_selected(self): """Test that best 5 cards are selected from 7""" # Should pick the straight flush over the pair cards_str = "2h3h4h5h6hAsAd" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.STRAIGHT_FLUSH assert str(ranking) == "Straight Flush(6 high)" @@ -132,7 +132,7 @@ class TestHandEvaluator: def test_multiple_possible_straights(self): """Test selecting highest straight from multiple possibilities""" cards_str = "As2h3d4c5h6s7s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.STRAIGHT # Should pick 3-4-5-6-7 over A-2-3-4-5 @@ -141,7 +141,7 @@ class TestHandEvaluator: def test_multiple_possible_flushes(self): """Test selecting best flush from multiple suits""" cards_str = "AhKh6h4h2h7s8s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert ranking.hand_type == HandType.FLUSH assert ranking.key_ranks[0] == Rank.ACE @@ -150,12 +150,11 @@ class TestHandEvaluator: """Test evaluating exactly 5 cards""" cards = [ Card(Rank.ACE, Suit.SPADES), - Card(Rank.ACE, Suit.HEARTS), + Card(Rank.ACE, Suit.HEARTS), Card(Rank.ACE, Suit.DIAMONDS), Card(Rank.ACE, Suit.CLUBS), Card(Rank.KING, Suit.SPADES) ] - ranking = HandEvaluator._evaluate_five_cards(cards) - + ranking = HandEvaluator.evaluate5Cards(cards) assert ranking.hand_type == HandType.FOUR_OF_A_KIND assert ranking.key_ranks[0] == Rank.ACE \ No newline at end of file diff --git a/tests/test_hand_ranking.py b/tests/test_hand_ranking.py index 7b257dd..b0f5367 100644 --- a/tests/test_hand_ranking.py +++ b/tests/test_hand_ranking.py @@ -90,48 +90,25 @@ class TestHandRanking: def test_three_of_a_kind_string_representation(self): """Test string representation for three of a kind""" - cards = [Card(Rank.ACE, Suit.SPADES)] * 5 # Dummy cards + cards = [Card(Rank.ACE, Suit.SPADES)] * 5 ranking = HandRanking(HandType.THREE_OF_A_KIND, [Rank.ACE], cards) assert str(ranking) == "Three of a Kind(A)" def test_two_pair_string_representation(self): """Test string representation for two pair""" - cards = [Card(Rank.ACE, Suit.SPADES)] * 5 # Dummy cards + cards = [Card(Rank.ACE, Suit.SPADES)] * 5 ranking = HandRanking(HandType.TWO_PAIR, [Rank.ACE, Rank.KING], cards) assert str(ranking) == "Two Pair(A and K)" def test_one_pair_string_representation(self): """Test string representation for one pair""" - cards = [Card(Rank.ACE, Suit.SPADES)] * 5 # Dummy cards + cards = [Card(Rank.ACE, Suit.SPADES)] * 5 ranking = HandRanking(HandType.ONE_PAIR, [Rank.ACE], cards) assert str(ranking) == "Pair(A)" def test_high_card_string_representation(self): """Test string representation for high card""" - cards = [Card(Rank.ACE, Suit.SPADES)] * 5 # Dummy cards + cards = [Card(Rank.ACE, Suit.SPADES)] * 5 ranking = HandRanking(HandType.HIGH_CARD, [Rank.ACE], cards) assert str(ranking) == "High Card(A)" - - def test_hand_ranking_equality(self): - """Test hand ranking equality""" - cards = [Card(Rank.ACE, Suit.SPADES)] * 5 # Dummy cards - ranking1 = HandRanking(HandType.FOUR_OF_A_KIND, [Rank.ACE, Rank.KING], cards) - ranking2 = HandRanking(HandType.FOUR_OF_A_KIND, [Rank.ACE, Rank.KING], cards) - ranking3 = HandRanking(HandType.FOUR_OF_A_KIND, [Rank.KING, Rank.ACE], cards) - - assert ranking1 == ranking2 - assert ranking1 != ranking3 - - def test_hand_ranking_comparison(self): - """Test hand ranking comparison""" - cards = [Card(Rank.ACE, Suit.SPADES)] * 5 # Dummy cards - - # Different hand types - quad_aces = HandRanking(HandType.FOUR_OF_A_KIND, [Rank.ACE], cards) - full_house = HandRanking(HandType.FULL_HOUSE, [Rank.ACE], cards) - assert full_house < quad_aces - - # Same hand type, different ranks - quad_aces = HandRanking(HandType.FOUR_OF_A_KIND, [Rank.ACE], cards) - quad_kings = HandRanking(HandType.FOUR_OF_A_KIND, [Rank.KING], cards) - assert quad_kings < quad_aces \ No newline at end of file + \ No newline at end of file diff --git a/tests/test_integration.py b/tests/test_integration.py index 6c7a2dc..96b34cd 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -15,7 +15,7 @@ class TestMainProgram: def test_example_input(self): """Test the example input from the requirements""" cards_str = "AsKs AhAdAc6s7s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert str(ranking) == "Quad(A)" @@ -35,19 +35,18 @@ class TestMainProgram: ] for cards_str, expected_result in test_cases: - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert str(ranking) == expected_result, f"Failed for {cards_str}" def test_wheel_straight(self): - """Test A-2-3-4-5 straight (wheel)""" + """Test A-2-3-4-5 straight""" cards_str = "As2h3d4c5h7s8s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert str(ranking) == "Straight(5 high)" def test_different_card_formats(self): """Test different ways of writing the same cards""" - # These should all represent the same hand formats = [ "AsKsAhAdAc6s7s", "As Ks Ah Ad Ac 6s 7s", @@ -57,30 +56,29 @@ class TestMainProgram: expected_result = "Quad(A)" for cards_str in formats: - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert str(ranking) == expected_result def test_case_insensitive_suits(self): """Test that suits are case insensitive""" cards_str = "AsKsAhAdAc6s7s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert str(ranking) == "Quad(A)" def test_edge_cases(self): """Test edge cases and boundary conditions""" - # All same rank except one cards_str = "2s2h2d2c3s4h5d" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert str(ranking) == "Quad(2)" # Minimum straight cards_str = "As2h3d4c5h6s7s" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) # Should pick 3-4-5-6-7 over A-2-3-4-5 assert "Straight(7 high)" in str(ranking) # Maximum straight cards_str = "9sTsJhQdKhAsAd" - ranking = HandEvaluator.evaluate_from_input(cards_str) + ranking = HandEvaluator.evaluateFromInput(cards_str) assert str(ranking) == "Straight(A high)" \ No newline at end of file