2015-11-07 20 views
0

所以我有一個循環來重複我對dota所做的小文本遊戲,但是當函數'play'在循環中被調用時,它不會返回我的cond函數的結果,它只需要一個輸入,然後移動到下一個循環。循環內的函數行爲有所不同

;;;;learn the invoker combo's 
(defparameter *invoker-combo* '((cold-snap (3 0 0) 'QQQ);all of the possible invoker combo's 
           (ghost-walk (2 1 0) 'QQW) 
           (Ice-Wall (2 0 1) 'QQE) 
           (EMP (0 3 0) 'WWW) 
           (Tornado (1 2 0) 'QWW) 
           (Alacrity (0 2 1) 'WWE) 
           (Sun-Strike (0 0 3) 'EEE) 
           (Forge-Spirit (1 0 2) 'QEE) 
           (Chaos-Meteor (0 1 2) 'WEE) 
           (Deafening-Blast (1 1 1) 'QWE))) 
(defun rand-combo (invoker-combo);returns a random combo 
    (nth (random (length invoker-combo))invoker-combo)) 

(defun count-letters (input);converts the keyboard strokes into numbers to be compared as it doesn't matter what order they are in, just that there is the correct quantity of them e.g QQE could also be written QEQ. 
    (append 
     (list (count #\Q input) 
       (count #\W input) 
       (count #\E input)))) 

(defun try-for-combo (rand-combo);takes i-p and compares it with the value for the random combo 
    (print(car rand-combo)) 
    (let* ((i-p (string-upcase(read-line))) 
      (try (count-letters i-p))) 
      (cond ((equal try (cadr rand-combo))'Good-job) 
        ((equal i-p "END")(list 'Thanks 'for 'playing)) 
        (t (list i-p 'was 'wrong 'correct 'is (caddr(assoc (car rand-combo)*invoker-combo*))))))) 

(defun play() 
    (try-for-combo (rand-combo *invoker-combo*))) 

(defun loop-play (x) 
    (loop for i from 0 to x 
     :do (play))) 

如果我調用該函數 '玩',我得到以下O/P:

FORGE-SPIRIT asdf 
("ASDF" WAS WRONG CORRECT IS 'QEE) 

ALACRITY wwe 
GOOD-JOB 

但如果我調用該函數 '循環播放' 我得到以下o/p:

Break 3 [7]> (loop-play 2)  
SUN-STRIKE eee  
ALACRITY wwe 
TORNADO qww 
NIL 

有人可以解釋對我來說爲什麼會發生這種情況? 編輯:隨時更改標題,我真的不知道要放什麼。

+0

您可能想縮進並更好地設置您的代碼的格式。 –

+0

如果您看到類似'BREAK 3 [7]>'的提示,那麼您的Lisp交互是在調試器中。從調試器中取出它。使用命令'help'獲得可用命令的幫助。 'quit'讓Lisp回到頂層。 –

+0

好的,謝謝。你有沒有關於如何正確格式化我的代碼的鏈接,因爲這是我在閱讀的書中完成的,我也發佈了關於它的問題,每個人都對它非常敵對,所以我不打擾。 – Floofk

回答

1

您的try-for-combo函數實際上並不是輸出什麼。相反,它返回值。

在REPL中,如果您評估表單,如(+ 1 2),它將始終在最後打印該表單的評估(在此例中爲3)。但是,請考慮(+ 1 (print 2))print函數實際上將參數輸出到標準輸出,然後返回值本身。因此,這將顯示(在REPL)

2 
3 

2首先輸出,因爲(print 2)本身打印2。然後,表格(+ 1 (print 2))的計算結果與(+ 1 2)3的計算結果相同。

在你的情況,你的try-for-combo函數應該是這樣的:

(defun try-for-combo (rand-combo) 
    (print (car rand-combo)) 
    (let* ((i-p (string-upcase(read-line))) 
     (try (count-letters i-p))) 
    (print 
    (cond 
     ((equal try (cadr rand-combo)) 'Good-job) 
     ((equal i-p "END") (list 'Thanks 'for 'playing)) 
     (t (list i-p 'was 'wrong 'correct 'is (caddr(assoc (car rand-combo) *invoker-combo*)))))) 
    nil)) 

這將打印cond形式的結果,並返回「零」。

+0

總之使用打印:D – Floofk

1

這僅僅是差異的程序將輸出和輸出Lisp的系統確實對每個評價之間:

print打印的東西(一個換行符,然後它的參數)並返回一個值。該值由REPL打印。因此,我們看到輸出兩次:

[3]> (print "3") 

"3" 
"3" 

接下來我們要做的progn好幾撥至print。 REPL打印progn表單的值。前三個串由代碼印刷和最後一個字符串是因爲Lisp的REPL印刷值的印刷:

[4]> (progn (print "1") (print "2") (print "3")) 

"1" 
"2" 
"3" 
"3" 
2

壓痕和代碼的格式化差。請讓你更容易閱讀代碼。

(defun try-for-combo (rand-combo);takes i-p and compares it with the value for the random combo 
    (print(car rand-combo)) 
    (let* ((i-p (string-upcase(read-line))) 
      (try (count-letters i-p))) 
      (cond ((equal try (cadr rand-combo))'Good-job) ; wrong indent level 
        ((equal i-p "END")(list 'Thanks 'for 'playing)) 
        (t (list i-p 'was 'wrong 'correct 'is (caddr(assoc (car rand-combo)*invoker-combo*))))))) 
  • 缺乏
  • 錯誤了縮進層次
  • 結構代碼不清的s表達式之間的空間
  • 不使用內置的文檔功能
  • 一些線路太長

更好:

(defun try-for-combo (rand-combo) 
    "takes i-p and compares it with the value for the random combo" ; built in doc 
    (print (car rand-combo)) 
    (let* ((i-p (string-upcase (read-line))) 
     (try (count-letters i-p))) 
    (cond ((equal try (cadr rand-combo))       ; indentation 
      'Good-job) 
      ((equal i-p "END") 
      (list 'Thanks 'for 'playing)) 
      (t 
      (list i-p 'was 'wrong 'correct 'is      ; several lines 
       (caddr (assoc (car rand-combo) 
           *invoker-combo*))))))) 

我會建議使用這其實瞭解一些Lisp語言格式的編輯器。像GNU Emacs的/泥,Clozure CL的鐵杉,LispWorks'編輯器...

如果你不確定格式,你也可以要求Lisp的做到這一點。 CLISP並不好,在格式化,而是要像SBCL或CCL會做:

* (let ((*print-case* :downcase)) 
    (pprint '(defun try-for-combo (rand-combo) 
(print (car rand-combo)) 
        (let* ((i-p (string-upcase (read-line))) 
(try (count-letters i-p))) 
          (cond ((equal try (cadr rand-combo)) 
'Good-job) ((equal i-p "END") 
           (list 'Thanks 'for 'playing)) 
(t (list i-p 'was 'wrong 'correct 'is 
             (caddr (assoc (car rand-combo) 
*invoker-combo*))))))))) 

,你會得到很好的格式化代碼:

(defun try-for-combo (rand-combo) 
    (print (car rand-combo)) 
    (let* ((i-p (string-upcase (read-line))) (try (count-letters i-p))) 
    (cond ((equal try (cadr rand-combo)) 'good-job) 
      ((equal i-p "END") (list 'thanks 'for 'playing)) 
      (t 
      (list i-p 'was 'wrong 'correct 'is 
       (caddr (assoc (car rand-combo) *invoker-combo*))))))) 

由編輯器的Lisp代碼自動縮進您節省了大量工作的。

有用於manual indentation提示。

+0

感謝您的幫助:)我很感激。有沒有什麼小方法可以記住正確的縮進和格式?像一個短語或其他東西。我不使用Emacs,因爲當我第一次開始使用Emacs和一些基本的lisp時非常困惑,所以當我更改書籍時,我只是使用Notepad ++,因爲我現在可以專注於學習LISP而不是LISP和Emacs。 – Floofk

+0

@Floofk:使用Notepad ++意味着您需要專注於手動縮進代碼和其他內容。 Emacs爲你做到了這一點,這大大簡化了Lisp編程。學習Emacs(或任何其他Lisp感知編輯器),並立即支付。 –

+0

你把它賣給了我哈哈,我會得到emacs和slime :) – Floofk