我怎么能在哈斯克尔的一副牌上抽到这么多牌呢



在这个程序中,我想询问用户卡片的数量,并从一副牌中抽取该数量的卡片(见下文(,并告诉用户卡片和"合计";这些卡片中的一张。在这种情况下,我指的是21点计数计数超过21,返回Nothing。21点计数计数2-10作为其面值,王后和国王的数量为10,王牌的数量为1或11。我需要两个功能:drawHand :: Int ->Deck ->([Card],Deck)totalCards :: [Card] ->Maybe Int

import Data.List
import Data.Random

drawHand :: Int -> Deck -> ([Card], Deck)
totalCards :: [Card] -> Maybe Int
main = do
putStrLn "How many cards?"
Random :: MonadRandom m => Deck-> m Deck
Random ran = runRVar (shuffle deck) StdRandom
Random <- getLine
putStrLn "Hand of [] totalCards: " ++ totalCards

错误:

Failed to load interface for ‘Data.Random’
Perhaps you meant Data.Ratio (from base-4.9.0.0)
Use -v to see a list of the files searched for.

请帮我

目前我们没有关于CardDeck数据类型的信息。

然而,眼前的问题似乎是从最初的N副牌中随机提取M张牌。

如果这个问题的解释是正确的,那么我们可以使用Rand单元构造函数,并从定义一个单元动作开始,该动作只将一张牌从右牌组转移到左牌组。

由于我们没有关于使用中的类型的信息,我们将假设"卡片"由0到51的普通数字表示。

接下来,我们定义了一个递归移动M张牌的动作,移动一张牌,然后用(M-1(参数调用自己。对于M=0,我们将动作定义为no-op。

这将是一元代码:

import  System.Random
import  Control.Monad.Random

moveOneCardLeft :: RandomGen g => ([a],[a]) -> Rand g ([a],[a])
moveOneCardLeft (deck, rest) =
do
let  remCount = length rest
choice <- getRandomR (0, (remCount-1))
let  (top, bot) = splitAt choice rest
return $ ((head bot) : deck, top ++ (tail bot))

moveSomeCardsLeft :: RandomGen g => Int -> ([a],[a]) -> Rand g ([a],[a])
moveSomeCardsLeft 0 (deck, rest) = return (deck, rest)  -- unchanged
moveSomeCardsLeft n (deck, rest) =
do
(deck1, rest1) <- moveOneCardLeft (deck, rest)
(deck2, rest2) <- moveSomeCardsLeft (n-1) (deck1, rest1)
return (deck2, rest2)

extractSomeCards :: RandomGen g => Int -> [a] -> Rand g ([a], [a])
extractSomeCards n xs =
do
(deck, rest) <- moveSomeCardsLeft n ([], xs)
return (deck, rest)

接下来,代码和一些初步的游戏相关实用程序功能:

drawSomeCards :: RandomGen g => g -> Int -> [a] -> (([a], [a]), g)
drawSomeCards gen0 n xs = runRand (extractSomeCards n xs) gen0
cardValue :: Int -> Int
cardValue n = let rank = mod n 13
in  if (rank < 10) then (rank+1)
else {- Jack Queen King -} 10
deckValue :: [Int] -> Int
deckValue cards = sum (map cardValue cards)
totalOfCards :: [Int] -> Maybe Int
totalOfCards cards =
let  s = deckValue cards
in   if (s <= 21)  then  (Just s)  else  Nothing

最后,用户测试代码:

main = do
let  wholeDeck  = [0..51]
randomSeed = 4243
gen0 = mkStdGen randomSeed
putStrLn "How many cards ?"
inLine <- getLine
let count = (read inLine :: Int)
putStrLn $ "Want to extract " ++ (show count) ++ " cards."
let  ((deck, rest), gen1) = drawSomeCards gen0 count wholeDeck
sumw = sum wholeDeck
suma = sum deck
sumb = sum rest
sum0 = (suma + sumb) - sumw
putStrLn $ "Must be zero: " ++ (show sum0)   -- sanity check
putStrLn $ "deck: " ++ (show deck)
putStrLn $ "rest: " ++ (show rest)
putStrLn $ "Deck value: " ++ (show $ deckValue deck)

程序执行:

$ q67025780.x
How many cards ?
10
Want to extract 10 cards.
Must be zero: 0
deck: [8,47,38,49,4,31,9,30,28,23]
rest: [0,1,2,3,5,6,7,10,11,12,13,14,15,16,17,18,19,20,21,22,24,25,26,27,29,32,33,34,35,36,37,39,40,41,42,43,44,45,46,48,50,51]
Deck value: 77
$ 

注意:如果认为合适,可以使用控件中的nest :: Monad m => Int -> (a -> m a) -> a -> m a函数简化moveOneCardLeft以外的上述代码。莫纳德。HT包。

像这样:

import  Control.Monad.HT  (nest)
moveOneCardLeft :: RandomGen g => ([a],[a]) -> Rand g ([a],[a])
moveOneCardLeft (deck, rest) =
do
let  remCount = length rest
choice <- getRandomR (0, (remCount-1))
let  (top, bot) = splitAt choice rest
return $ ((head bot) : deck, top ++ (tail bot))
drawSomeCards :: RandomGen g => g -> Int -> [a] -> (([a], [a]), g)
drawSomeCards gen0 n xs = let action = nest n moveOneCardLeft ([], xs)
in  runRand action gen0

最新更新