检查对角线时的逻辑错误 - nQueens

时间:2016-10-05 21:23:47

标签: list lisp common-lisp

用values-list解决了我的错误,并且能够运行我的程序直到最后,我发现我的对角检查似乎有一个逻辑错误。我的意见如下:

(THREAT?'(1 3)'((1 0)(2 4)(3 0)(4 0)(5 0)(6 0)(7 0)(8 0)))

我们正在测试的第一个参数是板空间是否可以放置一个后置,第二个参数是板的状态,y值1-8确定一个块的列位置和0值将表示x值行没有任何部分。我的代码如下:

(defun diagonal(point1 point2)
    (= (abs (- ( car point1 ) ( car point2 )))
       (abs (- ( cadr point1 ) ( cadr point2 ))))
)

(defun THREAT?(x y)
    ; Checks threat on the vertical
    (when (not (eq (values-list (cdr (nth (- (car x) 1 ) y )) ) '0 ) )
            (return-from THREAT? t)
    )
    (loop for i from 0 to (list-length y)

            ; Checks threat on the horizontal
            when (eq (values-list ( cdr x  )) (values-list (cdr (nth i y))) )
                    do (return-from THREAT? t)
            ; With the help of the diagonal function checks along the diagonal
            when (diagonal x (nth i y) )
                    do (return-from THREAT? t)
    )
)

如果我的理解是正确的,我的程序应该循环遍历y的每个元素。它会将x和当前y对传递给对角线函数。对角函数将减去它们的绝对值并检查它们是否相等(如果它们是对角线则它们应该是ex。(1 2)和(2 3)是对角线因此| 1 - 2 | = 1和| 2 - 3 | = 1)。如果这些数字相等,则对角线函数应返回true。相应的when语句只应在从对角线函数接收到true时激活,但它似乎总是返回true,即使我给程序一个完全空白的板。如何修正对角线以正确确定板上的威胁?非常感谢任何和所有的帮助!

1 个答案:

答案 0 :(得分:3)

我已经将代码重写为更好的Lisp风格。

  • 更好的命名。
  • 有用名称的程序会使注释变得多余
  • 个别程序更易于测试
  • 摆脱了VALUES-LIST废话
  • 摆脱所有CAR,CDR,CADR。使用FIRST和SECOND。
  • 介绍了点的x和y组件的访问器
  • 用RETURN-FROM摆脱了奇怪的控制流程,用简单的OR替换它
  • 实际上直接遍历列表,而不是一直使用NTH
  • EQ不用于比较数字相等,使用=而不是
  • 不要将括号单独放在一条线上。
  • 缩进并正确格式化代码
  • 不要在括号之间加上空格
  • 在原子和左括号之间放置一个空格

<强>代码:

(defun get-x (point)
  (first point))

(defun get-y (point)
  (second point))

(defun diagonal? (point1 point2)
  (= (abs (- (get-x point1) (get-x point2)))
     (abs (- (get-y point1) (get-y point2)))))

(defun vertical? (point)
  (not (zerop (get-y point))))

(defun horizontal? (point1 point2)
  (= (get-y point1)
     (get-y point2)))

(defun threat? (point list-of-columns)
  (or (vertical? (nth (1- (get-x point)) list-of-columns))
      (loop for point2 in list-of-columns
            when (or (horizontal? point point2)
                     (diagonal?   point point2))
            return t)))

示例

现在我们可以追踪三个威胁谓词:

? (trace vertical? diagonal? horizontal?)
NIL

现在你可以打电话给你的例子:

? (threat? '(1 3) '((1 0) (2 4) (3 0) (4 0) (5 0) (6 0) (7 0) (8 0)))
0> Calling (VERTICAL? (1 0)) 
<0 VERTICAL? returned NIL
0> Calling (HORIZONTAL? (1 3) (1 0)) 
<0 HORIZONTAL? returned NIL
0> Calling (DIAGONAL? (1 3) (1 0)) 
<0 DIAGONAL? returned NIL
0> Calling (HORIZONTAL? (1 3) (2 4)) 
<0 HORIZONTAL? returned NIL
0> Calling (DIAGONAL? (1 3) (2 4)) 
<0 DIAGONAL? returned T
T

这应该会有所帮助,以便您可以更好地调试代码...查看跟踪输出。

不使用空列描述的版本

(defun get-x (point)
  (first point))

(defun get-y (point)
  (second point))

(defun diagonal? (point1 point2)
  (= (abs (- (get-x point1) (get-x point2)))
     (abs (- (get-y point1) (get-y point2)))))

(defun vertical? (point list-of-columns)
  (let ((point2 (find (get-x point) list-of-columns :key #'get-x)))
    (and point2 (not (zerop (get-y point2))))))

(defun horizontal? (point1 point2)
  (= (get-y point1)
     (get-y point2)))

(defun threat? (point list-of-columns)
  (or (vertical? point list-of-columns)
      (loop for point2 in list-of-columns
            when (or (horizontal? point point2)
                     (diagonal?   point point2))
            return t)))

(defun print-board (board)
  (format t "~%+-+-+-+-+-+-+-+-+")
  (dotimes (y 8)
    (terpri)
    (dotimes (x 8)
      (format t "|~a" (if (member (list x y) board :test #'equal) "x" " ")))
    (format t "|~%+-+-+-+-+-+-+-+-+")))

示例:

CL-USER 138 > (threat? '(1 2) '((2 4)))
NIL

CL-USER 139 > (print-board '((1 2) (2 4)))

+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| |x| | | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| | |x| | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
NIL

另一个例子:

CL-USER 140 > (threat? '(1 2) '((2 4) (4 5)))
T

CL-USER 141 > (print-board '((1 2) (2 4) (4 5)))

+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| |x| | | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| | |x| | | | | |
+-+-+-+-+-+-+-+-+
| | | | |x| | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
| | | | | | | | |
+-+-+-+-+-+-+-+-+
NIL