在 Lisp 中验证棋盘上的移动和移动棋子

validate moves and move pieces on the board in Lisp

下面这个项目我有这个板[10,10],我不能移动板上的棋子

这个问题是关于 Lisp 的其他问题的一部分,你可以在我的个人资料上看到

(defun board ()
  "T in position x=0 and y=0"
  '(
    (T 25 54 89 21 8 36 14 41 96) 
    (78 47 56 23 5 NIL 13 12 26 60) 
    (0 27 17 83 34 93 74 52 45 80) 
    (69 9 77 95 55 39 91 73 57 30) 
    (24 15 22 86 1 11 68 79 76 72) 
    (81 48 32 2 64 16 50 37 29 71) 
    (99 51 6 18 53 28 7 63 10 88) 
    (59 42 46 85 90 75 87 43 20 31) 
    (3 61 58 44 65 82 19 4 35 62) 
    (33 70 84 40 66 38 92 67 98 97)
    )
)

不一样但相似,这里的行从 1 开始,但在项目中是从 0 开始的

and this function to print the board

(defun print-board (board)
    (format T "~%")
    (mapcar (lambda (x) (format T " ~A ~%" x)) board)
    (format nil ""))

I have 8 movements implemented but I only put 4 examples for the question not to get too much code

(defun UP-LEFT (x y board)
  "Function that receives 2 indexes and board, validate movement and move piece up and left"
    (cond
        ((equal (validate-movements (- x 1) (- y 2) board) 0) 
         (move-piece x y -1 -2 board))
        (T nil)))

(defun UP-RIGHT (x y board)
  "receive 2 indexes and board, validate movement and move piece up and right"
    (cond
        ((equal (validate-movements (+ x 1) (- y 2) board) 0) 
         (move-piece x y 1 -2 board))
        (T nil)))

(defun LEFT-DOWN (x y board)
   "Function that receives 2 indexes and board, validate movement and move piece left and down"
    (cond
        ((equal (validate-movements (- x 2) (+ y 1) board) 0)
         (move-piece x y -2 1 board))
        (T nil)))

(defun LEFT-UP (x y board)
   "Function that receives 2 indexes and board, validate movement and move piece left and up"
    (cond
        ((equal (validate-movements (- x 2) (- y 1) board) 0) 
         (move-piece x y -2 -1 board))
        (T nil)))

(defun DOWN-RIGHT (x y board)
   "Function that receives 2 indexes and board, validate movement and move piece down and right"
    (cond
        ((equal (validate-movements (+ x 1) (+ y 2) board) 0)
         (move-piece x y 1 2 board))
        (T nil)))

my doubt is in this move piece in board in axis (x,y)

(defun move-piece (x y dx dy board)
 "Function that receives two indexes and board to move the piece on the board"
  (mapcar 
    (lambda (L) 
        (cond
            ((atom L) L)
            ((and 
             (equal (nth 0 L) x) 
             (equal (nth 1 L) y)) 
             (list (+ (nth 0 L) dx) (+ (nth 1 L) dy) (nth 2 L) 
                   (nth 3 L) (nth 4 L) (nth 5 L) (nth 6 L) 
                   (nth 7 L) (nth 8 L) (nth 9 L)))
    (T L))) board))

and this function to validate movements

(defun validate-movements (x y board)   
 "Function that receives two indexes and board to validate movement"
  (cond 
      ((and 
           ;; validation of rows and columns
           (>= x 0) 
           (>= y 0) 
           (<= x 9) 
           (<= y 9) 
           (= (apply '+ (mapcar (lambda (L) 
                                       (cond 
                                           ((atom L) 0)
                                           ((or (not(equal (nth 0 L ) x)) (not (equal (nth 1 L) y))) 0) 
                                           (T 1))) board)) 0)) 0)
    (T nil )))

when I try to test the movements https://ideone.com/jaeCLu it's not move, because don´t return nothing and show nothing

我做错了什么?

让我们看一下验证函数。首先,做出明智的 limebreaks:当多行表单关闭时,打破行。

(defun validate-movements (x y board)
  "Function that receives two indexes and board to validate movement"
  (cond ((and
          ;; validation of rows and columns
          (>= x 0)
          (>= y 0)
          (<= x 9)
          (<= y 9)
          (= (apply '+
                    (mapcar (lambda (L)
                              (cond ((atom L) 0)
                                    ((or (not (equal (nth 0 L ) x))
                                         (not (equal (nth 1 L) y)))
                                     0)
                                    (T 1)))
                            board))
             0))
         0)
        (T nil )))

只有两种可能结果的情况最好通过 if 处理:

