我怎样才能从 Haskell 的一副牌中抽出那么多张牌

问题描述

在这个程序中,我想询问用户卡片的数量并从一副牌中抽取该数量的卡片(见下文)并告诉用户卡片和 这些卡片的“总数”。在这种情况下,我的意思是最多 21 点的 21 点,其中 计数超过 21 返回 nothing。二十一点点数计为 2-10 作为其面值,千斤顶, 皇后和国王算作 10,王牌算作 1 或 11。我需要两个函数Option Explicit Sub Savetest() Dim OldWorkBook As Workbook: Set OldWorkBook = ThisWorkbook Dim WorkSheetNames() As String Dim FilePath As String Dim FileName As String With OldWorkBook.Worksheets("CSG") ReDim WorkSheetNames(1 To .Parent.Worksheets.Count) FilePath = "C:\Users\Tom\Desktop\" & .Range("B1").Value & " " _ & .Range("B2").Value FileName = .Range("B1").Value & " " & .Range("B2").Value & ".xlsx" End With On Error Resume Next MkDir FilePath On Error GoTo 0 FilePath = FilePath & "\" Dim ws As Worksheet Dim n As Long For Each ws In OldWorkBook.Worksheets n = n + 1 WorkSheetNames(n) = ws.Name Next ws Application.ScreenUpdating = False OldWorkBook.Worksheets(WorkSheetNames).copy With ActiveWorkbook ' new workbook Application.displayAlerts = False .Worksheets("CSG").Delete .SaveAs FilePath & FileName,51 ' xlOpenXMLWorkbook Application.displayAlerts = True '.Close SaveChanges:=False End With Application.ScreenUpdating = True End Sub 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

请帮助我

解决方法

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

然而,手头的问题似乎是从一副初始的 N 张牌中随机提取 M 张牌。

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

由于我们没有关于所用类型的信息,我们将假设“卡片”用普通数字表示,从 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])
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 包中的 moveOneCardLeft 函数简化上述 nest :: Monad m => Int -> (a -> m a) -> a -> m a 之外的代码。

像这样:

import  Control.Monad.HT  (nest)

moveOneCardLeft :: RandomGen g => ([a],top ++ (tail bot))

drawSomeCards :: RandomGen g => g -> Int -> [a] -> (([a],g)
drawSomeCards gen0 n xs = let action = nest n moveOneCardLeft ([],xs)
                          in  runRand action gen0

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...