############################################################################ # # File: vnq.icn # # Subject: Program to display solutions to n-queens problem # # Author: Stephen B. Wampler # # Date: August 14, 1996 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This program displays solutions to the n-queens problem. # ############################################################################ # # 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