将随机值一次分配给一个变量,并在LISP中使用该信息

将随机值一次分配给一个变量,并在LISP中使用该信息,lisp,common-lisp,lispworks,Lisp,Common Lisp,Lispworks,现在我正在开发一个程序,该程序应该能够从7人名单中选出3人(a b c d e f g)并将他们指定为罪犯。这个“游戏”然后从7人中随机选出3人,告诉你其中有多少人是罪犯,并询问你是否想猜出这三名罪犯是谁,猜一猜(“这三个人中有两个是罪犯(你想猜猜罪犯是谁吗)。然而,我目前有一个程序,从名单中随机抽取3名罪犯,然而我所面临的斗争最初是确定谁是罪犯或不是罪犯(从名单中随机抽取3名,并将其分配给以后可以调用的值)这是我到目前为止的代码,我希望有人能给我指出正确的方向,我对函数式编程还是个新手 ;al

现在我正在开发一个程序,该程序应该能够从7人名单中选出3人(a b c d e f g)并将他们指定为罪犯。这个“游戏”然后从7人中随机选出3人,告诉你其中有多少人是罪犯,并询问你是否想猜出这三名罪犯是谁,猜一猜(“这三个人中有两个是罪犯(你想猜猜罪犯是谁吗)。然而,我目前有一个程序,从名单中随机抽取3名罪犯,然而我所面临的斗争最初是确定谁是罪犯或不是罪犯(从名单中随机抽取3名,并将其分配给以后可以调用的值)这是我到目前为止的代码,我希望有人能给我指出正确的方向,我对函数式编程还是个新手

;allows us to use prompt to ask the user for input
(defun prompt-read (prompt)
  (format *query-io* "~a: " prompt)
  (force-output *query-io*)
  (read-line *query-io*))

;allows you to add elements in needed spots
(defun element-at (org-list pos &optional (ini 1))
  (if (eql ini pos)
      (car org-list)
      (element-at (cdr org-list) pos (+ ini 1))))

(defun element-at (lista n)
  (if (= n 1)
      (first lista)
      (element-at (rest lista) (1- n))))

;allows for the removal of unneeded elements 
(defun remove-at (org-list pos &optional (ini 1))
  (if (eql pos ini)
      (cdr org-list)
      (cons (car org-list) (remove-at (cdr org-list) pos (+ ini 1)))))

;returns a chosen  number of random elements from a list
(defun rnd-select (org-list num &optional (selected 0))
  (if (eql num selected)
      nil
      (let ((rand-pos (+ (random (length org-list)) 1)))
        (cons (element-at org-list rand-pos) (rnd-select (remove-at org-list rand-pos) num (+ selected 1))))))

;returns 3 random criminals from a list of 7
(defun rnd-criminals ()
  (rnd-select '(a b c d e f g) 3))

(defun game ()
  (prompt-for-players))

;allows for the storing of number of players
(defun num-of-players(number)
  (list :number number))

;prompts for the amount of players you want to play
(defun prompt-for-players ()
  (num-of-players
   (or (parse-integer (prompt-read "How many players are there?"
                                   :junk-allowed t) 0))))

这是一个没有替换问题的抽样(因为,我假设,你不会希望每次从列表中挑选同一个人来“挑选三个罪犯”)。有很多方法可以做到这一点。一种方法是生成索引,直到你有足够多的不同索引。类似这样的方法如何:

(defun pick (sequence n)
  "Return n elements chosen at random from the sequence."
  (do ((len (length sequence))  ; the length of the sequence
       (indices '())            ; the indices that have been used
       (elements '()))          ; the elements that have been selected
      ((zerop n)          ; when there are no more elements to select,
       elements)          ; return the elements that were selectd.
    (let ((i (random len)))       ; choose an index at random
      (unless (member i indices)  ; unless it's been used already
        (push i indices)          ; add it to the list of used indices
        (push (elt sequence i) elements) ; and grab the element at the index
        (decf n)))))                     ; and decrement n.
如果您不太熟悉
do
,可以使用递归方法,例如,使用局部递归函数:

(defun pick2 (sequence n &aux (len (length sequence)))
  (labels ((pick2 (indices elements n)
             (if (zerop n) ; if no more elements are needed, 
                 elements ; then return elements.
                 (let ((i (random len))) ; Otherwise, pick an index i.
                   ;; If it's been used before,
                   (if (member i indices) 
                       ;; then continue on with the same indices,
                       ;; elements, and n.
                       (pick2 indices elements n)
                       ;; else, continue with it in the list of
                       ;; indices, add the new element to the list of
                       ;; elements, and select one fewer elements
                       ;; (i.e., decrease n).
                       (pick2 (list* i indices)
                              (list* (elt sequence i) elements)
                              (1- n)))))))
    ;; Start the process off with no indices, no elements, and n.
    (pick2 '() '() n)))
另一种方法是一种基于它的方法