2014-10-01 71 views
1

我寫在方案中的小劊子手遊戲和我得到一個非常奇怪的問題,幾乎看起來像一個特定語言之一。遞推方案函數值誤差

在我的遊戲我有持有允許的失誤和我的遊戲循環的每次遞歸調用數的變量,我「讓」的值到一個新的,如果需要改變它。這裏有一些代碼來幫助可視化我如何運行遊戲循環。

guessed_list - (前的含舊的猜測,一個新的猜測串字符列表 '( 「A」, 「X」, 「B」),其中 「a」 是新的猜測)

game_word - '( 「a」「b」「c」)

display_word - 包含字母的字符串列表我已經匹配了連字符,並且還沒有達到我的遊戲循環的迭代(ex'(「」「 b「」「),其中來自guessed_list的」a「將被評估爲該循環迭代)

errors_left - 我有的錯誤數我的遊戲應該因錯誤的猜測而結束。最初這從6開始,但在我當前的例子中應該是5,因爲1個字母「x」被錯誤地猜出了。

 ;; Game Loop. 
    (define (game-loop guessed_list display_word mistakes_left) 
    (let ((n_mistakes_left 
      (- mistakes_left (if (contains? game_word (car guessed_list)) 
           0 1)))) 
     (if (= n_mistakes_left 0) 
      (display n_mistakes_left);; End game output 
      (let ((display_word (fill-in-guess (list (car guessed_list)) 
              game_word display_word)) 
       (guessed_list (sort guessed_list string<?))) 

      (display "You have guessed: ") 
      (display-list guessed_list ", ") 
      (display "\n\n") 
      (draw-hangman n_mistakes_left) 
      (display "\n\nWord: ") 
      (display-list display_word " ") 

      (cond ((contains? display_word "_") 
        (display "\n\nEnter a letter to guess: ") 
        (game-loop (append (list (symbol->string (read))) guessed_list) 
           display_word n_mistakes_left)) 
        (else (display "\n\nYou Won!"))))))) 

我可以張貼我的輔助方法包括如果有必要?填空題猜測,顯示列表,畫,劊子手,但他們的工作,因爲他們應該和不改變我的mistakes_left變量的值他們的功能。

我遇到的問題是我的errors_left變量從6開始,在遊戲循環的第一次調用中通過罰款,但在隨後的調用中,即使猜測正確的值時也會變小。我已將每件作品單獨進行了測試,並且在出現錯誤之前,errors_left會顯示正確的值。

我懷疑它與遞歸和「讓」荷蘭國際集團我的變量做的,但我想一個difinitive答案,如果任何人都可以或指出最可能簡單的錯誤,我失蹤了!

編輯:

下面是代碼測試的其餘部分,我仍然得到這個問題。我認爲追加工作,因爲它將第二個列表追加到第一個列表,所以在這個意義上,cons和append給了我相同的輸入。

(define zero_wrong " 
    |--------- 

    |  | 

    |  

    |   

    |   

    |   

    |   

    |   

    |   

    |_______________") 
    (define one_wrong " 
    |--------- 

    |  | 
      ___ 
    |  |. .| 
      --- 
    |   

    |   

    |   

    |   

    |   

    |   

    |_______________") 
    (define two_wrong " 
    |--------- 

    |  | 
      ___ 
    |  |. .| 
      --- 
    |  | 
      | 
    |  | 
      | 
    |   

    |   

    |   

    |   

    |_______________") 
    (define three_wrong " 
    |--------- 

    |  | 
      ___ 
    |  |. .| 
      --- 
    |  | 
      |---- 
    |  | 
      | 
    |   

    |   

    |   

    |   

    |_______________") 
    (define four_wrong " 
    |--------- 

    |  | 
      ___ 
    |  |. .| 
      --- 
    |  | 
     ----|---- 
    |  | 
      | 
    |   

    |   

    |   

    |   

    |_______________") 
    (define five_wrong "|--------- 

    |  | 
      ___ 
    |  |. .| 
      --- 
    |  | 
     ----|---- 
    |  | 
      | 
    |   \\ 
      \\ 
    |   

    |   

    |   

    |_______________") 
    (define six_wrong "|--------- 

    |  | 
      ___ 
    |  |x x| 
      --- 
    |  | 
     ----|---- 
    |  | 
      | 
    |  /\\ 
     / \\ 
    |   

    |   

    |   

    |_______________") 

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Read list value at x. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    (define (get-str-at x str_lst) 
    (cond ((equal? x 0) 
     (car str_lst)) 
    (else 
     (get-str-at (- x 1) (cdr str_lst)) 
    ) 
    ) 
) 

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Car operation for strings. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    (define (string-car str) 
    (substring str 0 1) 
) 

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Cdr operation for strings. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    (define (string-cdr str) 
    (substring str 1 (string-length str)) 
) 

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Converts a string into a 
    ;; list of character strings. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

    (define (string-to-char-string-list str) 
    (cond 
     ((equal? (string-cdr str) "") 
      (list str) 
     ) 
     (
      (append (list (string-car str)) (string-to-char-string-list (string-cdr str))) 
     ) 
    ) 
) 

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Tests if a list contains a spefified object. 
    ;; 
    ;; Method code from: 
    ;; http://stackoverflow.com/questions/1869116/scheme-built-in-to-check-list-containment 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    (define (contains? list item) 
    (if (empty? list) 
      #f 
     (or (eq? (first list) item) 
      (contains? (rest list) item) 
     ) 
    ) 
) 

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Displays a list with the 
    ;; given separater. 
    ;; 
    ;; Base code from: 
    ;; ftp://ftp.cs.utexas.edu/pub/garbage/cs345/schintro-v13/schintro_99.html 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

    (define (display-list a_list separater) 
    (if (null? a_list) 
     (display "") 
     (begin 
      (display (car a_list)) 
      (if (null? (cdr a_list)) 
       (display "") 
       (display separater)) 
      (display-list (cdr a_list) separater) 
     ) 
    ) 
) 


    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Gets the Xth word in the 
    ;; provided file. 
    ;; 
    ;; Does not check for eof 
    ;; condition, so x must be 
    ;; within range of the file. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    (define (get-word x file) 
    (cond 
     ((= 1 x) 
      (read file)) 
     (else 
      (read file) 
      (get-word (- x 1) file) 
     ) 
    ) 
) 


    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Returns a list of blanks 
    ;; equal to the number of 
    ;; letters in provided word. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

    (define (init-display-word game_word) 
    (cond 
     ((null? game_word) 
      (list)) 
     (else 
      (append (init-display-word (cdr game_word)) '("_")) 
     ) 
    ) 
) 


    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Fills in the blank spaces 
    ;; in the display word with 
    ;; the letter that matches 
    ;; those positions in the 
    ;; game word. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

    (define (fill-in-guess letter game_word display_word) 
    (cond 
     ((null? game_word) 
      (list) 
     ) 
    (else 
    (cond 
     ((equal? letter (list (car game_word))) 
      (append letter (fill-in-guess letter (cdr game_word) (cdr display_word))) 
     ) 
     (else 
      (append (list (car display_word)) (fill-in-guess letter (cdr game_word) (cdr display_word))) 
     ) 
    ) 
    ) 
    ) 
) 

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Draws the hanging man. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

    (define (draw-hangman guesses_left) 
     (cond ((equal? guesses_left 6) 
       (display zero_wrong)) 
     (else (cond ((equal? guesses_left 5) 
       (display one_wrong)) 
     (else (cond ((equal? guesses_left 4) 
       (display two_wrong)) 
     (else (cond ((equal? guesses_left 3) 
       (display three_wrong)) 
     (else (cond ((equal? guesses_left 2) 
       (display four_wrong)) 
     (else (cond ((equal? guesses_left 1) 
       (display five_wrong)) 
     (else (display six_wrong)) 
    ))))))))))) 
) 
+0

「包含?」謂詞除了檢查值之外的其他值是否在列表中?如果沒有,請使用內置的Racket功能'member'而不是 – Jack 2014-10-01 07:35:26

+0

否,它不會執行任何其他工作。我對Scheme相當陌生,所以我不熟悉很多內置的構造,但是非常感謝。我會在我的代碼中改變它。 – MrJman006 2014-10-01 11:12:19

+0

如果答案解決了您的問題。請接受它。 – Rptx 2014-10-01 23:00:11

回答

1

我對你的代碼做了一些修改。我已經在函數上面標註了我的更改,並對它們進行了解釋。你問題是你排序guessed_list。沒有必要這樣做。我已經測試過它,它工作。請記住,如果你調用game-loop與猜測的一個空列表就會報錯。爲了解決這個問題,你需要測試,如果guessed_list爲空,也爲減法返回0。我會把它留給你。 此外,在代碼中的許多地方,你有嵌套cond s表示是沒有必要的。在這裏閱讀:cond

(define game_word '("a" "b" "c")) 

(define zero_wrong " 
    |--------- 

    |  | 

    |  

    |   

    |   

    |   

    |   

    |   

    |   

    |_______________") 
    (define one_wrong " 
    |--------- 

    |  | 
      ___ 
    |  |. .| 
      --- 
    |   

    |   

    |   

    |   

    |   

    |   

    |_______________") 
    (define two_wrong " 
    |--------- 

    |  | 
      ___ 
    |  |. .| 
      --- 
    |  | 
      | 
    |  | 
      | 
    |   

    |   

    |   

    |   

    |_______________") 
    (define three_wrong " 
    |--------- 

    |  | 
      ___ 
    |  |. .| 
      --- 
    |  | 
      |---- 
    |  | 
      | 
    |   

    |   

    |   

    |   

    |_______________") 
    (define four_wrong " 
    |--------- 

    |  | 
      ___ 
    |  |. .| 
      --- 
    |  | 
     ----|---- 
    |  | 
      | 
    |   

    |   

    |   

    |   

    |_______________") 
    (define five_wrong "|--------- 

    |  | 
      ___ 
    |  |. .| 
      --- 
    |  | 
     ----|---- 
    |  | 
      | 
    |   \\ 
      \\ 
    |   

    |   

    |   

    |_______________") 
    (define six_wrong "|--------- 

    |  | 
      ___ 
    |  |x x| 
      --- 
    |  | 
     ----|---- 
    |  | 
      | 
    |  /\\ 
     / \\ 
    |   

    |   

    |   

    |_______________") 

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Read list value at x. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
(define (get-str-at x str_lst) 
    (cond ((equal? x 0) 
     (car str_lst)) 
     (else 
     (get-str-at (- x 1) (cdr str_lst))))) 

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Car operation for strings. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
(define (string-car str) 
    (substring str 0 1)) 

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Cdr operation for strings. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; *** This is enough. 
(define (string-cdr str) 
    (substring str 1)) 

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Converts a string into a 
    ;; list of character strings. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

(define (string-to-char-string-list str) 
    (cond 
    ((equal? (string-cdr str) "") 
    (list str)) 
    ((append (list (string-car str)) (string-to-char-string-list (string-cdr str)))))) 

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Tests if a list contains a spefified object. 
    ;; 
    ;; Method code from: 
    ;; http://stackoverflow.com/questions/1869116/scheme-built-in-to-check-list-containment 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
(define (contains? list item) 
    (if (empty? list) 
     #f 
     (or (string=? (first list) item) 
      (contains? (rest list) item)))) 

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Displays a list with the 
    ;; given separater. 
    ;; 
    ;; Base code from: 
    ;; ftp://ftp.cs.utexas.edu/pub/garbage/cs345/schintro-v13/schintro_99.html 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

(define (display-list a_list separater) 
    (if (null? a_list) 
     (display "") 
     (begin 
     (display (car a_list)) 
     (if (null? (cdr a_list)) 
      (display "") 
      (display separater)) 
     (display-list (cdr a_list) separater)))) 


    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Gets the Xth word in the 
    ;; provided file. 
    ;; 
    ;; Does not check for eof 
    ;; condition, so x must be 
    ;; within range of the file. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
(define (get-word x file) 
    (cond 
    ((= 1 x) 
    (read file)) 
    (else 
    (read file) 
    (get-word (- x 1) file)))) 


    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Returns a list of blanks 
    ;; equal to the number of 
    ;; letters in provided word. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

(define (init-display-word game_word) 
    (cond 
    ((null? game_word) 
    (list)) 
    (else 
    (append (init-display-word (cdr game_word)) '("_"))))) 


    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Fills in the blank spaces 
    ;; in the display word with 
    ;; the letter that matches 
    ;; those positions in the 
    ;; game word. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

; No need for append here. Just use cons when adding to the start of the list. 
; No need to nest conds 
(define (fill-in-guess letter game_word display_word) 
    (cond 
    ((null? game_word) 
    '()) 
    ((equal? letter (car game_word)) 
    (cons letter (fill-in-guess letter (cdr game_word) (cdr display_word)))) 
    (else 
    (cons (car display_word) 
      (fill-in-guess letter (cdr game_word) (cdr display_word)))))) 

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
    ;; Draws the hanging man. 
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

; You used cond as an if/else statement. You can have multiple clauses in a cond. 
; You only need one final else cluase. 
(define (draw-hangman guesses_left) 
    (cond ((equal? guesses_left 6) 
     (display zero_wrong)) 
     ((equal? guesses_left 5) 
     (display one_wrong)) 
     ((equal? guesses_left 4) 
     (display two_wrong)) 
     ((equal? guesses_left 3) 
     (display three_wrong)) 
     ((equal? guesses_left 2) 
     (display four_wrong)) 
     ((equal? guesses_left 1) 
     (display five_wrong)) 
     (else (display six_wrong)))) 

; Don't sort the guessed-list. 
; You had display when guess left was 0. Not draw_hagman 
(define (game-loop guessed_list display_word mistakes_left) 
    (let ((n_mistakes_left 
     (- mistakes_left (if (contains? game_word (car guessed_list)) 
           0 1)))) 
    (if (= n_mistakes_left 0) 
     (draw-hangman n_mistakes_left);; End game output 
     (let ((display_word (fill-in-guess (car guessed_list) 
              game_word display_word))) 

      (display "You have guessed: ") 
      (display-list guessed_list ", ") 
      (display "\n\n") 
      (draw-hangman n_mistakes_left) 
      (display "\n\nWord: ") 
      (display-list display_word " ") 

      (cond ((contains? display_word "_") 
       (display "\n\nEnter a letter to guess: ") 
       (game-loop (cons (symbol->string (read)) guessed_list) 
          display_word n_mistakes_left)) 
       (else (display "\n\nYou Won!")))))))