问题描述
在这个程序中,我想询问用户卡片的数量并从一副牌中抽取该数量的卡片(见下文)并告诉用户卡片和
这些卡片的“总数”。在这种情况下,我的意思是最多 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
请帮助我
解决方法
此时我们没有关于 Card
和 Deck
数据类型的信息。
然而,手头的问题似乎是从一副初始的 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