我正在写一个小的绞刑架游戏,在计划和得到一个非常奇怪的问题,几乎似乎是一个语言特定的问题。
在我的游戏中,我有一个变量,它保存允许的错误数量,并且在我的游戏循环的每个递归调用中,如果需要更改,我会将值“让”为一个新值。这里有一些代码来帮助可视化我是如何运行游戏循环的。
guessed_list -包含旧猜测和一个新猜测的字符串字符列表(例如。‘'("a“x”b")其中"a“是新的猜测)
game_word -‘(a "b“"c")
display_word --包含我匹配的字母和连字符的字符串列表,用于那些我还没有到游戏循环(“ex‘( "b”") )迭代的字符串,其中guessed_list中的"a“将在这个循环迭代中进行计算。
mistakes_left --由于猜错了,我在比赛前犯的错误数量应该会结束。最初从6开始,但在我当前的示例中应该是5,因为一个字母"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变量的值。
我遇到的问题是,我的mistakes_left变量从6开始,在游戏循环的第一次调用时会很好地通过,但是在随后的调用中,即使在猜测正确的值时,也会变得更小。我已经取得了每一件单独的,测试它和mistakes_left出了正确的价值,直到我恢复。
我怀疑这是与递归和“让”我的变量,但我想要一个明确的答案,如果有人可以或指出最可能的简单错误,我错过了!
编辑:
下面是要测试的其余代码,我仍然知道问题所在。我认为追加之所以有效,是因为它将第二个列表附加到第一个列表中,因此在这个意义上,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))
)))))))))))
)发布于 2014-10-04 16:24:16
我概括了这个问题,不把重点放在绞刑方面。问题得到了立即的回答,评论进一步解释了错误的原因。您可以在这篇文章中找到所有这些信息:方案递归循环值不正确和变量绑定。
发布于 2014-10-01 15:20:29
我对你的代码做了几处修改。我在函数上方用注释标记了我的更改,并对它们进行了解释。你的问题是你把guessed_list分类了。没有必要这样做。我已经测试过了,而且效果很好。请记住,如果您使用一个空的猜测列表调用game-loop,它将出错。要解决这个问题,您需要测试guessed_list是否为null,并返回0作为减法。我会把这个留给你。此外,在代码中的许多地方,都有不必要的嵌套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!")))))))https://stackoverflow.com/questions/26134917
复制相似问题