首先,一些格式化:
(loop for e in entries do
(if (and (not (member e sub))
(not (member e col)))
(progn (setq choices (nconc choices (list e)))
(print choices)))
(if (= (length choices) 1)
(setq pick (car choices))
(if (not (= (length choices) 0))
(setq pick (nth (random (+ 0 (length choices))) choices))))
然後,如果你不需要的if
的替代條款,但希望有一個progn
,你可以使用when
:
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(setq choices (nconc choices (list e)))
(print choices))
(if (= (length choices) 1)
(setq pick (car choices))
(if (not (= (length choices) 0))
(setq pick (nth (random (+ 0 (length choices))) choices))))
最後兩個if
條款是相互排斥的,因此要麼cond
要麼case
是合適的(我將使用cond
現在):
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(setq choices (nconc choices (list e)))
(print choices))
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (= (length choices) 0))
(setq pick (nth (random (+ 0 (length choices))) choices))))
有一個zerop
斷言:
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(setq choices (nconc choices (list e)))
(print choices))
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (zerop (length choices)))
(setq pick (nth (random (+ 0 (length choices))) choices))))
我看不出有什麼加0到某一值時應該做到:
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(setq choices (nconc choices (list e)))
(print choices))
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (zerop (length choices)))
(setq pick (nth (random (length choices)) choices))))
除非確定pick
設置爲一個合理的默認開始,你應該也許有一個默認情況下(這可能是你的問題之一):
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(setq choices (nconc choices (list e)))
(print choices))
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (zerop (length choices)))
(setq pick (nth (random (length choices)) choices)))
(t
(setq pick nil))
而不是使用setq
和nconc
的,你可以使用push
(這使新的元素在列表的開始,但因爲你挑隨機無論如何,這不應該是一個問題):
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(push e choices)
(print choices))
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (zerop (length choices)))
(setq pick (nth (random (length choices)) choices)))
(t
(setq pick nil))
我懷疑,在這個片段的開始,choices
應該是()
,你不要這個片段後需要choices
,並在打印choices
只是用於調試,所以你可以通過這樣做以不同的方式使用remove-if
並更改條件:
(let ((choices (remove-if (lambda (e)
(or (member e sub)
(member e col)))
entries)))
(print choices)
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (zerop (length choices)))
(setq pick (nth (random (length choices)) choices)))
(t
(setq pick nil)))
如果choices
現在打印爲()
,這意味着有沒有在這裏留下的選擇,所以你將不得不做一些回溯然後(或進入死衚衕時,無論你的算法一樣)。
最後,由於(length choices)
只能爲非負整數,則可以使用case
而不是cond
如果您在不同的順序測試情況:
(let ((choices (remove-if (lambda (e)
(or (member e sub)
(member e col)))
entries)))
(print choices)
(case (length choices)
(0 (setq pick nil))
(1 (setq pick (car choices)))
(otherwise (setq pick (nth (random (length choices)) choices)))))
更新的請求。正如Rainer所指出的,這基本上是一個pick
函數的主體,所以我們可以擺脫所有的自由變量。此外,而不是car
,你可以使用(用於列表)更具描述性的名稱first
:
(defun pick (entries sub col)
(let ((choices (remove-if (lambda (e)
(or (member e sub)
(member e col)))
entries)))
(print choices)
(case (length choices)
(0 nil)
(1 (first choices))
(otherwise (nth (random (length choices)) choices)))))
該功能將定義在別處,而在片段的地方,它會被稱爲是這樣的:
(pick entries sub col)
爲了不計算(length choices)
兩次,我們可以將其寫入let
(這需要成爲let*
串行評估):
(defun pick (entries sub col)
(let* ((choices (remove-if (lambda (e)
(or (member e sub)
(member e col)))
entries))
(choices-length (length choices)))
(print choices)
(case choices-length
(0 nil)
(1 (first choices))
(otherwise (nth (random choices-length) choices)))))
最後一步(真的是可選的,但也許你發現你有更多的序列減少你的選擇,例如, row
)會有點概括:
(defun pick (entries &rest exclusion-sequences)
(let* ((choices (remove-if (lambda (e)
(some #'identity
(mapcar (lambda (seq)
(member e seq))
exclusion-sequences)))
entries))
(choices-length (length choices)))
(print choices)
(case choices-length
(0 nil)
(1 (first choices))
(otherwise (nth (random choices-length) choices)))))
這個函數的調用是相同的形狀,但你現在可以使用任意數量的排除序列:
(pick entries col sub row ver ima fou)
不,條目是在子和列中找不到的元素的列表。 Col表示我在當前循環中的列,sub表示棋盤的子矩陣。具有
作爲表,對於迭代3,col表示(1 2 -1)和sub((2 2 2)(3 3 -1)) – Manticore