我有以下两项基本职能:
(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))) )))
这就是我想要做的,所以,在用户输入“是”或“y”之后,它会给他们5个骰子,并给他们3次机会重新掷出他们想要的骰子。所以,这就是我现在想要的工作。
Edit2:
(defun roll-again(lst) (if (null lst)nil (setf (nth (car lst) list-dices)(dice)) (yup (cdr lst)) ))
为什么这个功能不起作用?我现在要做的是使用这个函数重新滚动用户选择的骰子。所以,一旦我从用户那里得到输入,我就把输入放到一个列表中,然后使用这个函数重新滚动那些骰子。但是,由于某种原因,我无法让这个函数工作。
发布于 2016-06-20 02:08:44
最简单的方法是使用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)))
发布于 2016-06-20 00:36:48
我认为对于小列表,您的最佳任务是访问列表中的元素并对其进行修改。例如,使用函数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)
发布于 2016-06-20 02:20:44
像这样的东西可能适用于重滚:
(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
的列表。
https://stackoverflow.com/questions/37913002
复制相似问题