(define (solver row col board boolboard) ;solve the game
(if (equal? row 9)
board
(if (equal? (get-value boolboard row col) #t)
(begin
(for ([ite '(1 2 3 4 5 6 7 8 9)]) ;true
(when (equal? (check-available row col ite board) #t) ;should be careful here
(begin
(let ([new-board (set-value board row col ite)])
(if (equal? col 8)
(solver (+ 1 row) 0 new-board boolboard)
(solver row (+ 1 col) new-board boolboard)))
)
)
))
(if (and (equal? col 8) (equal? row 8)) ;false
board
(if (equal? col 8)
(solver (+ 1 row) 0 board boolboard)
(solver row (+ 1 col) board boolboard)
)))
)
)
这是soduku解算器。我已经检查了解算器最终到达了(如果(等于?第9行)所以它得到了电路板。但是函数仍然返回#。我不知道为什么它没有返回电路板。
任何人都可以帮助我吗?
答案 0 :(得分:3)
修复这些类型的错误的一般规则:
如果它返回了您不期望的内容(此处为#<void>
),那么请查找函数中可能返回的内容。您确定基本案例返回您期望的内容,但您还必须检查其他案例。
下一个案例中有一个begin
,其中包含for
。无论在任何迭代中返回的正文表达式是什么,for
形式总是返回#<void>
。
因此,您可以回复#<void>
。 for
表单在每次迭代时计算循环体,但忽略返回值。
因此,for
几乎不是你想要的。通常情况下,for/list
,for/or
和for/fold
这样的表单会更有用。在这种情况下,for/first
看起来可能就是您的意思。
如果你盲目翻译,
(for/first ([ite '(1 2 3 4 5 6 7 8 9)])
(when (equal? (check-available row col ite board) #t)
(let ([new-board (set-value board row col ite)])
(if (equal? col 8)
(solver (+ 1 row) 0 new-board boolboard)
(solver row (+ 1 col) new-board boolboard)))))
然后这仍然无效,因为它仍会在很多时候返回#<void>
,因为when
形式在条件为假时返回#<void>
。 for/first
形式并不神奇。它没有看到when表单失败或使用该信息转到下一个子句。要使for/first
检查条件并继续执行下一条,如果它是假的,请在#:when
之后使用[ite ...]
子句。
(for/first ([ite '(1 2 3 4 5 6 7 8 9)]
#:when (equal? (check-available row col ite board) #t))
(let ([new-board (set-value board row col ite)])
(if (equal? col 8)
(solver (+ 1 row) 0 new-board boolboard)
(solver row (+ 1 col) new-board boolboard))))
for/first
表单将评估#:when
条件为真的第一次迭代的正文,然后返回。
但是,如果任何迭代的#:when
条件永远不为真,则for/first
表单将返回false,这将导致solver
函数返回false。
但这意味着for/first
表单中的递归调用可能返回false。如果发生这种情况,该怎么办?您可能想要进入循环的下一次迭代。为此,您可以使用for/or
,它类似于for/first
,但如果正文返回false,它将继续进行下一次迭代。
(for/or ([ite '(1 2 3 4 5 6 7 8 9)]
#:when (equal? (check-available row col ite board) #t))
(let ([new-board (set-value board row col ite)])
(if (equal? col 8)
(solver (+ 1 row) 0 new-board boolboard)
(solver row (+ 1 col) new-board boolboard))))
这样,如果填写一个数字并不会产生一个解决方案,并且返回false,则可以尝试下一个数字。
这解决了有关它返回#<void>
的问题。如果您的代码存在更多问题,则应该提出另一个问题。