哈斯克尔
用一个随机的东西做另一个随机的东西:在这种情况下,洗牌可以产生骰子投掷。
import System.Environment
import System.Random
import Data.Array.IO
import Control.Monad
-- make random dice from random cards
suit c=map (\(a,b)->[a,b])$zip "A23456789TJQK" (repeat c)
deck=concatMap(\s->suit s) "♠♥♦♣"
-- just like casinos, use more decks for extra randomness
decks=concat$take 8$repeat deck
-- shuffle the cards
shuffle :: [a] -> IO [a]
shuffle xs = do
ar <- newArray n xs
forM [1..n] $ \i -> do
j <- randomRIO (i,n)
vi <- readArray ar i
vj <- readArray ar j
writeArray ar j vi
return vj
where
n = length xs
newArray :: Int -> [a] -> IO (IOArray Int a)
newArray n xs = newListArray (1,n) xs
-- convert a card to a die, by counting along the original deck
-- then taking mod (faces). If we don't have enough cards to make
-- a full set of faces, assign the 'extra' cards a value of 0
card2die faces card=
let index=(head[i|(i,c)<-zip[0..]deck,c==card]) in
if (index > (length deck-(length deck`mod`faces)))
then 0
else (index`mod`faces)+1
main=
do
args <- getArgs
let faces = read (args!!0)
-- throw away cards we can't map to die faces
cards<-shuffle$filter (\card->card2die faces card/=0) decks
mapM_ (\card->putStrLn (card++" -> "++(show (card2die faces card)))) cards
接受一个论点,即模具上的面数。输出是这样的:
./cards 20|head
2♦ -> 8
7♥ -> 20
J♦ -> 17
6♥ -> 19
9♥ -> 2
8♥ -> 1
5♥ -> 18
4♠ -> 4
Q♥ -> 5
2♣ -> 1
...等等,所有卡(未打印丢弃卡)。太明显了吗?
getRandomBetween(1,d)
都会使我更深入地研究它。