(defun validate-movements (x y board)
  "Function that receives two indexes and board to validate movement"
  (if (and
       ;; validation of rows and columns
       (>= x 0)
       (>= y 0)
       (<= x 9)
       (<= y 9)
       (= (apply '+
                 (mapcar (lambda (L)
                           (cond ((atom L) 0)
                                 ((or (not (equal (nth 0 L ) x))
                                      (not (equal (nth 1 L) y)))
                                  0)
                                 (T 1)))
                         board))
          0))
      0
      nil))

<=这样的比较器可以接受更多的参数:

(defun validate-movements (x y board)
  "Function that receives two indexes and board to validate movement"
  (if (and (<= 0 x 9)
           (<= 0 y 9)
           (= (apply '+
                     (mapcar (lambda (L)
                               (cond ((atom L) 0)
                                     ((or (not (equal (nth 0 L) x))
                                          (not (equal (nth 1 L) y)))
                                      0)
                                     (T 1)))
                             board))
              0))
      0
      nil))

由于您的面板是一个列表列表(每行一个 10 元素子列表),所以一行永远不会是一个原子:

(defun validate-movements (x y board)
  "Function that receives two indexes and board to validate movement"
  (if (and (<= 0 x 9)
           (<= 0 y 9)
           (= (apply '+
                     (mapcar (lambda (L)
                               (cond ((or (not (equal (nth 0 L) x))
                                          (not (equal (nth 1 L) y)))
                                      0)
                                     (T 1)))
                             board))
              0))
      0
      nil))

同样,双子句条件句比 if:

(defun validate-movements (x y board)
  "Function that receives two indexes and board to validate movement"
  (if (and (<= 0 x 9)
           (<= 0 y 9)
           (= (apply '+
                     (mapcar (lambda (L)
                               (if (or (not (equal (nth 0 L) x))
                                       (not (equal (nth 1 L) y)))
                                   0
                                   1))
                             board))
              0))
      0
      nil))

现在,我想告诉您布尔值如何更容易表达逻辑。但是,这种情况对我来说毫无意义:您似乎检查了板上是否有某条线在其第一个字段中带有 x 坐标,在第二个字段中带有 y 坐标。

也许您想检查目标坐标是否为空?

(defun target-valid-p (x y board)
  (and (<= 0 x 9)
       (<= 0 y 9)
       (null (nth x (nth y board)))))

接下来,移动功能。同样,换行符:

(defun move-piece (x y dx dy board)
  "Function that receives two indexes and board to move the piece on the board"
  (mapcar (lambda (L) 
            (cond
              ((atom L) L)
              ((and (equal (nth 0 L) x) 
                    (equal (nth 1 L) y)) 
               (list (+ (nth 0 L) dx) (+ (nth 1 L) dy) (nth 2 L) 
                     (nth 3 L) (nth 4 L) (nth 5 L) (nth 6 L) 
                     (nth 7 L) (nth 8 L) (nth 9 L)))
              (T L)))
          board))

你的线条永远不是原子:

(defun move-piece (x y dx dy board)
  "Function that receives two indexes and board to move the piece on the board"
  (mapcar (lambda (L) 
            (cond
              ((and (equal (nth 0 L) x) 
                    (equal (nth 1 L) y)) 
               (list (+ (nth 0 L) dx) (+ (nth 1 L) dy) (nth 2 L) 
                     (nth 3 L) (nth 4 L) (nth 5 L) (nth 6 L) 
                     (nth 7 L) (nth 8 L) (nth 9 L)))
              (T L)))
          board))

双分支条件是if:

(defun move-piece (x y dx dy board)
  "Function that receives two indexes and board to move the piece on the board"
  (mapcar (lambda (L) 
            (if (and (equal (nth 0 L) x) 
                     (equal (nth 1 L) y)) 
                (list (+ (nth 0 L) dx) (+ (nth 1 L) dy) (nth 2 L) 
                      (nth 3 L) (nth 4 L) (nth 5 L) (nth 6 L) 
                      (nth 7 L) (nth 8 L) (nth 9 L))
                L))
          board))

使用list*nthcdr更新列表的一部分:

(defun move-piece (x y dx dy board)
  "Function that receives two indexes and board to move the piece on the board"
  (mapcar (lambda (L) 
            (if (and (equal (nth 0 L) x) 
                     (equal (nth 1 L) y)) 
                (list* (+ (nth 0 L) dx)
                       (+ (nth 1 L) dy)
                       (nthcdr 2 L))
                L))
          board))

现在看来您又一次只更新了该行的前两个单元格。也许我不理解你的数据模型,但我以为你只是想更新给定坐标处的单元格:

(defun move-piece (x y dx dy board)
  (let ((new-board (copy-tree board))
        (new-x (+ x dx))
        (new-y (+ y dy))
        (piece (nth x (nth y board))))
    (setf (nth x (nth y new-board)) nil
          (nth new-x (nth new-y new-board)) piece)
    new-board))