Bonjour,

j'ai écrit une petite librairie pour compter le score d'une main de cribbage en Haskell. J'aimerais avoir des commentaires s'il vous plaît. Pour ceux qui ne savent pas comment compter les points au cribbage, voici un lien qui peut aider: http://www.cribbage.ca/cribbage_points_fr.shtml

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
151
152
153
154
155
156
157
 
module Cribbage where
 
-- We're going to need bit manipulation for powerset
import Data.Bits
import Data.List
 
data Suit = Clubs | Diamond | Heart | Spade
    -- Ord is needed when we sort cards.  In cribbage, no suit is
    -- stronger than another.
    deriving (Show, Eq, Ord) 
 
data Value = Ace
           | Two
           | Three
           | Four
           | Five
           | Six
           | Seven
           | Eight
           | Nine
           | Ten
           | Jack
           | Queen
           | King
    deriving (Show, Eq, Ord)
 
type Card = (Value, Suit)
type Hand = [Card]
type Starter = Maybe Card
 
suit :: Card -> Suit
suit = snd
 
-- A numerical card has its own value, the ace is worth one,
-- and all figures are worth 10.
value :: Card -> Int
value (val, _) =
    case val of
        Ace   -> 1
        Two   -> 2
        Three -> 3
        Four  -> 4
        Five  -> 5
        Six   -> 6
        Seven -> 7
        Eight -> 8
        Nine  -> 9
        _     -> 10
 
-- This will be needed to figure out if we have a straight later on.
position :: Card -> Int
position (val, _) = 
    case val of
        Ace   -> 0
        Two   -> 1
        Three -> 2
        Four  -> 3
        Five  -> 4
        Six   -> 5
        Seven -> 6
        Eight -> 7
        Nine  -> 8
        Ten   -> 9
        Jack  -> 10
        Queen -> 11
        King  -> 12
 
powerset :: [a] -> [[a]]
powerset l =
    [[l !! j | j <- [0 .. length l], (shiftL 1 j::Int) .&. i > 0]
     | i <- [0 .. 2 ^ (length l) - 1]]
 
 
-- Count all points in a hand
count :: Hand -> Starter -> Bool -> Int
count hand starter isCrib =
    sum [ countPairs hand starter
        , countJack hand starter
        , count15 hand starter
        , countFlush hand starter isCrib
        , countStraight hand starter]
 
-- 1 pair: 2 points
-- 2 pairs: 4 points
-- 3 pairs (3 of a kind): 6 points
-- 6 pairs (4 of a kind): 12 points
countPairs :: Hand -> Starter -> Int
countPairs hand (Just starter) = countPairsAux (starter:hand)
countPairs hand Nothing        = countPairsAux hand
 
countPairsAux :: Hand -> Int
countPairsAux hand =
    length pairs * 2 
        where sets  = powerset [value | (value, _) <- hand]
              pairs = [set | set <- sets, length set == 2 &&
                  (set !! 0) == (set !! 1)]
 
-- One point if the suit of a jack in the hand
-- is the same as the suit of the starter card.
countJack :: Hand -> Starter -> Int
countJack hand Nothing = 0
countJack hand (Just (_, starter_suit)) = 
    if jack then 1 else 0
        where suits = [suit | (value, suit) <- hand, value == Jack]
              jack  = any (== starter_suit) suits
 
 
-- Every combination of cards totaling 15 is worth 2 points.
count15 :: Hand -> Starter -> Int
count15 hand Nothing = count15Aux hand
count15 hand (Just starter) = count15Aux (starter:hand)
 
count15Aux :: Hand -> Int
count15Aux hand =
    length [x | x <- values, sum x == 15] * 2
        where values = powerset [value card | card <- hand]
 
 
-- If every card in a hand are of the same suit, 1 point
-- per hand is awarded.  To be valid in the crib, the 
-- starter card must also be of the same suit.
countFlush :: Hand -> Starter -> Bool -> Int
countFlush hand Nothing _ = countFlushAux hand
countFlush hand (Just starter) True = countFlushAux (starter:hand)
countFlush hand (Just starter) False = 
    maximum [countFlushAux x | x <- [hand, (starter:hand)]]
 
countFlushAux :: Hand -> Int
countFlushAux hand =
    if allSameSuit then length hand else 0
        where suits = map suit hand
              allSameSuit = all (== (head suits)) suits
 
-- Straights of 3 cards and more are worth 1 point per card.
-- Only the longest straights are considered.
countStraight :: Hand -> Starter -> Int
countStraight hand Nothing = countStraightAux hand
countStraight hand (Just starter) = countStraightAux (starter:hand)
 
countStraightAux :: Hand -> Int
countStraightAux hand =
    sum $ map length $ keepLongest straights
        where straights = [straight | straight <- powerset hand,
                           isStraight straight]
 
isStraight :: Hand -> Bool
isStraight l | length l < 3 = False
isStraight l =
    all (== (head values)) values
        where cards = sort l
              values = [e - i | (i, e) <- zip [0..] (map position cards)]
 
keepLongest :: [Hand] -> [Hand]
keepLongest straights = 
    [straight | straight <- straights, length straight == maxLength]
        where maxLength = maximum $ map length straights