我很困惑为什么以下的Racket代码没有产生正确的结果。它适用于n = 4或5时,但对于高于此值的任何结果,该函数返回false。但是,我知道其中一些有解决方案。任何帮助,将不胜感激。问题可以在here找到。
(define QUEEN (text "♛" 25 "black"))
(define SQR (square 30 "outline" "black"))
(define QNPEC (place-image QUEEN 15 15 SQR))
; QP is (make-posn CI CI)
; CI is a natural number in [0,8)
; interpretation a CI denotes a row or column index for a chess board,
; (make-posn r c) specifies the square in the r-th row and the c-th column
; QP QP -> Boolean
; determines whether or not a QP is threatened
; by another
(define (threatening? er nee)
(cond
[(= (posn-x er) (posn-x nee)) true]
[(= (posn-y er) (posn-y nee)) true]
[(diagonal? er nee) true]
[else false]))
(check-expect (threatening? (make-posn 1 0) (make-posn 4 3)) true)
(check-expect (threatening? (make-posn 1 0) (make-posn 1 3)) true)
(check-expect (threatening? (make-posn 3 54) (make-posn 9 54)) true)
(check-expect (threatening? (make-posn 3 55) (make-posn 9 54)) false)
; QP QP -> Boolean
; determines whether or not a QP is diagonal
; to another
(define (diagonal? er nee)
(cond
[(and (or (= (posn-x nee) (- (posn-x er)
(- (posn-y er) (posn-y nee))))
(= (posn-x nee) (+ (posn-x er)
(- (posn-y er) (posn-y nee)))))
(= (posn-y nee) (- (posn-y er)
(- (posn-y er) (posn-y nee))))) true]
[else false]))
(check-expect (diagonal? (make-posn 0 0) (make-posn 2 2)) true)
(check-expect (diagonal? (make-posn 1 0) (make-posn 4 3)) true)
(check-expect (diagonal? (make-posn 4 3) (make-posn 1 0)) true)
(check-expect (diagonal? (make-posn 12 0) (make-posn 4 3)) false)
(define (make-hgrid n i)
(cond
[(zero? n) empty-image]
[else (beside i (make-hgrid (sub1 n) i))]))
(define (make-vgrid n i)
(cond
[(zero? n) empty-image]
[else (above i (make-vgrid (sub1 n) i))]))
(define (make-sgrid n i)
(make-vgrid n (make-hgrid n i)))
; N [List-of QP] Image -> Image
; returns image of n-by-n chess board
(define (render-queens n l i)
(cond
[(empty? l) (make-sgrid n SQR)]
[else (local ((define F (first l))
(define IW (* (image-width SQR)))
(define PR (/ IW 2)))
(place-image i (+ (* (posn-x F) IW) PR)
(+ (* (posn-y F) IW) PR)
(render-queens n (rest l) i)))]))
; Set Set -> Boolean
; determines equivalence of sets
(define (set=? s1 s2)
(if (= (length s1) (length s2))
(andmap (lambda (x) (member? x s2)) s1)
false))
(check-expect (set=? '(a b c) '(c b a)) true)
(check-expect (set=? '(1 2 4) '(4 2 1)) true)
(check-expect (set=? '(1 2 3 4) '(a b c 1)) false)
; N -> [Maybe [List-of QP]]
; find a solution to the n queens problem
; data example:
(define 4QUEEN-SOLUTION-2
(list (make-posn 0 2) (make-posn 1 0) (make-posn 2 3) (make-posn 3 1)))
(define (n-queens n)
(local ((define MAIN (find-boards n)))
(cond
[(or (= n 2) (= n 3)) false]
[(= (length MAIN) n) MAIN]
[else false])))
; checks
(check-expect (n-queens-solution? 4 (n-queens 4)) true)
(check-expect (n-queens 2) false)
; N [List-of QP] -> Boolean
; determines whether or not a list of QP is an
; n-queens solution
(define (n-queens-solution? n l)
(cond
[(= (length l) n)
(local ((define (ds n l)
(cond
[(empty? l) true]
[else (or (ormap (lambda (x) (threatening? (first l) x)) l)
(ds n (rest l)))])))
(ds n l))]
[else false]))
(check-expect (n-queens-solution? 4 4QUEEN-SOLUTION-2) true)
(check-expect (n-queens-solution? 3 4QUEEN-SOLUTION-2) false)
; a Board is a [List-of Posn]
; N -> Board
; creates board
(define (make-board n)
(take-all-elems (build-list n (lambda (b) (build-list n (lambda (m) (make-posn m b)))))))
; checks
(check-expect (set=? (make-board 3)
(list (make-posn 0 0) (make-posn 1 0) (make-posn 2 0)
(make-posn 0 1) (make-posn 1 1) (make-posn 2 1)
(make-posn 0 2) (make-posn 1 2) (make-posn 2 2))) true)
; [List-of List] -> List
; inserts all elements of sublists into a single list
(define (take-all-elems l)
(foldr append empty l))
; Posn [List-of QP] -> Boolean
; determines whether a QP threatens any element in list
(define (threatens-list? e l)
(ormap (lambda (x) (threatening? x e)) l))
; checks
(check-expect (threatens-list? (make-posn 0 0)
(list (make-posn 0 0) (make-posn 1 0) (make-posn 2 0))) true)
(check-expect (threatens-list? (make-posn 0 0)
(list (make-posn 134 34) (make-posn 1 32) (make-posn 1292 39090))) false)
; N Posn -> [List-of QP]
; see n-queens
(define (find-boards n)
(local ((define BOARD (make-board n))
(define (trials l b)
(cond
[(empty? b) l]
[(empty? l) (trials (list (first b)) b)]
[(threatens-list? (first b) l) (trials l (rest b))]
[(not (threatens-list? (first b) l)) (trials (cons (first b) l) (rest b))]))
(define MAIN (trials empty BOARD)))
(cond
[(n-queens-solution? n MAIN) MAIN]
[else (trials empty (rest BOARD))])))
(define (render-n-queens n)
(render-queens n (n-queens n) QUEEN))