N-Queens不返还任何皇后区

时间:2015-03-11 17:36:25

标签: algorithm scheme racket n-queens

我很困惑为什么以下的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))

0 个答案:

没有答案