我正在构建一个蛇游戏,我正在为游戏使用光泽图形。 我正在使用G.play开始游戏:
main :: IO ()
main = do
rand <- R.randomIO
let world = startWorld rand
G.play
(displayMode world)
backgroundColor
stepRate
world
drawWorld
handleEvent
handleStep
现在蛇基本上是坐标对的列表,分数是蛇的长度。但是,我添加了一个特殊苹果的功能,它给你2分而不是1分,并且只为蛇增加了1个长度。但是因为得分是基于蛇的长度我想创建一个全局变量,它将计算蛇吃掉特殊苹果的次数并将其添加到得分中。我搜索了网络,无法弄清楚如何实际使用Monad.State来帮助我使用这个全局变量。
答案 0 :(得分:0)
如果您希望同时访问IO和State,则可以使用StateT。 State使用完全相同的接口减去类型构造函数中的额外参数。
import Control.Monad.Trans.State
import Control.Monad.IO.Class
游戏类型是应用于IO的状态转换器。这将状态包含在IO类型中,允许我们在需要时将lift
IO函数插入IO monad。这里s
是我们的开始状态,a
是我们的返回状态。
type Game s a = StateT s IO a
捕获游戏状态作为记录类型,其中包含您要随时更新的字段。这是您在全局游戏状态下存储蛇,长度和其他项目的地方。
data GameState = GameState
{ _score :: Int
, _length :: Int
} deriving (Show)
要修改状态,我们使用modify
中的StateT
函数获取状态,在其上应用函数,然后设置结果状态(modify fn = do s <- get; put (fn s)
)
set :: (GameState -> GameState) -> Game GameState ()
set field = modify field
score :: (Int -> Int) -> GameState -> GameState
score fn (GameState s l) = GameState (fn s) l
len :: (Int -> Int) -> GameState -> GameState
len fn (GameState s l) = GameState s (fn l)
要使用IO
,我们必须使用liftIO
将函数提升为IO monad
display :: Show a => a -> Game GameState ()
display = liftIO . print
以下是一个使用它的例子。
game :: Game GameState ()
game = do s <- gets _score
l <- gets _length
display "initial values"
display s
display l
set $ score (+2)
set $ len (+1)
s <- gets _score
l <- gets _length
display "modified values"
display s
display l
runStateT game (GameState 0 0)
将打印
"initial values"
0
0
"modified values"
2
1
((),GameState (_score = 2, _length = 1})
哪个适合您现有的模型并进行细微更改。