99 lines
2.8 KiB
Common Lisp
99 lines
2.8 KiB
Common Lisp
|
|
;
|
|
; Place n queens on a board (graphical version)
|
|
; See Winston and Horn Ch. 11
|
|
;
|
|
; Usage:
|
|
; (queens <n>)
|
|
; where <n> is an integer -- the size of the board - try (queens 4)
|
|
;
|
|
; I do not know who the original Author of this is but it was found with some
|
|
; XLISP example lisp programs. This has been slightly modified to run on
|
|
; PC-LISP V2.13.
|
|
;
|
|
; Peter Ashwood-Smith
|
|
; August 22nd, 1986
|
|
|
|
; Do two queens threaten each other ?
|
|
|
|
(defun threat (i j a b)
|
|
(or (= i a) ;Same row
|
|
(= j b) ;Same column
|
|
(= (- i j) (- a b)) ;One diag.
|
|
(= (+ i j) (+ a b)))) ;the other diagonal
|
|
|
|
; Is poistion (n,m) on the board safe for a queen ?
|
|
|
|
(defun conflict (n m board)
|
|
(cond ((null board) nil)
|
|
((threat n m (caar board) (cadar board)) t)
|
|
(t (conflict n m (cdr board)))))
|
|
|
|
|
|
; Place queens on a board of size SIZE
|
|
|
|
(defun queens (size)
|
|
(prog (n m board soln)
|
|
(setq soln 0) ;Solution #
|
|
(setq board ())
|
|
(setq n 1) ;Try the first row
|
|
loop-n
|
|
(setq m 1) ;Column 1
|
|
loop-m
|
|
(cond ((conflict n m board) (go un-do-m))) ;Check for conflict
|
|
(setq board (cons (list n m) board)) ; Add queen to board
|
|
(cond ((> (setq n (1+ n)) size) ; Placed N queens ?
|
|
(print-board (reverse board) (setq soln (1+ soln))))) ; Print it
|
|
(go loop-n) ; Next row which column?
|
|
un-do-n
|
|
(cond ((null board) (return 'Done))) ; Tried all possibilities
|
|
(setq m (cadar board)) ; No, Undo last queen placed
|
|
(setq n (caar board))
|
|
(setq board (cdr board))
|
|
un-do-m
|
|
(cond ((> (setq m (1+ m)) size) ; Go try next column
|
|
(go un-do-n))
|
|
(t (go loop-m)))))
|
|
|
|
|
|
;Print a board
|
|
|
|
(defun print-board (board soln)
|
|
(prog (size)
|
|
(setq size (length board)) ;we can find our own size
|
|
(princ "\f\n\t\tSolution: ")
|
|
(princ soln)
|
|
(princ "\n\n\t")
|
|
(print-header size 1)
|
|
(princ "\n")
|
|
(print-board-aux board size 1)
|
|
(princ "\n")
|
|
)
|
|
)
|
|
|
|
; Put Column #'s on top
|
|
|
|
(defun print-header (size n)
|
|
(cond ((> n size) (princ "\n"))
|
|
(t (prog () (patom n)
|
|
(princ " ")
|
|
(print-header size (1+ n))))))
|
|
|
|
(defun print-board-aux (board size row)
|
|
(princ "\n")
|
|
(cond ((null board) ())
|
|
(t (prog ()
|
|
(princ row) ;print the row #
|
|
(princ "\t")
|
|
(print-board-row (cadar board) size 1) ;Print the row
|
|
(print-board-aux (cdr board) size (1+ row)))))) ;Next row
|
|
|
|
(defun print-board-row (column size n)
|
|
(cond ((> n size)())
|
|
(t (prog ()
|
|
(cond ((equal column n) (princ "Q"))
|
|
(t (princ ".")))
|
|
(princ " ")
|
|
(print-board-row column size (1+ n))))))
|
|
|