【问题标题】:How can I draw that number of cards from a deck in haskell我怎样才能从haskell的一副牌中抽出这么多张牌
【发布时间】:2021-07-05 14:38:06
【问题描述】:

在这个程序中,我想询问用户卡片的数量并从一副牌中抽取该数量的卡片(见下文)并告诉用户卡片和 这些卡的“总数”。在这种情况下,我的意思是二十一点计数高达 21,与 计数超过 21 返回 Nothing。二十一点计数将 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.

请帮帮我

【问题讨论】:

  • 错误告诉你 GHC 找不到 Data.Random - random 包中有一个 Sytem.Random - 也许你想要那个?
  • 关于你的两个函数的可能更紧迫和有趣的问题:到目前为止你尝试了什么?有什么起点吗?
  • 一个猜测:totalCards [] = NothingtotalCards xs = Just (length xs)? ...不知道-您没有给出CardDeck的定义(我猜type Deck = [Card]是因为shuffle?)
  • @Daniel Wagner - 我认为这个问题最终会被关闭,但我不认为这真的是你链接的那个重复
  • @Carsten 提问者有责任确定他们要问的问题。如果你想让它成为读者的责任,并将问题从陈述的问题扩展到完整的问题,那么我可以接受,但解决方案仍然很接近(这次不是有足够的针对性)。因此,看起来“像重复一样接近”是至少与其他选项一样好的结果 - 因为至少它可以帮助他们解决一个问题而不是一个问题。

标签: function haskell blackjack


【解决方案1】:

此时我们没有关于 CardDeck 数据类型的信息。

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

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

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

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

这将是一元代码:

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
$ 

注意:如果认为合适,可以使用Control.Monad.HT 包中的nest :: Monad m =&gt; Int -&gt; (a -&gt; m a) -&gt; a -&gt; m a 函数简化moveOneCardLeft 之外的上述代码。

像这样:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-03
    • 1970-01-01
    • 2011-09-10
    • 2023-03-18
    • 2014-01-02
    • 2017-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多