好吧,所以我在Lisp中编写一个程序来解决拼图(http://www.tilepuzzles.com/default.asp?p=12),我的两个函数都有问题。我有单独的功能来“交换”空的瓷砖与它的上方,下方,左侧或右侧,但只有上面和左侧工作。 switch_above和switch_below之间的唯一区别是在一个中使用+
而在另一个中使用-
(参见代码),据我所知,这是造成问题的原因。< / p>
;;Switches the Empty tile with whatever is above it
(defun switch_above (state)
(let ((x (nth (- (find_empty state) 3) state))) ;;Find the number that is above the Empty tile, set as X
(setf (nth (find_empty state) state) x) ;;Replace the Empty tile with X
(setf (nth (position x state) state) 'E)) state) ;;Put Empty tile where X was
;;Switches the Empty tile with whatever is below it
(defun switch_below (state)
(let ((x (nth (+ (find_empty state) 3) state))) ;;Find the number that is below the Empty tile, set as X
(setf (nth (find_empty state) state) x) ;;Replace the Empty tile with X
(setf (nth (position x state) state) 'E)) state) ;;Put Empty tile where X was
“状态”列表设置如下:
(1 2 3 4 E 5 6 7 8)
其中E是空图块
find_empty
返回空图块的位置,因此它将在上述状态下返回4.
撰写时switch_above
可以正常使用,但switch_below
没有。
答案 0 :(得分:4)
考虑在SETF
中执行第一次switch_below
时会发生什么。
ROTATEF旋转地点
尝试使用Common Lisp宏ROTATEF。见这个例子:
CL-USER 76 > (defun find-empty (state)
(position 'e state))
FIND-EMPTY
CL-USER 77 > (defun switch-below (state &aux (empty-pos (find-empty state)))
(rotatef (nth empty-pos state)
(nth (+ empty-pos 3) state))
state)
SWITCH-BELOW
CL-USER 78 > (switch-below '(1 2 3 4 E 5 6 7 8))
(1 2 3 4 7 5 6 E 8)
顺便说一句:如果有人想知道为什么我在上面的交互中使用了引用列表。在Common Lisp中,修改文字列表的后果是未定义的。好吧,我们使用的是Lisp Listener(Read Eval Print Loop)。 read
部分通常为每个交互分配一个新的新列表,并且在实现中通常这些列表不受任何保护。怎么可能出错? a)列表可以再次受到保护修改。 b)它可以与其他列表共享结构(可能很难被用户检测到)。
在程序中最好写一些像
这样的东西(switch-below (copy-list '(1 2 3 4 E 5 6 7 8)))
避免上述问题。