J'ai écrit un petit module (qui va s'élargir éventuellement) pour calculer le nombre de points d'une main de cribbage.

http://fornost.homeip.net:81/vince/cribbage.tar.gz

J'aimerais bien si des gens pouvait regarder le code (et les tests) et me donner des commentaires. Il y a certaines places dans le code que je pense améliorer (je vous dit pas lesquelles ), mais j'aimerais avoir vos commentaire quand même.

Vous pouvez commentez la ligne qui import IPython, elle est pas nécessaire (mais très pratique pour déboguer)

Ceux qui veulent pas downloader un tar.gz, voici le code (sans les tests):

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
 
class InvalidCard(Exception): pass
class InvalidHand(Exception): pass
 
def powerset(L):
    if L == []:
        return [[]]
    else:
        return powerset(L[1:]) + \
                [x + [L[0]] for x in powerset(L[1:])]
 
def is_straight(L):
    if len(L) < 2:
        return True
    L.sort()
    for i, n in enumerate(L[:-1]):
        if n + 1 != L[i + 1]:
            return False
    return True
 
 
class Card(object):
    def __init__(self, card_desc):
        self.suits = {'C': 'Club',
                      'D': 'Diamond',
                      'H': 'Heart',
                      'S': 'Spade'}
        self.value, self.suit = self._make_card(card_desc.upper())
 
    def _make_card(self, card_desc):
        valid_values = 'A23456789TJQK'
        valid_suits = 'CDHS'
 
        if len(card_desc) != 2:
            raise InvalidCard('Invalid card description length')
        if card_desc[0] not in valid_values:
            raise InvalidCard('Invalid card description value')
        if card_desc[1] not in valid_suits:
            raise InvalidCard('Invalid card description suit')
 
        value = valid_values.index(card_desc[0]) + 1
        suit = self.suits[card_desc[1]]
        return value, suit
 
    def value_name(self):
        values = {1: 'Ace',
                  11: 'Jack',
                  12: 'Queen',
                  13: 'King',
                 }
        return values.get(self.value, str(self.value))
 
    def real_value(self):
        '''All figure cards have a value of 10.  The ace
        has a value of 1.'''
        if self.value < 10:
            return self.value
        else:
            return 10
 
    def __cmp__(self, other):
        return cmp(self.value, other.value)
 
    def __str__(self):
        return '%s of %s' % (self.value_name(), self.suit)
 
 
# TODO: Check validity of the hand
class Hand(object):
    def __init__(self, pocket_cards, crib_card, is_crib=False):
        self.pocket_cards = pocket_cards
        self.crib_card = crib_card
        self.all = pocket_cards + [crib_card]
        self.is_crib = is_crib
 
    def count(self):
        '''Sum of the individual ways to make points.'''
        return sum((self._count_pairs(),
                    self._count_triples(),
                    self._count_quadruples(),
                    self._count_jack(),
                    self._count_flush(),
                    self._count_15(),
                    self._count_straight()))
 
    def _count_indentical_values(self, n):
        values = [card.value for card in self.all]
        d = {}
        for value in values:
            d[value] = values.count(value)
        return len([x for x in d.itervalues() if x == n])
 
    def _count_pairs(self):
        '''Every pair is worth 2 points.'''
        return self._count_indentical_values(2) * 2
 
    def _count_triples(self):
        '''Every triple is worth 6 points (there can only
        be one per hand.)'''
        return self._count_indentical_values(3) * 6
 
    def _count_quadruples(self):
        '''Every quadruple is worth 12 points (there can only
        be one per hand.)'''
        return self._count_indentical_values(4) * 12
 
    def _count_jack(self):
        '''If a the suit of a jack in the player\'s pocket
        cards matches the suit of the crib card, the player
        is awarded one point.'''
        jacks_suits = [card.suit for card in self.pocket_cards
                       if card.value == 11]
        return int(any(self.crib_card.suit == suit for suit in jacks_suits))
 
    def _count_flush(self):
        '''Pocket cards have the same suit: 4 points.
        Pocket cards + crib card have the same suit: 5 points.
        The 4 point flush is available only in the "normal" hand.'''
        if all(card.suit == self.all[0].suit for card in self.all):
            return 5
        elif not self.is_crib and \
                all(card.suit == self.pocket_cards[0].suit for card in
                    self.pocket_cards): 
            return 4
        else:
            return 0
 
    def _count_15(self):
        '''Every combination that adds up to 15 is worth 2 points.'''
        values = powerset([card.real_value() for card in self.all])
        return len([x for x in values if sum(x) == 15]) * 2
 
    def _count_straight(self):
        '''Every card that is part of a straight is worth one point.
        A card can be counted more than once.  Only straights of three
        and more cards are considered.
 
        E.g.: If a player has 2, 3, 3, 4, the two and four are counted
        twice for a total of 6 points.'''
        straights = [s for s in powerset([card.value for card in self.all])
                     if len(s) >= 3 and is_straight(s)]
        if straights: # max() doesn't work with empty lists
            longests = self._keep_longest(straights)
            return sum(map(len, longests))
        else:
            return 0
 
    def _keep_longest(self, straights):
        length = len(max(straights, key=len))
        return [s for s in straights if len(s) == length]