gpt4 book ai didi

algorithm - 如何让这段Haskell代码更简洁?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:35:53 25 4
gpt4 key购买 nike

作为练习,我正在尝试用 Haskell 编写赌场游戏“ war ”的模拟。

http://en.wikipedia.org/wiki/Casino_war

这是一个非常简单的游戏,有一些规则。用我知道的任何一种命令式语言编写都是一个非常简单的问题,但是我正在努力用 Haskell 编写它。

我目前的代码:

 -- Simulation for the Casino War

import System.Random
import Data.Map

-------------------------------------------------------------------------------
-- stolen from the internet

fisherYatesStep :: RandomGen g => (Map Int a, g) -> (Int, a) -> (Map Int a, g)
fisherYatesStep (m, gen) (i, x) = ((insert j x . insert i (m ! j)) m, gen')
where
(j, gen') = randomR (0, i) gen

fisherYates :: RandomGen g => g -> [a] -> ([a], g)
fisherYates gen [] = ([], gen)
fisherYates gen l = toElems $ Prelude.foldl
fisherYatesStep (initial (head l) gen) (numerate (tail l))
where
toElems (x, y) = (elems x, y)
numerate = zip [1..]
initial x gen = (singleton 0 x, gen)

-------------------------------------------------------------------------------

data State = Deal | Tie deriving Show

-- state: game state
-- # cards to deal
-- # cards to burn
-- cards on the table
-- indices for tied players
-- # players
-- players winning
-- dealer's winning
type GameState = (State, Int, Int, [Int], [Int], Int, [Int], Int)

gameRound :: GameState -> Int -> GameState
gameRound (Deal, toDeal, toBurn, inPlay, tied, numPlayers, pWins, dWins) card
| toDeal > 0 =
-- not enough card, deal a card
(Deal, toDeal - 1, 0, card:inPlay, tied, numPlayers, pWins, dWins)
| toDeal == 0 =
-- enough cards in play now
-- here should detemine whether or not there is any ties on the table,
-- and go to the tie state
let
dealerCard = head inPlay
p = zipWith (+) pWins $ (tail inPlay) >>=
(\x -> if x < dealerCard then return (-1) else return 1)
d = if dealerCard == (maximum inPlay) then dWins + 1 else dWins - 1
in
(Deal, numPlayers + 1, 0, [], tied, numPlayers, p, d)
gameRound (Tie, toDeal, toBurn, inPlay, tied, numPlayers, pWins, dWins) card
-- i have no idea how to write the logic for the tie state AKA the "war" state
| otherwise = (Tie, toDeal, toBurn, inPlay, tied, numPlayers, pWins, dWins)

-------------------------------------------------------------------------------

main = do
rand <- newStdGen
-- create the shuffled deck
(deck, _) <- return $ fisherYates rand $ [2 .. 14] >>= (replicate 6)
-- fold the state updating function over the deck
putStrLn $ show $ Prelude.foldl gameRound
(Deal, 7, 0, [], [], 6, [0 ..], 0) deck

-------------------------------------------------------------------------------

我理解为什么要创建随机数需要额外的工作,但我很确定我遗漏了一些基本的结构或概念。保留状态集合并在输入列表上运行分支逻辑应该不会这么尴尬。我什至想不出一个好的方法来为表中有关系的情况编写逻辑。

我不要求完整的解决方案。如果有人能指出我做错了什么,或者一些相关的好阅读 Material ,那就太好了。

提前致谢。

最佳答案

一种用于维护应用程序状态的有用设计模式是所谓的状态 monad。您可以找到描述和一些介绍性示例 here .此外,您可能需要考虑使用具有命名字段的数据类型而不是 GameState 的元组,例如:

data GameState = GameState { state :: State, 
toDeal :: Int
-- and so on
}

这将使使用 record syntax 访问/更新单个字段变得更加容易.

关于algorithm - 如何让这段Haskell代码更简洁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11076461/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com