【发布时间】:2014-10-01 05:52:47
【问题描述】:
我正在编写一个计划中的小刽子手游戏,遇到了一个非常奇怪的问题,几乎看起来像是一个特定于语言的问题。
在我的游戏中,我有一个变量来保存允许的错误数量,并且在我的游戏循环的每次递归调用中,如果需要更改它,我会“让”这个值到一个新的值。这里有一些代码可以帮助我可视化我是如何运行游戏循环的。
guessed_list - 包含旧猜测和一个新猜测的字符串字符列表(例如 '("a" "x" "b"),其中 "a" 是新猜测)
game_word - '("a" "b" "c")
display_word - 一个字符串字符列表,其中包含我匹配的字母和连字符,用于我的游戏循环的这次迭代(例如 '("" "b" "")来自guessed_list 的“a”将在此循环迭代中被评估)
mistakes_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!")))))))
如有必要,我可以发布我的辅助方法 contains?、fill-in-guess、display-list、draw-hangman,但它们都按应有的方式工作,并且不会更改我的 errors_left 变量的值以实现其功能。
我遇到的问题是我的 errors_left 变量从 6 开始,并在第一次调用游戏循环时很好地通过,但在随后的调用中,即使猜测正确的值也会变小。我已经单独提取了每一块,对其进行了测试,errors_left 得出了正确的值,直到我递归为止。
我怀疑它与递归和“让”我的变量有关,但如果有人可以或指出我遗漏的最可能的简单错误,我想要一个明确的答案!
编辑:
这是要测试的其余代码,我仍然遇到问题。我认为 append 有效,因为它将第二个列表附加到第一个列表,所以在这个意义上 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))
)))))))))))
)
【问题讨论】:
-
除了检查值是否在列表中之外,
contains?谓词是否还有其他作用?如果没有,请改用内置的 Racket 函数member -
不,它不做任何其他工作。我对Scheme还很陌生,所以我还不熟悉许多内置结构,但谢谢你。我将在我的代码中更改它。
-
如果答案解决了您的问题。请接受。
-
您的解决方案虽然更简单,但不起作用。猜出有效字母时,图像仍然显示不正确。
标签: recursion scheme logic racket