2016-06-19 2 views
0

Ich habe diese zwei grundlegende Funktionen:Mit Common Lisp Würfel neu Rolle ausgewählt, und nicht ausgewählte halten Benutzereingaben

(defun dice() 
    (+ 1 (random 6))) 

(defun five-dice() 
    (list (dice) (dice) (dice) (dice) (dice))) 

Alles, was sie tun, ist eine Liste von fünf geworfenen Würfel erstellen. Ich möchte eine bestimmte Anzahl von Würfeln auswählen, um sie erneut zu würfeln. Das heißt, ich möchte entweder 2, 3 oder alle 5 auswählen, um erneut zu würfeln und die Würfel, die erneut gewürfelt werden, zu ersetzen, während ich diejenigen behalte, die ich nicht würfle. Ich möchte dies mit Benutzereingaben tun.

Meine Annahme ist, dass der beste Weg, dies zu tun ist, ein Symbol zu verwenden, aber ich habe für einen Tag versucht und kann nicht herausfinden, wie genau dies zu tun ist. Deshalb habe ich beschlossen, Hilfe zu suchen.

Bearbeiten: Vielen Dank für Ihre Hilfe, ich schätze es wirklich. Ich habe Probleme, meinen Kopf darüber zu wickeln, wie Lisp Benutzereingaben akzeptiert und wie diese in Variablen gespeichert werden.

Also, ich erstelle eine globale Variable, und verwenden Sie diese als erste Rolle des Benutzers, aber sobald ich versuche, die Eingabe des Benutzers zu verwenden, um bestimmte Würfel neu zu rollen, das ist der Teil, den ich habe Schwierigkeiten zu verstehen. Ich habe ein paar Beispiele sieht, und ich habe versucht, es neu zu erstellen, aber es funktioniert nicht Training für mich:

(defun testfunction() (terpri) (princ "would you like to roll? ") (read-line) (if (member (read-line) '("y" "yes" "") :test #'string=) (let ((roll (five-dice))) )))

Das ist, was ich versuche zu arbeiten, um zu bekommen, so, nachdem der Benutzer Ja oder Ja eingegeben hat, gibt er ihnen 5 Würfel und gibt ihnen 3 Chancen, eine beliebige Anzahl von Würfeln erneut zu würfeln. Also, das ist, was ich gerade versuche zu arbeiten.

Edit2:

(defun roll-again(lst) (if (null lst)nil (setf (nth (car lst) list-dices)(dice)) (yup (cdr lst)) ))

Warum nicht funktioniert diese Funktion? Was ich jetzt versuche, ist, diese Funktion zu verwenden, um die Würfel, die der Benutzer wählt, erneut zu würfeln. Sobald ich vom Benutzer Eingaben erhalte, lege ich diese Eingabe in eine Liste und benutze diese Funktion, um diese Würfel erneut zu würfeln. Aber ich kann diese Funktion aus irgendeinem Grund nicht ausführen.

+0

* Am besten verwenden Sie ein Symbol *. Was meinen Sie? Können Sie eine Beispielinteraktion mit dem Benutzer zeigen, die die verschiedenen Anwendungsfälle zeigt? – coredump

Antwort

0

Ich denke, dass für kleine Liste Ihre beste otion ist, Elemente zu der Liste zu öffnen und sie zu ändern. Verwenden Sie die Funktion n-ten zum Beispiel, wenn Sie das zweite Element ändern mögen Sie so tun können:

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) 
+0

Also, wie würde ich das mit Benutzereingaben und mehreren Würfeln verwenden? So würde ich dies tun: (Format t ....................) ((setf (n-te Lese-line-Liste-Würfel) (Würfel)) Ersetzen Sie einfach die ganze Zahl mit read-line, weil das ist, was ich versucht habe zu tun und es hat nicht funktioniert edit: Wie würde das funktionieren, wenn der Benutzer 2 Würfel oder mehr neu zu rollen. – FlipZip

2

Der einfachste Weg, dies zu tun, wäre MAPCAR zu verwenden, um durch die Liste zu gehen, den Benutzer zu fragen, ob sie möchte die Würfel erneut werfen.

(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))) 

bearbeiten

In Ihrem bearbeiten gesagt, Sie die Benutzer in der Lage sein sollten, eine beliebige Anzahl von Würfeln neu zu rollen bis zu dreimal. Hier ist eine Version, die sie können das tun:

(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~^, ~}[email protected] 
         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))) 
+0

Eventuell musst du 'finish-output' aufrufen (ich habe kürzlich den gleichen Kommentar erhalten, jetzt bin ich dran). – coredump

+1

@coredump Ich habe es hinzugefügt, um sicher zu sein, aber es könnte redundant sein, da ich mir ziemlich sicher bin' Y-OR- NP "muss es auf jeden Fall anrufen. – jkiiski

+1

Sie haben wahrscheinlich Recht: Blick auf SBCLs [Quellcode] (https://github.com/sbcl/sbcl /blob/master/src/code/query.lisp#L35), erzwingt er tatsächlich die Ausgabe, nachdem er die Frage gestellt hat, so dass er wie erwartet funktioniert. Ich habe mich auch darüber gewundert, aber ich konnte keinen definitiven Hinweis finden, ob wir es erwarten können oder nicht. – coredump

0

Etwas Ähnliches könnte für die Wiederwalzen arbeiten:

(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)) 

Diese destruktive gemacht werden kann, indem die let/copy-list Skipping, aber nicht-destruktiv ist im Allgemeinen besser. Dies macht auch keine Fehlerprüfung.Es geht auch nicht darum, vom Benutzer Eingaben zu erhalten, weil das auf eine wirklich benutzerfreundliche Art und Weise zu tun ist, habe ich keine Zeit zu schreiben.

(defun get-dice-to-reroll() 
    (format t "Provide a list of dice to reroll, between parentheses: ") 
    (finish-output) 
    (read)) 

Auch dies hat nur minimale Fehlerprüfung, sondern gibt eine Liste, das zu füttern in als reroll-list-reroll-specific-dice geeignet ist:

Für eine „minimal“ Benutzereingabe, könnten Sie so etwas wie zu tun.