使用Racket制作BlackJack扑克牌组遇到的两类技术问题
解决Racket中制作BlackJack扑克牌组的问题
问题1:代码输出异常的原因
你的代码输出出现#<void>是因为pair-items函数的逻辑错误:
displayln函数的返回值是#<void>,你在cons里直接嵌套调用pair-items x (cdr y),会把递归调用的返回值(也就是displayln的#<void>)拼接到列表里,导致输出出现. #<void>。- 函数的递归分支没有正确返回构建好的牌组列表,反而依赖
displayln打印,同时终止条件的返回值也没有和递归部分衔接。
你的原代码:
;This function creates a list of all the card faces. (define faces '(2 3 4 5 6 7 8 9 10 J Q K A)) ;This function creates a list of all card suits. (define suits '(Clubs Diamonds Hearts Spades)) ;make-deck: Creates a new (unshuffled) 52 card deck ; Returns: The deck (a list of cards) ; Parameters: none (define make-deck (letrec ([pair-items (lambda (x y) (cond [(null? x) '()] [(null? y) '()] [(displayln (cons (car x) (cons (car y) (pair-items x (cdr y)))))] ))]) (pair-items faces suits)) )
问题2:实现所有牌面与花色的配对
要让每个牌面和所有花色配对,本质是求两个列表的笛卡尔积,不需要手动“重置迭代器”,用递归或者Racket的高阶循环函数都能轻松实现:
方法1:用for*/list(最简洁)
for*/list会自动嵌套遍历两个列表,生成所有组合:
(define faces '(2 3 4 5 6 7 8 9 10 J Q K A)) (define suits '(Clubs Diamonds Hearts Spades)) (define (make-deck) (for*/list ([face faces] [suit suits]) (list face suit)))
调用(make-deck)会返回完整的52张牌的列表,每张牌是(face suit)的形式。
方法2:递归实现
如果想用纯递归逻辑,可以写嵌套的递归函数:
(define faces '(2 3 4 5 6 7 8 9 10 J Q K A)) (define suits '(Clubs Diamonds Hearts Spades)) (define (make-deck) (letrec ([pair-face-with-all-suits (lambda (face suits) (if (null? suits) '() (cons (list face (car suits)) (pair-face-with-all-suits face (cdr suits))))) [pair-all-faces (lambda (faces suits) (if (null? faces) '() (append (pair-face-with-all-suits (car faces) suits) (pair-all-faces (cdr faces) suits))))]) (pair-all-faces faces suits)))
这个逻辑里,pair-face-with-all-suits负责把单个牌面和所有花色配对,pair-all-faces遍历所有牌面,把每个牌面的配对结果拼接起来,最终得到完整牌组。
修正你原代码的问题
如果要保留你原有的递归结构,需要让函数返回列表而不是依赖displayln,比如:
(define faces '(2 3 4 5 6 7 8 9 10 J Q K A)) (define suits '(Clubs Diamonds Hearts Spades)) (define make-deck (letrec ([pair-items (lambda (x y) (cond [(null? x) '()] [(null? y) (pair-items (cdr x) suits)] ; 花色遍历完,切换到下一个牌面 [else (cons (list (car x) (car y)) (pair-items x (cdr y)))]))]) (pair-items faces suits)))
这里修改了递归逻辑:当花色列表为空时,递归处理下一个牌面(重置为完整的suits列表),否则构建当前牌的列表并继续遍历剩余花色。
内容的提问来源于stack exchange,提问作者spaceman777
相关产品推荐
相关产品推荐

