Quadtree Maze中的Ocaml探路



我有一个Quadtree类型:

type 'a quadtree = 
| Empty 
| Leaf of 'a 
| Node of 'a quadtree * 'a quadtree * 'a quadtree * 'a quadtree;;

定义的房间
type room = {
n : bool;
e : bool;
s : bool;
w : bool;
ps : coord;
exit : bool
}

定义的坐标
type coord = {
x : int;
y : int;
}

所以所有这些,我有一个Quadtree的房间,这些房间已经或没有向上,向下,左和向右退出。

现在的目标是创建一个可以从一个房间到另一个房间(来自其坐标)的函数(如果存在),问题是我看不到在OCAML中如何做...无论如何,谢谢您的时间,祝您有美好的一天。

编辑:为了澄清,我是定义类型的人,可以在需要时更改它们。另外,我尝试实现Dijkstra的算法(来自Wikipedia的伪代码),但对这两个图表非常不熟悉,OCAML的数组和列表和列表非常不熟悉。确切地说,我的问题 - 我认为 - 我无法修改函数中的变量,例如在Wikipedia的伪代码中,在此行中:

u ← Q.extract_min()                    // Remove and return best vertex

我看到了如何删除最佳顶点,我看到了如何返回它,但并非同时返回。或者,这里:

for each neighbor v of u:           // where v is still in Q.
    alt ← dist[u] + length(u, v)
    if alt < dist[v]:               // A shorter path to v has been found
        dist[v] ← alt 
        prev[v] ← u

如何在" for"循环之外修改区域和上一条段?我可以使用循环吗?还是更简单/更好地使用递归功能?

我也应该清楚地表明,迷宫是"定向",这意味着能够从A房间到B房间,这并不意味着您可以从B房间到A房间A。

编辑2:一开始我应该澄清一下,对不起:Quadtree遵循以下规则:

| Node of North West * North East * South West * South East

编辑3:好的,计划的改变,事实证明我做了很愚蠢的事情。我不需要找到通往某个房间的道路,而只是出口。所以我尝试了:

let rec contains_exit = function
    | [] -> false
    | e::l' when (getCell e.x e.y maze).exit -> true
    | e::l' when (getCell e.x e.y maze).exit = false -> contains_exit l'
;;
let rec find_exit start way =
    if is_exit start then 
        way
    else
    (let a = find_exit (northp start) way@[start] in
    if contains_exit a then
        way
        else
        (
        let b = find_exit (eastp start) way@[start] in
        if contains_exit b then
            way
            else 
            (
        let c = find_exit (southp start) way@[start] in
        if contains_exit c then
            way
                else
                (
            let d = find_exit (westp start) way@[start] in
            if contains_exit d then
                way
                    else
                        way
                )
            )
        )
    )
;;

,但它给了我一个堆叠的溢出。经过一些研究后,似乎"包含_exit a"的行似乎永远不会真实,因此路线永远不会返回,并且循环!

有什么想法为什么?问题是我的 contains_exit 函数吗?

编辑4:最终执行此功能:

let rec find_exit start way =
    sleep 50000000;
    let r = (Random.int 180) in
    set_color (rgb r r r);
    fill_rect (start.x * sizeCell + doorWidth * 2) (start.y * sizeCell + doorWidth * 2) (sizeCell - 4 * doorWidth) (sizeCell - 4 * doorWidth);
    if is_exit start then 
            way@[start]
    else
    (let a = if (getCell start.x start.y maze).n && ((mem (northp start) way) = false) then find_exit (northp start) way@[start] else [] in
    if a != [] then
        a
        else
        (
        let b = if (getCell start.x start.y maze).e && ((mem (eastp start) way) = false) then find_exit (eastp start) way@[start] else [] in
        if b != [] then
            b
            else 
            (
        let c = if (getCell start.x start.y maze).w && ((mem (westp start) way) = false) then find_exit (westp start) way@[start] else [] in
        if c != [] then
            c
                else
                (
            let d = if (getCell start.x start.y maze).s && ((mem (southp start) way) = false) then find_exit (southp start) way@[start] else [] in
            if d != [] then
                d
                    else
                        []
                )
            )
        )
    )
