我有这两个基本功能:
(defun dice ()
(+ 1 (random 6)))
(defun five-dice ()
(list (dice) (dice) (dice) (dice) (dice)))
他们所做的只是创建一个五个掷骰子的列表。我想要做的是选择一定数量的骰子再次滚动。意思是,我想选择2,3或全部五个再次滚动,并替换重新掷骰子,同时保留我决定不滚动的骰子。我想使用用户输入来做到这一点。
我的假设是,最好的方法是使用符号,但我已经尝试了大约一天,无法确定如何做到这一点。这就是我决定寻求帮助的原因。
编辑:谢谢大家的帮助,我真的很感激。我无法理解lisp如何接受用户输入,以及如何将其存储到变量中。
所以,我创建了一个全局变量,并将其用作用户的初始滚动,但是一旦我尝试使用来自用户的输入来重新滚动某些骰子,那就是我无法理解的部分。我看了几个例子,我试图重新创建它,但它不适合我:
(defun testfunction()
(terpri)
(princ "would you like to roll? ")
(read-line)
(if (member (read-line) '("y" "yes" "") :test #'string=)
(let ((roll (five-dice)))
)))
这就是我想要开始工作的事情,因此,在用户输入yes或y之后,它会给他们5个骰子,并且它会给他们3次机会重新掷出任意数量的骰子他们要。所以,这就是我目前正在努力开展的工作。
EDIT2:
(defun roll-again(lst)
(if (null lst)nil
(setf (nth (car lst) list-dices)(dice))
(yup (cdr lst))
))
为什么这个功能不起作用?我现在要做的是使用此功能重新掷出用户选择的骰子。所以,一旦我从用户那里得到输入,我就把这个输入放到一个列表中,然后用这个函数来重新掷骰子。但是,由于某种原因,我无法使用此功能。
答案 0 :(得分:2)
最简单的方法是使用MAPCAR
浏览列表,询问用户是否要重新掷骰子。
(defun dice ()
(1+ (random 6)))
(defun roll-dice (&optional (n 5))
(let ((dice (loop repeat n collecting (dice))))
(format *query-io* "Rolled: ~{~a~^, ~}." dice)
(finish-output *query-io*)
(mapcar (lambda (d)
(if (y-or-n-p "Roll ~a again?" d)
(dice)
d))
dice)))
修改强>
在你的编辑中,你说用户应该可以重复掷任意数量的骰子三次。这是一个允许他们这样做的版本:
(defun roll-dice (&optional (n 5))
(loop with dice = (loop repeat n collecting (dice))
for rolls-left from 3 downto 1
while (y-or-n-p "Rolled: ~{~a~^, ~}.~@
Re-roll (~a re-roll~:*~p left)?"
dice rolls-left)
do (map-into dice
(lambda (d)
(if (y-or-n-p "Roll ~a again?" d)
(dice)
d))
dice)
finally (return dice)))
答案 1 :(得分:0)
我认为对于小清单,您最好的选择是访问列表中的元素并进行修改。例如,使用函数nth,如果你想修改你可以这样做的第二个元素:
CL-USER> (defparameter list-dices (five-dice))
LIST-DICES
CL-USER> list-dices
(1 5 2 3 2)
CL-USER> (setf (nth 1 list-dices) (dice))
2
CL-USER> list-dices
(1 2 2 3 2)
答案 2 :(得分:0)
像这样的东西可能适用于重新滚动:
(defun reroll-specific-dice (dice-list reroll-list)
"Takes a list of dice results, and a list of dice indexes to reroll,
returns a list of those dice, re-rolled. This function is non-destructive."
(let ((dice-list (copy-list dice-list)))
(loop for reroll-index in reroll-list
do (setf (nth reroll-index dice-list) (dice)))
dice-list))
这可以通过跳过let
/ copy-list
来破坏,但非破坏性通常会更好。这也没有错误检查。它也不涉及从用户那里获取输入,因为以一种非常用户友好的方式做这件事是我没有时间写的。
对于“最小”用户输入,您可以执行以下操作:
(defun get-dice-to-reroll ()
(format t "Provide a list of dice to reroll, between parentheses: ")
(finish-output)
(read))
同样,这只有最少的错误检查,但会返回一个适合作为reroll-list
转发到reroll-specific-dice
的列表。