====== cs20pf22as05: Poker Hand ====== ===== Goals ===== * Practice with object-oriented design in Python. * Define a class that models a card-game object. ----- ====== Prerequisites ====== This assignment requires familiarity with the [[:lecture materials/]] presented in class through [[:lecture materials/week 05]]. ----- ====== Background ====== {{:poker_hand.jpg?nolink|Image of a five-card poker hand, specifically a royal flush with clubs}} There are [[https://en.wikipedia.org/wiki/List_of_poker_variants|many variants]] game of [[https://en.wikipedia.org/wiki/Pokep|poker]], most of which involve **hands** consisting of five cards from a standard 52-card deck. Hands are [[https://en.wikipedia.org/wiki/List_of_poker_hands|ranked by category]], e.g. //straight// or //two pair//. For the purposes of this assignment, a **card descriptor** shall be a **two-character string** consisting of the **rank** and **suit** of a card. ^ Rank characters | 23456789TJQKA | ^ Suit characters | ♠♣♥♦ | Here are ten example card descriptors: ''T♦ Q♦ 7♥ 3♦ K♠ 2♠ J♣ 2♣ K♥ 2♥'' ----- ====== Assignment ====== You shall define a class named ''PokerHand'' in a module named ''poker_hand''. ''PokerHand'' instances represent five-card poker hands and support various Python operators for easy interaction with the language, as demonstrated briefly in the REPL session below: >>> h1 = PokerHand(['4♠', '9♠', '2♣', '2♦', '9♥']) >>> h1.describe() 'two pair' >>> int(h1) 2 >>> h2 = PokerHand(['3♠', '3♣', '2♠', 'Q♣', '3♦']) >>> h2.describe() 'three of a kind' >>> int(h2) 3 >>> h1 < h2 True >>> PokerHand(['2♠', '5♠', 'A♥', '4♥', '3♦']) < PokerHand(['Q♠', 'J♠', 'K♣', 'A♠', 'T♥']) True ===== Specifications ===== Define your class with the starter code below, and fill in code for the methods as specified by the docstrings and doctests. Feel free to add other internal-only attributes (module-scoped variables, helper methods, etc.) in order to reduce redundant code. """ Classifying and ranking poker hands. Numeric ranks and rank descriptions are as follows: 0: high card 1: one pair 2: two pair 3: three of a kind 4: straight 5: flush 6: full house 7: four of a kind 8: straight flush 9: royal flush """ from __future__ import annotations # for self-referential type hints from collections.abc import Sequence # for type hints class PokerHand: """ Represents a hand of cards for 5-card poker. Card descriptors are two-character strings (RS: Rank and Suit). Valid ranks: 23456789TJQKA Valid suits: ♥♠♦♣ """ def __init__(self, cards: Sequence[str]): """ Initializes a poker hand from a sequence of card descriptors. >>> h = PokerHand(('6♦', 'J♦', '8♣', '4♦', 'T♣')) >>> int(h) 0 >>> h.describe() 'high card' >>> h2 = PokerHand('6♣ 2♣ 7♣ 5♣ 3♣'.split()) >>> int(h2) 5 >>> h2.describe() 'flush' >>> h < h2 True """ pass def __contains__(self, descriptor): """ Determines whether this hand contains the given descriptor. >>> '2♠' in PokerHand(['3♠', '3♣', '2♠', 'Q♣', '3♦']) True >>> 'Q♦' in PokerHand(['3♠', '3♣', '2♠', 'Q♣', '3♦']) False """ pass def __int__(self): """ Returns the integer rank for this hand (0 through 9—see class docstring). >>> hands = ['T♥ A♠ 2♦ 9♣ J♣', ... 'T♦ 6♦ 2♠ J♠ T♥', ... '6♣ 5♥ 8♠ 5♠ 6♥', ... '9♠ 9♦ Q♥ 9♥ A♥', ... '7♦ 4♠ 5♦ 6♦ 8♣', ... '5♠ T♠ J♠ 3♠ 2♠', ... 'Q♣ 7♣ 7♥ Q♠ Q♦', ... '4♥ 5♣ 5♥ 5♦ 5♠', ... '5♣ 4♣ 8♣ 6♣ 7♣', ... 'A♣ J♣ T♣ Q♣ K♣'] >>> list(map(int, [PokerHand(h.split()) for h in hands])) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] """ pass def __lt__(self, other: PokerHand): """Compares this hand with another by rank.""" pass def __le__(self, other: PokerHand): """Compares this hand with another by rank.""" pass def __gt__(self, other: PokerHand): """Compares this hand with another by rank.""" pass def __ge__(self, other: PokerHand): """Compares this hand with another by rank.""" pass def __eq__(self, other: PokerHand): """Compares this hand with another by rank.""" pass def __ne__(self, other: PokerHand): """Compares this hand with another by rank.""" pass def __repr__(self): """Returns a printable representation of this hand, suitable for eval().""" pass def __str__(self): """ Returns the nicely printable string representation of this hand: 'C1 C2 C3 C4 C5 (rank description)' >>> h = PokerHand(['7♦', '4♠', '5♦', '6♦', '8♣']) >>> print(h) 7♦ 4♠ 5♦ 6♦ 8♣ (straight) """ pass def describe(self) -> str: """ Returns the description of this hand's rank (see class docstring). >>> hands = ['T♥ A♠ 2♦ 9♣ J♣', ... 'T♦ 6♦ 2♠ J♠ T♥', ... '6♣ 5♥ 8♠ 5♠ 6♥', ... '9♠ 9♦ Q♥ 9♥ A♥', ... '7♦ 4♠ 5♦ 6♦ 8♣', ... '5♠ T♠ J♠ 3♠ 2♠', ... 'Q♣ 7♣ 7♥ Q♠ Q♦', ... '4♥ 5♣ 5♥ 5♦ 5♠', ... '5♣ 4♣ 8♣ 6♣ 7♣', ... 'A♣ J♣ T♣ Q♣ K♣'] >>> list(map(PokerHand.describe, [PokerHand(h.split()) for h in hands])) ['high card', 'one pair', 'two pair', 'three of a kind', 'straight', 'flush', 'full house', 'four of a kind', 'straight flush', 'royal flush'] """ pass ===== Test Data ===== File ''[[http://jeff.cis.cabrillo.edu/datasets/poker_hands|/srv/datasets/poker_hands]]'' contains descriptions and rankings of 1 million sample poker hands, e.g. here are 10 randomly selected lines: J♦ 2♥ 2♦ 5♠ 9♣ 1 4♦ 8♠ 7♥ 3♣ 4♠ 1 Q♦ 2♠ 7♣ T♠ 4♦ 0 9♠ 3♦ 9♥ 3♥ 7♥ 2 2♥ 5♦ 5♠ 6♥ 2♦ 2 A♣ 4♠ 5♠ 2♦ J♦ 0 3♥ 2♥ 3♣ 3♦ A♠ 3 T♦ 4♠ 4♥ T♥ T♠ 6 4♣ 2♥ A♣ 5♦ A♥ 1 9♠ T♥ 5♦ 2♠ Q♠ 0 If you need some sample hands with a given rank to test/work with, you could either pull them out in a Python script of your own, or use the interpreter as follows with the ''[[https://docs.python.org/3/using/cmdline.html#cmdoption-c|-c]]'' option to quickly isolate the hands you'd like and print them as lists of strings, e.g. to get all straight flush (rank 8) hands in the file: % python -c 'import sys; print("\n".join(str(t[:-1]) for l in sys.stdin if (t := l.split())[-1] == "8"))' Or to get 5 randomly selected three-of-a-kind (rank 3) hands: % python -c 'import sys; print("\n".join(str(t[:-1]) for l in sys.stdin if (t := l.split())[-1] == "3"))' ----- ====== Submission ====== Submit ''poker_hand.py'' via [[info:turnin]]. {{https://jeff.cis.cabrillo.edu/images/feedback-robot.png?nolink }} //**Feedback Robot**// This project has a feedback robot that will run some tests on your submission and provide you with a feedback report via email within roughly one minute. Please read the feedback carefully. ====== Due Date and Point Value ====== Due at 23:59:59 on the date listed on the [[:syllabus|syllabus]]. ''Assignment 05'' is worth 60 points. Possible point values per category: --------------------------------------- Hand comparison methods 36 Other methods 24 Possible deductions: Style and practices 10–20% Possible extra credit: Submission via Git 5% ---------------------------------------