我有一个简单的树,如此定义:
type BspTree =
| Node of Rect * BspTree * BspTree
| Null
我可以像这样获得叶子节点(我的树“dungeon”中的房间)的集合,它似乎有效:
let isRoom = function
| Node(_, Null, Null) -> true
| _ -> false
let rec getRooms dungeon =
if isRoom dungeon then
seq { yield dungeon }
else
match dungeon with
| Node(_, left, right) ->
seq { for r in getRooms left -> r
for r in getRooms right -> r }
| Null -> Seq.empty
但是现在我正在尝试让姐妹叶节点房间,所以我可以将它们与走廊连接起来,而且我失败了(我经常这样做)。这是我的尝试:
let rec getCorridors dungeon =
match dungeon with
| Null -> failwith "Unexpected null room"
| Node(_, left, right) ->
match left, right with
| Null, Null -> Seq.empty
| Node(leftRect, _, _), Node(rightRect, _, _) ->
if isRoom left && isRoom right
then seq { yield makeCorridor leftRect rightRect }
else seq { for l in getCorridors left -> l
for r in getCorridors right -> r }
| _ -> failwith "Unexpected!"
我最后得到一个空的seq。无论如何,这一切都伤害了我的大脑,而且我知道任何人都不会勉强通过它,但我认为这不会让人感到伤心。
答案 0 :(得分:4)
正如罗伯特评论的那样,也许你的makeCorridor功能需要一些关注。 我已经调整了你的代码,制作了我自己的makeCorridor函数并用int替换了Rect。
我使用了活动模式来确定BspTree何时是一个房间。我还使用yield! sequence
代替for x in sequence -> x
。这些修改导致相同的行为。我只想展示一个活动模式可以做什么:
type BspTree =
| Node of int * BspTree * BspTree
| Null
let (|IsRoom|_|) dungeon =
match dungeon with
| Node(_,Null,Null) -> Some dungeon
| _ -> None
let rec getRooms = function
| IsRoom dungeon -> Seq.singleton dungeon
| Null -> Seq.empty
| Node (_, left, right) -> seq { yield! getRooms left
yield! getRooms right }
let makeCorridor leftNode rightNode =
match leftNode, rightNode with
| Node(left,Null,Null), Node(right,Null,Null) ->
sprintf "(%d) -> (%d)" left right
| _ -> failwith "Illegal corridor!"
let rec getCorridors = function
| Null -> failwith "Unexpected null room"
| Node(_, Null, Null) -> Seq.empty
| Node(_, IsRoom left, IsRoom right) -> seq { yield makeCorridor left right }
| Node(_, left, right) -> seq { yield! getCorridors left
yield! getCorridors right }
示例:
let dungeon =
Node(1, Node(2, Node(4,Null,Null),
Node(5,Node(8,Null,Null),
Node(9,Null,Null))),
Node(3, Node(6,Null,Null),
Node(7,Null,Null)))
FSI的结果:
> getCorridors dungeon;;
val it : seq<string> = seq ["(8) -> (9)"; "(6) -> (7)"]