List 如何操作由列表组成的复杂数据结构?

List 如何操作由列表组成的复杂数据结构?,list,lisp,common-lisp,connect,List,Lisp,Common Lisp,Connect,我试图展示一个3D Connect 4棋盘游戏: 例如,我有以下列表结构: ( ( (NIL NIL NIL NIL) (NIL NIL NIL NIL) (NIL NIL NIL NIL) (NIL NIL NIL NIL) ) (1 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 10 10 10 10) ) 每个NIL代表其中的一个位置。例如,如果我在第一个位置放置两块(一块黑色,另一块白色),它将如下所示: ( ( ((B W) NIL N

我试图展示一个3D Connect 4棋盘游戏:

例如,我有以下列表结构:

(
(
(NIL NIL NIL NIL)
(NIL NIL NIL NIL)
(NIL NIL NIL NIL)
(NIL NIL NIL NIL)
)
(1 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 10 10 10 10)
)
每个NIL代表其中的一个位置。例如,如果我在第一个位置放置两块(一块黑色,另一块白色),它将如下所示:

(
(
((B W) NIL NIL NIL)
(NIL NIL NIL NIL)
(NIL NIL NIL NIL)
(NIL NIL NIL NIL)
)
(1 1 1 1 1 1 1 1 1 1 1 1 10 10 10 10 10 10 10 10 10 10 10 10)
)
这意味着W将是底部的那个。我还需要将它们相互比较,以便程序能够说明何时找到了获胜者


如何在每个位置添加碎片?既然它们是具有NIL值的列表,我该如何比较它们呢?

原则上,如果您有一个列表列表,那么您可以使用嵌套的
n
调用到达要检查的位置。在这种特定情况下,
nth
的线性时间特性可能并不可怕,但我可能会使用4x4列表数组,或4x4x4数组,尽管在这种情况下,您最终需要自己跟踪“下一个位置”,即使这会简化“检查获胜条件”逻辑

以及如何使用
push
nth
改变列表列表列表的示例(我编辑了s的显示方式,以使其“Arraynes”更易于查看):


无论您选择使用什么实现,最好定义一个接口来操作您的对象。下面,我定义了
makeboard
push-token
pop-token
功能。您还可以定义其他访问器函数,例如获取坐标(x y z)处的值

然后,您只需通过此接口操作数据,以便代码可读且易于维护。我使用的是向量的2D矩阵,其中内部向量由于其填充指针而被用作堆栈(有关详细信息,请参阅)

板类和令牌类型 建造师 定制打印机 推动(x,y) 从(x,y)弹出 试验 输出
#
# 
# 
# 
# 
# 
# 
# 
#

您是如何决定此特定数据结构的?底部的1和10是什么?您是否考虑使用多维数组来代替?使用LISP的常用列表函数。这有什么不对?你是要有一个状态并对其进行变异,还是要用回溯算法?结构的选择通常有好处和权衡,因此,尽管有很多可能的方法可以做到这一点,但在特定环境下,只有少数几种方法是最优的。我想象在地图中得到切片,也许第一个元素应该是底部,或者元素是带有占位符的列表,这样第一个元素就是顶部,即使顶部还没有放好。你知道,还有一个
向量pop
@Svante谢谢,不知怎的,我没有想到它
* *s*

((NIL NIL NIL NIL) 
 (NIL NIL NIL NIL) 
 (NIL NIL NIL NIL) 
 (NIL NIL NIL NIL))
* (push 'w (nth 0 (nth 0 *s*)))

(W)
* *s*

(((W) NIL NIL NIL) 
 (NIL NIL NIL NIL) 
 (NIL NIL NIL NIL) 
 (NIL NIL NIL NIL))
(defclass board ()
  ((matrix :reader board-matrix :initarg :matrix)
   (size :reader board-size :initarg :size)))

(deftype token-type () '(member white black))
(defun make-board (size)
  (let ((board
         (make-array (list size size))))
    (dotimes (i (array-total-size board))
      (setf (row-major-aref board i)
            (make-array size
                        :element-type 'symbol
                        :fill-pointer 0)))
    (make-instance 'board :matrix board :size size)))
(defmethod print-object ((b board) stream)
  (print-unreadable-object (b stream :type t)
    (let ((matrix (board-matrix b))
          (size (board-size b)))
      (dotimes (row size)
        (fresh-line)
        (dotimes (col size)
          (let* ((stack (aref matrix row col)))
            (dotimes (z size)
              (princ (case (aref stack z)
                       (white #\w)
                       (black #\b)
                       (t #\.))
                     stream)))
          (princ #\space stream))))))
(defun push-token (board x y token)
  (check-type token token-type)
  (vector-push token (aref (board-matrix board) y x)))
(defun pop-token (board x y)
  (ignore-errors
    (let ((stack (aref (board-matrix board) y x)))
      (prog1 (vector-pop stack)
        ;; we reset the previous top-most place to NIL because we
        ;; want to allow the access of any cell in the 3D
        ;; board. The fill-pointer is just here to track the
        ;; position of the highest token.
        (setf (aref stack (fill-pointer stack)) nil)))))
(let ((board (make-board 4)))
  (flet ((@ (&rest args) (print board)))
    (print board)
    (@ (push-token board 1 2 'white))
    (@ (push-token board 1 2 'black))
    (@ (push-token board 1 2 'white))
    (@ (push-token board 1 2 'black))
    (@ (push-token board 1 2 'black))
    (@ (push-token board 0 3 'white))
    (@ (pop-token board 1 2))
    (@ (pop-token board 1 2))))
#<BOARD 
.... .... .... .... 
.... .... .... .... 
.... .... .... .... 
.... .... .... .... > 
#<BOARD 
.... .... .... .... 
.... .... .... .... 
.... w... .... .... 
.... .... .... .... > 
#<BOARD 
.... .... .... .... 
.... .... .... .... 
.... wb.. .... .... 
.... .... .... .... > 
#<BOARD 
.... .... .... .... 
.... .... .... .... 
.... wbw. .... .... 
.... .... .... .... > 
#<BOARD 
.... .... .... .... 
.... .... .... .... 
.... wbwb .... .... 
.... .... .... .... > 
#<BOARD 
.... .... .... .... 
.... .... .... .... 
.... wbwb .... .... 
.... .... .... .... > 
#<BOARD 
.... .... .... .... 
.... .... .... .... 
.... wbwb .... .... 
w... .... .... .... > 
#<BOARD 
.... .... .... .... 
.... .... .... .... 
.... wbw. .... .... 
w... .... .... .... > 
#<BOARD 
.... .... .... .... 
.... .... .... .... 
.... wb.. .... .... 
w... .... .... .... >