所以我正在进行A *搜索8拼图,它似乎有效,但问题是一旦找到解决方案,它就会继续通过优先级映射并输出所有可能性。一旦遇到病情,有没有办法停止输出?
注意:我觉得使用for循环使doseqs懒惰并使它们不是eval整个事情是最好的。有没有办法做到这一点?
这是我的代码:
(defn a-star
([board history]
(if (at-end? board) (print-board board)
(let [options (filter #(possible-move? % board) *moves*)
move (into (pm/priority-map) (for [move options] [move (global-man-dis (move-tile board move))]))]
(doseq [pair move :let [next-move (key pair)]]
(print-board (move-tile board next-move))
(println)
(a-star (move-tile board next-move) next-move (conj history board))
)
)
))
([board prev-move history]
(if (or (at-end? board) (history-check history board)) (print-board board)
(let [options (get-queue board (dont-go-back prev-move))
move (into (pm/priority-map) (for [move options] [move (global-man-dis (move-tile board move))]))]
(doseq [pair move :let [next-move (key pair)]]
(print-board (move-tile board next-move))
(println)
(a-star (move-tile board next-move) next-move (conj history board))
)
)
)))
(defn -main [& args]
(println "insert a list all numbers no spaces or letters")
(def board (mapv (fn [^Character c] (Character/digit c 10)) (read-line)))
;(def testt [0 8 4 7 2 1 3 5 6])
;(def testt [1 2 3 5 4 6 8 0 7])
(a-star board [])
)
答案 0 :(得分:2)
为了扩展我昨天的评论,这里是Clojure中完整的通用A *实现。由于你没有在你的a-star
函数中包含各种辅助函数,我不知道你是如何将8拼图问题转化为图搜索问题,但你应该能够自己调整以下代码。
(ns a-star.core
(:require [clojure.data.priority-map :refer [priority-map]]))
(defn pred->path
"Determine the path to GOAL from the map of predecessors PRED."
[pred goal]
(loop [node goal, path ()]
(if (contains? pred node)
(recur (pred node) (cons node path))
(cons node path))))
(defn expand
[node h [open g pred] succ cost]
(let [g-succ (+ (g node) cost)]
(if (and (contains? open succ)
(>= g-succ (g succ)))
[open g pred]
[(assoc open succ (+ g-succ (h succ)))
(assoc g succ g-succ)
(assoc pred succ node)])))
(defn a*
"Determine the shortest path from START to GOAL in graph GRAPH
with heuristic cost function H. GRAPH format is {from {to cost}}."
[start goal graph h]
(loop [open (priority-map start 0)
closed ()
g {start 0}
pred {}]
(if (empty? open)
:no-path-found
(let [node (key (peek open))]
(if (= node goal)
[:path-found (pred->path pred goal) (g goal)]
(let [successors (apply dissoc (graph node) closed)
[open* g* pred*] (reduce-kv (partial expand node h)
[(pop open) g pred]
successors)]
(recur open* (conj closed node) g* pred*)))))))
测试代码应阐明如何使用a*
函数:
(ns a-star.core-test
(:require [clojure.test :refer :all]
[a-star.core :refer :all]))
(deftest test-a*
(is (= (a* :sb :wb
{:sb {:kl 70, :kr 145}
:kl {:ff 103, :lh 53}
:ff {:wb 116}
:lh {:wb 183}
:kr {:hb 84}
:hb {:wb 102}}
{:sb 222, :kl 158, :ff 96, :wb 0, :lh 108, :kr 140, :hb 87})
[:path-found '(:sb :kl :ff :wb) 289])
"Find path in a directed graph.")
(is (= (a* :sb :wb
{:sb {:kl 70, :kr 145}
:kl {:sb 70, :ff 103, :lh 53}
:ff {:kl 103, :wb 116}
:lh {:kl 53, :wb 183}
:kr {:sb 145, :hb 84}
:hb {:kr 84, :wb 102}
:wb {:ff 116, :lh 183, :hb 102}}
{:sb 222, :kl 158, :ff 96, :wb 0, :lh 108, :kr 140, :hb 87})
[:path-found '(:sb :kl :ff :wb) 289])
"Find path in an undirected graph.")
(is (= (a* :sb :wb
{:kl {:sb 70}
:ff {:kl 103}
:lh {:kl 53}
:kr {:sb 145}
:hb {:kr 84}
:wb {:ff 116, :lh 183, :hb 102}}
{:sb 222, :kl 158, :ff 96, :wb 0, :lh 108, :kr 140, :hb 87})
:no-path-found)
"Find no path in reversed directed graph."))
答案 1 :(得分:1)
一种常见的方法是在最后的递归调用周围添加if
语句。类似的东西:
(if-not (finished? move)
(a-star ... ))
ps:一个无关紧要的格式化点,如果所有连续的结束)
都在同一条线上,一些clojure程序员会发现它更容易阅读,尽管这纯粹是个人品味。