;;

有时会有时起作用...但是有时它会挡住,并且从一个房间到下面的一个房间,然后再次向上移动...我不明白为什么!?

如果您想尝试整个程序,则是:链接

然后您可以去做一些这样的事情:

type 'a quadtree = 
| Empty 
| Leaf of 'a 
| Node of 'a * 'a quadtree * 'a quadtree * 'a quadtree * 'a quadtree;;
type room = {
n : bool;
e : bool;
s : bool;
w : bool;
ps : coord;
exit : bool
};;
type coord = {
x : int;
y : int;
};;
let rec treeForRoom(tree, room) = 
    match tree with
    | Empty -> Empty
    | Leaf l -> if l.ps == room.ps then l else Empty
    | Node (r, n, e, s, w) as node -> 
        if r == room 
        then  node
        else 
            match ((r.ps.x - room.ps.x), (r.ps.y - room.ps.y)) with
            | (0, n) -> if n > 0 then treeForRoom(w) else treeForRoom(e)
            | (n, 0) -> if n > 0 then treeForRoom(s) else treeForRoom(n)
(* Assuming the root of the tree is the room we start from *)
let rec searchPath(tree, r) = 
    match tree with
    | Empty -> (false, 0, [])
    | Leaf l -> if l == r then (true, 0) else (false, 0, [])
    | Node (r, n, e, s, w) as node -> 
       let pn = searchPath(n, r) 
       and pe = searchPath(e, r) 
       and ps = searchPath(s, r)
       and pw = searchPath(w, r)
    in
        find_best_path(p1, p2, p3, p4)
let find_best_path(p1, p2, p3, p4) = 
    match (p1, p2, p3, p4) with
    | ((false,_,_), (false,_,_), (false,_,_), (false,_,_)) -> (false, -1, [])
    | ((true, w, p), (false,_,_), (false,_,_), (false,_,_)) -> (true, w, p)
    | ((false,_,_), (true, w, p)), (false,_,_), (false,_,_)) -> (true, w, p)
    | ((false,_,_), (false,_,_), (true, w, p)), (false,_,_)) -> (true, w, p)
    | ((false,_,_), (false,_,_), (false,_,_),(true, w, p)) -> (true, w, p)
    | ((p1ok, p1w, p1p), (p2ok, p2w, p2p),(p3ok, p3w, p3p),(p4ok, p4w, p4p)) -> 
        if p1ok && p2ok && p3ok && p4ok
        then 
            min_weight([(p1ok, p1w, p1p), (p2ok, p2w, p2p),(p3ok, p3w, p3p),(p4ok, p4w, p4p)])
        else 
        ....
let rec min_weight(l) = 
    match l with
    | [] -> (false, -1, [])
    | [t] -> t 
    | [(to, tw, tp) as t::q] -> let (mo, mw, mp) as minw = min_weight(q) in 
        if tw < mw
        then
            t
        else
            minw

我将根添加到类型定义('a* ...)中,因此我可以制作一个函数以找到要通过的好树。我还假设树尊重以下规则:每个节点的(root, north room, east room, south room, west room)(您可以制作一个添加函数以确保此属性)。

然后,您可以通过从末端探索的树,并获得最小的重量路径,然后结束起点。(它的重量与在相同条件下经过相同路径的重量相同(因为您从一开始就探索树,但从当时的结束来计算路径)。

此代码没有考虑到通过门的可能性,但这只是一项添加的检查,因为已经正确地将穿过树的方式定向了。

我让您完成并更正代码。

希望它对您有帮助。

相关内容

  • 没有找到相关文章

最新更新