有什么毛病我的树遍历code?我的、有什么、遍历、毛病

2023-09-11 23:09:26 作者:超人没对象i

我有一个简单的树,正是如此定义的:

I have a simple tree, defined thusly:

type BspTree =
    | Node of Rect * BspTree * BspTree
    | Null

我可以得到叶节点的集合(客房我的树地牢)这个样子,它似乎工作:

I can get a collection of leaf nodes (rooms in my tree "dungeon") like this, and it seems to work:

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

但现在我试图让妹妹叶节点房间,所以我可以用走廊连接起来,而我失败了(因为我经常这样做)。这里是我的尝试:

But now I'm trying to get sister leaf node rooms so I can connect them with corridors, and I'm failing miserably (as I often do). Here's my attempt:

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!"

我刚刚结束了一个空的序列。无论如何,这都伤害了我的大脑,我知道这是不太可能有人会猛击通过它,但我想它不会伤害要求。

I just end up with an empty seq. Anyway, this all hurts my brain, and I know it's unlikely anyone will slog through it, but I figured it wouldn't hurt to ask.

推荐答案

正如罗伯特评论说,也许你makeCorridor功能需要一定的关注。 我已经适应你的code,使我自己的makeCorridor功能和更换矩形为int。

As Robert commented, maybe your makeCorridor function needs some attention. I've adapted your code, making my own makeCorridor function and replacing Rect by int.

我用积极的方式来确定何时BspTree一个房间。我还用屈服!序而不是对于x的序列 - > X 。这些修饰导致相同的行为。我只是想显示什么积极的模式可以做的:

I've used an active pattern to determine when a BspTree is a room. I've also used yield! sequence instead of for x in sequence -> x. These modifications result in the same behavior. I just wanted to show what an active pattern can do:

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)"]