home *** CD-ROM | disk | FTP | other *** search
- ############################################################################
- #
- # File: vnq.icn
- #
- # Subject: Program to display solutions to n-queens problem
- #
- # Author: Stephen B. Wampler
- #
- # Date: December 12, 1989
- #
- ###########################################################################
- #
- # Links: options
- #
- ############################################################################
-
- link options
-
- global n, nthq, solution, goslow, showall, line, border
-
- procedure main(args)
- local i, opts
-
- opts := options(args, "sah")
- n := integer(get(args)) | 8 # default is 8 queens
- if \opts["s"] then goslow := "yes"
- if \opts["a"] then showall := "yes"
- if \opts["h"] then helpmesg()
-
- line := repl("| ", n) || "|"
- border := repl("----", n) || "-"
- clearscreen()
- movexy(1, 1)
- write()
- write(" ", border)
- every 1 to n do {
- write(" ", line)
- write(" ", border)
- }
-
- nthq := list(n+2) # need list of queen placement routines
- solution := list(n) # ... and a list of column solutions
-
- nthq[1] := &main # 1st queen is main routine.
- every i := 1 to n do # 2 to n+1 are real queen placement
- nthq[i+1] := create q(i) # routines, one per column.
- nthq[n+2] := create show() # n+2nd queen is display routine.
-
- write(n, "-Queens:")
- @nthq[2] # start by placing queen in first colm.
-
- movexy(1, 2 * n + 5)
- end
-
- # q(c) - place a queen in column c (this is c+1st routine).
- procedure q(c)
- local r
- static up, down, rows
-
- initial {
- up := list(2 * n -1, 0)
- down := list(2 * n -1, 0)
- rows := list(n, 0)
- }
-
- repeat {
- every (0 = rows[r := 1 to n] = up[n + r - c] = down[r + c -1] &
- rows[r] <- up[n + r - c] <- down[r + c -1] <- 1) do {
- solution[c] := r # record placement.
- if \showall then {
- movexy(4 * (r - 1) + 5, 2 * c + 1)
- writes("@")
- }
- @nthq[c + 2] # try to place next queen.
- if \showall then {
- movexy(4 * (r - 1) + 5, 2 * c + 1)
- writes(" ")
- }
- }
- @nthq[c] # tell last queen placer 'try again'
- }
-
- end
-
- # show the solution on a chess board.
-
- procedure show()
- local c
- static count, lastsol
-
- initial {
- count := 0
- }
-
- repeat {
- if /showall & \lastsol then {
- every c := 1 to n do {
- movexy(4 * (lastsol[c] - 1) + 5, 2 * c + 1)
- writes(" ")
- }
- }
- movexy(1, 1)
- write("solution: ", right(count +:= 1, 10))
- if /showall then {
- every c := 1 to n do {
- movexy(4 * (solution[c] - 1) + 5, 2 * c + 1)
- writes("Q")
- }
- lastsol := copy(solution)
- }
- if \goslow then {
- movexy(1, 2 * n + 4)
- writes("Press return to see next solution:")
- read() | {
- movexy(1, 2 * n + 5)
- stop("Aborted.")
- }
- movexy(1, 2 * n + 4)
- clearline()
- }
-
- @nthq[n+1] # tell last queen placer to try again
- }
-
- end
-
- procedure helpmesg()
- write(&errout, "Usage: vnq [-s] [-a] [n]")
- write(&errout, " where -s means to stop after each solution, ")
- write(&errout, " -a means to show placement of every queen")
- write(&errout, " while trying to find a solution")
- write(&errout, " and n is the size of the board (defaults to 8)")
- stop()
- end
-
- # Move cursor to x, y
- #
- procedure movexy (x, y)
- writes("\^[[", y, ";", x, "H")
- return
- end
-
- #
- # Clear the text screen
- #
- procedure clearscreen()
- writes("\^[[2J")
- return
- end
-
- #
- # Clear the rest of the line
- #
- procedure clearline()
- writes("\^[[2K")
- return
- end
-