On Wed, Oct 7, 2009 at 4:46 PM, kirby urner <kirby.urner@gmail.com> wrote:
The code below isn't stellar, but has some pedagogical value nevertheless.
Indeed the code was far from stellar, however it gave some direction. The version below is in Python 3.1 and demonstrates primitive conditionals and exception handling, too often postponed because of that "phylogeny problem" (older languages just crashed or tried to catch everything at compile time, so we didn't see try/except syntax until relatively newer languages). In the Game of War (a silly game), each player gets a deck. Our Deck class is able to hand back a smaller sample from an already-shuffled deck of 52 (no jokers). They each then turn over the top card and see which has the higher value, scoring accordingly. Our Deck class spits a random card from anywhere in the deck, which would be another way to play (as if fanning the cards and picking any at will).
A's King of Diamonds beats B's Ace of Hearts B's 9 of Spades beats A's 5 of Clubs A's 10 of Clubs beats B's 2 of Hearts B's Ace of Diamonds matches A's Ace of Hearts B's 7 of Clubs beats A's 5 of Hearts B's 10 of Diamonds beats A's 9 of Hearts B's King of Hearts beats A's 6 of Spades A's King of Hearts beats B's Jack of Hearts A's 9 of Diamonds beats B's 4 of Clubs B's King of Spades beats A's 2 of Diamonds Game Over: B wins
What's demonstrated in the code, besides exception handling and flow (in a somewhat pedantic and repetitive style) is (a) use of shuffle and randint from random module and (b) __rib__ syntax for > < ==. The Card type gets the logic for comparing any two card instances. The Deck is innocent of such logic, just needs to manage "how many" and "which cards". from random import shuffle, randint thesuits = ['Hearts','Diamonds','Clubs','Spades'] theranks = ['Ace'] + [str(v) for v in range(2,11)] + ['Jack','Queen','King'] rank_values = list(zip(theranks, range(1,14))) class Card: def __init__(self, suit, rank_value ): self.suit = suit self.rank = rank_value[0] self.value = rank_value[1] def __lt__(self, other): if self.value < other.value: return True else: return False def __gt__(self, other): if self.value > other.value: return True else: return False def __eq__(self, other): if self.value == other.value: return True else: return False def __repr__(self): return "Card(%s, %s)" % (self.suit, (self.rank, self.value)) def __str__(self): return "%s of %s" % (self.rank, self.suit) class Deck: def __init__(self, numcards = 52): # build a complete deck then slice try: assert 0 < numcards <= 52 except: raise ValueError() self.numcards = numcards self.cards = [Card(suit, rank_value) for rank_value in rank_values for suit in thesuits ] shuffle(self.cards) self.cards = self.cards[ : self.numcards] def spit_card(self): try: assert self.numcards > 0 except: raise AssertionError() some_card = self.cards.pop( randint( 0, self.numcards - 1 )) self.numcards = len(self.cards) return some_card def __repr__(self): return "Deck(%s)" % self.numcards def __str__(self): return str([str(card) for card in self.cards]) def test(): thedeck = Deck() print (str(thedeck)) def game_of_war(): deckA = Deck(10) deckB = Deck(10) PlayerA_score = 0 PlayerB_score = 0 try: assert deckA.numcards == deckB.numcards except: raise AssertionError() for i in range(deckA.numcards): playerA_card = deckA.spit_card() playerB_card = deckB.spit_card() if playerA_card > playerB_card: PlayerA_score += 1 print("A's %s beats B's %s" % (playerA_card, playerB_card)) if playerA_card < playerB_card: PlayerB_score += 1 print("B's %s beats A's %s" % (playerB_card, playerA_card)) if playerA_card == playerB_card: print("B's %s matches A's %s" % (playerB_card, playerA_card)) if PlayerA_score > PlayerB_score: print("Game Over: A wins") if PlayerA_score < PlayerB_score: print("Game Over: B wins") if PlayerA_score == PlayerB_score: print("Game Over: it's a draw!") if __name__ == '__main__': # test() game_of_war() A subtle error I was having, which took me back to Steve Holden's workshop at Pycon 2009 (Chicago) was this line below: rank_values = list(zip(theranks, range(1,14))) At first I just returned the zip without making it a list. But in 3.1 that's a "zip object" and gets exhausted through iteration. In creating a first deck object from this global variable, it'd exhaust the zip object, leaving nothing for the next deck to iterate against upon instantiation. Coercing to a list forces a static object on the heap, suitable for continued reiteration. I should give more explicit error messages and have more interesting tests. This is still in need of some spit and polish, but is already suitable as a lesson plan for gnu math teachers. Kirby