在 Lisp 中实现车移动和可能移动的最佳方式

Best way to implement rook moves and possible moves in Lisp

我有棋盘 [8,8],我正在尝试根据棋盘上、下、左、右的移动、车的移动来实现水平移动和垂直移动,但我遇到了困难在如何将棋子移动到正方形与要移动的正方形数量中。

(defun board ()
 '((64 35 74 26 21 57 12 28) 
   (43 15 47 53 24 56 42 29) 
   (51 41 71 31 17 45 55 30) 
   (67 66 22 T 54 75 32 38) 
   (13 11 16 23 25 27 33 20) 
   (34 36 37 44 46 52 61 48) 
   (10 49 59 69 68 70 50 40) 
   (62 63 65 72 73 76 77 58)))

车向前或向后水平和垂直移动任意数量的方格。在图中,车可以移动到任何突出显示的方块。

检查坐标是否有效的函数

(defun position-valid (x y)
  (and (>= x 0) (>= y 0) (< x 8) (< y 8)))

根据坐标 (x, y) 移动塔的函数

(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))

下移棋子的函数

 (defun DOWN (x y board) 
   (cond
    ((equal (position-valid (+ x 1) (+ y 0)) 'T)
     (move-piece x y 1 0 board))
    (T NIL)))

将棋子向上移动的函数

(defun UP (x y board) 
  (cond
    ((equal (position-valid (- x 1) (+ y 0)) 'T)
     (move-piece x y -1 0 board))
    (T NIL)))

将棋子向左移动的函数

(defun LEFT (x y board) 
  (cond
    ((equal (position-valid (+ x 0) (- y 1)) 'T)
     (move-piece x y 0 -1 board))
    (T NIL)))

将棋子向右移动的函数

(defun RIGHT (x y board) 
  (cond
    ((equal (position-valid (+ x 0) (+ y 1)) 'T)
     (move-piece x y 0 1 board))
   (T NIL)))

现在的目标是在上面提到的运动的基础上实现垂直和水平的运动,让棋子移动,在这种情况下,我认为我们仍然需要根据运动的类型来实现可能的运动以及要移动多少个方块

我实现了这个用于水平和垂直移动的运算符列表,但它不起作用

水平移动塔的函数

(defun HORIZONTAL (x y n mov board) ;;n is number of square to move
  (cond
    ((and (equal (position-valid (+ x 0) (- y 1)) 'T) ;;left
          (equal (position-valid (+ x 0) (+ y 1)) 'T));;right     
          (cond
               ((equal mov 'LEFT)  (LEFT x y board))
               ((equal mov 'RIGHT) (RIGTH x y board))
               (T (HORIZONTAL x y (1- n) mov board))))
   (T NIL)))

使塔在垂直方向移动的功能,

(defun VERTICAL(x y n mov board) ;;n is number of square to move
  (cond
    ((and (equal (position-valid (- x 1) (+ y 0)) 'T) ;;up
          (equal (position-valid (+ x 1) (+ y 0)) 'T));;down
          (cond
               ((equal mov 'DOWN)  (DOWN x y board))     
               ((equal mov 'UP)    (UP x y board))
               (T (VERTICAL x y (1- n) mov board))))
   (T NIL)))

以及如何根据移动类型获取棋盘上塔的可能移动

有什么建议吗?

在我看来,您构建了太多不必要的功能。我要做的是拥有一个基于 move-piece 的 MOVE 函数,它可以进行水平和垂直位移。由于你有参数mov,它可以是UP、DOWN、LEFT或RIGHT,水平和垂直运动已经是隐含的,所以不需要每个方向都有一个单独的函数。
所以这就是我要做的:

(setq board 
 '((64 35 74 26 21 57 12 28) 
   (43 15 47 53 24 56 42 29) 
   (51 41 71 31 17 45 55 30) 
   (67 66 22 T 54 75 32 38) 
   (13 11 16 23 25 27 33 20) 
   (34 36 37 44 46 52 61 48) 
   (10 49 59 69 68 70 50 40) 
   (62 63 65 72 73 76 77 58)))


(defun position-valid (x y)
  (and (>= x 0) (>= y 0) (< x 8) (< y 8)) )


(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))) )
    (when (position-valid new-x new-y)
      (setf (nth x (nth y new-board)) nil
          (nth new-x (nth new-y new-board)) piece ))
    new-board))


(defun MOVE (x y n mov board) ;; n is number of squares to move
  (case mov
    (UP (move-piece x y 0 (- n) board))
    (DOWN (move-piece x y 0 n board))
    (LEFT (move-piece x y (- n) 0 board))
    (RIGHT (move-piece x y n 0 board))
    (otherwise NIL) ))

然后,如果您想获得所有可能走法的列表:

(defun valid-moves (x y board)
  (let (result)
    (dolist (mov '(up down left right) result)
      (dotimes (n 7)
        (when (move x y n mov board)
          (push (list n mov) result) )))))