问题所在
我正在做一个文字冒险游戏,作为一个业余项目来教自己一些新的Haskell概念。
现在,我遇到了一个挑战,就是如何表示游戏中的各个级别(或“场景”)以及它们之间的各种连接方式。为了让自己保持简单,我把游戏的“地图”想象成一个简单的2d空间,其中的场景通过基本方向(NESW)连接起来:
Lake
⇳
Forest
⇳
Home ⬄ Field*
*: Starting location在这里,从湖边往南走会带你到森林,反之亦然;从田野往西走会带你到家。这里的挑战是,--我需要某种方法来编码不仅连接了哪些场景,而且还需要 how 它们是如何连接的E 210,其中'how‘指的是一个基本方向。
到目前为止,我考虑的两个选项是将级别表示为图或使用元组的列表,但我对这两种方法并不完全满意。
将场景表示为图
我用图形表示场景及其关联的基本方法如下:
data Scene = InitialField | Forest | House | Lake
-- |`gameScenes` maps scenes to their integer representation, as used in `sceneGraph`.
gameScenes :: Map Int Scene
gameScenes =
let scenes =
[ (0, InitialField)
, (1, Forest)
, (2, House)
, (3, Lake)
]
in
fromList scenes
-- |the `sceneGraph` describes the way different scenes of the game connect to each other.
sceneGraph :: Graph
sceneGraph =
let
bounds = (0, 3)
edges =
[ (0, 1) -- link initial field to forest
, (0, 2) -- link initial field to house
, (1, 3) -- link forest to lake
]
in
buildG bounds edges缺点:这里的主要限制是这个图没有编码任何关于基数方向的信息。这是不幸的,因为除了这个限制之外,图似乎是表示场景(顶点)及其连接(边)的完美数据结构。有没有办法编码图中边的‘元数据’(在本例中是基数)?
使用元组列表表示场景
当我遇到上述限制时,我决定尝试一种不同的方法,并将场景之间的链接表示为元组列表:
data Scene = InitialField | Forest | House | Lake
data CardinalDirection = North | East | South | West
type LinkedScene = (CardinalDirection, Scene)
-- |`linkedScenes`, applied to a `Scene`, returns a list of the connected scenes and their cardinal directions.
linkedScenes :: Scene -> [LinkedScene]
linkedScenes InitialField = [(North, Forest)]
linkedScenes Forest = [(South, InitialField), (West, Lake)]
-- The other links are left as an exercise for the reader ;)
linkedScenes _ = []缺点:这种方法确实允许我们通过将sceneLinks应用到玩家当前所在的Scene中来对不同场景之间的联系进行编码,但它有一个巨大的、丑陋的缺点:它要求我们对场景之间的空间关联进行双端编码。换句话说,如果我们知道森林位于字段的北面,我们需要编写两个函数:一个接受Forest并生成[(South, InitialField)],另一个反函数获取InitialField并生成[(North, Forest)]。这似乎是在乞求bug:如果我想要添加一个场景,或者改变游戏世界的布局,我需要记住要仔细检查来自两端的每一个链接。
总结:要求
理想情况下,我正在寻找一种方法:
如果有人能想到这样的方法,一定是Haskell社区的人:)
谢谢!
发布于 2022-07-07 12:41:18
从描述一些连接的三元组开始:
data Scene = Field | Forest | House | Lake
data Dir = N | E | S | W
type Edge = (Scene, Dir, Scene)
uniEdges :: [Edge]
uniEdges = [(Field, N, Forest), (Forest, W, Lake)]通过反转所有元组展开到完整的映射:
class Dual a where dual :: a -> a
instance Dual Dir where
dual N = S
dual E = W
dual S = N
dual W = E
instance Dual Edge where dual (s, d, s') = (s', dual d, s)
instance Dual a => Dual [a] where dual = map dual
allEdges :: [Edge]
allEdges = uniEdges ++ dual uniEdges然后将这些插入到您喜欢的任何数据结构中;Map Scene (Dir, Scene)或Gr或其他什么。
这种方法的一个很好的特性是:它使您能够在不改变场景图的所有用户的情况下,稍后决定不是所有的边缘都应该自己打开,就像这张带有弯曲路径的地图:
House
|
\
`--Lake发布于 2022-07-07 10:00:24
我认为有两种选择:
PseudoAffine类用于距离。)https://stackoverflow.com/questions/72893976
复制相似问题