我想使用响应式香蕉来编写人们可以为其编写机器人的旅行者游戏。FRP 对我来说是全新的,我很难开始。当我开始时,我创建了一个更精细的图表,但为了我的目的,我试图让它尽可能简单。我想要一些指导,主要是关于从哪里开始,以及如何将这个更大的问题分解成更小的问题来解决。这是最初的设计。
这个想法是有一个 LNodes 的图(为了简单起见,我现在忽略了加权边缘)。我将这些 LNode 描述为Planet
s。s 有一个名字,一个和s上的Planet
玩家地图。玩家有一个 id、resources 和一个 Planet。这里是 Data Structues 和一些相关的功能,接下来是更多的讨论。Planet
Resource
-- Graph-building records and functions
data PlanetName = Vulcan
| Mongo
| Arakis
| Dantooine
| Tatooine
deriving (Enum,Bounded,Show)
data Planet = Planet {pName :: PlanetName
,player :: IntMap Player
,resources :: Int
} deriving Show
data Player = Player {pid :: Int
,resources :: Int
} deriving Show
makePlanetNodes :: PlanetName -> [LNode Planet]
makePlanetNodes planet = Prelude.map makePlanetNodes' $
zip [planet ..] [0 ..]
where makePlanetNodes' (planet,i) =
(i,Planet {pName = planet, players = IM.empty})
makePlanetGraph p = mkGraph p [(0,1,1),(1,2,2),(2,3,4),(3,4,3),(4,0,2)]
-- Networking and command functions
prepareSocket :: PortNumber -> IO Socket
prepareSocket port = do
sock' <- socket AF_INET Stream defaultProtocol
let socketAddress = SockAddrInet port 0000
bindSocket sock' socketAddress
listen sock' 1
putStrLn $ "Listening on " ++ (show port)
return sock'
acceptConnections :: Socket -> IO ()
acceptConnections sock' = do
forever $ do
(sock, sockAddr) <- Network.Socket.accept sock'
handle <- socketToHandle sock ReadWriteMode
sockHandler sock handle
sockHandler :: Socket -> Handle -> IO ()
sockHandler sock' handle = do
hSetBuffering handle LineBuffering
forkIO $ commandProcessor handle
return ()
commandProcessor :: Handle -> IO ()
commandProcessor handle = untilM (hIsEOF handle) handleCommand >> hClose handle
where
handleCommand = do
line <- hGetLine handle
let (cmd:arg) = words line
case cmd of
"echo" -> echoCommand handle arg
"move" -> moveCommand handle arg
"join" -> joinCommand handle arg
"take" -> takeCommand handle arg
"give" -> giveCommand handle arg
_ -> do hPutStrLn handle "Unknown command"
echoCommand :: Handle -> [String] -> IO ()
echoCommand handle arg = do
hPutStrLn handle (unwords arg)
moveCommand = undefined
joinCommand = undefined
takeCommand = undefined
giveCommand = undefined
到目前为止,这是我所知道的,我的事件将涉及类型Planet
和Player
. 行为将涉及移动、加入、获取和给予。当玩家加入时,它将创建一个新Player
事件并使用该事件更新 Vulcan 上的地图Player
。移动将允许从一个遍历
LNode
到另一个,前提是LNode
s 由一条边连接。Take 将从resources
当前Planet
的Player
“打开”中删除并将它们添加resources
到
Player
. 给予会适得其反。
我怎样才能把这个大问题分解成更小的问题,这样我才能理解这些东西?
更新:事实证明 Hunt the Wumpus 不是帮助学习 FRP 的好选择,请参阅此处的 FRP 用途说明。这是 Heinrich Apfelmus 的回应。
也就是说,我现在将完全忽略网络代码。我可以写一些虚拟机器人来测试时间等。
更新:有些人似乎对这个问题感兴趣,所以我将在这里跟踪相关问题。