This page is no longer maintained — Please continue to the home page at www.scala-lang.org

OO n-queens; comments?

No replies
Kenneth McDonald
Joined: 2009-01-11,
User offline. Last seen 42 years 45 weeks ago.

As an exercise, I decided to write the n-queens problem (without
looking at the solution :-) ), but using some OO in there to make
things (I believe) a little clearer. I'd be curious as to what people
thought--is the OO solution really easier to understand, or am I just
thinking too much in OO?

Oh, it has a really crude printout facility, if you actually run it....

Thanks,
Ken

-----------------

package nqueensPackage

// A position is the position of a single queen.
case class Position(row:Int, col:Int) {
// Is this position safe from being in check by a queen at
position p?
def isSafeFrom(p:Position) = {
(p.row != row) && (p.col != col) && ((p.col-col).abs !=
(p.row-row).abs)
}
}

// A layout is a layout of queens, none in check with each other.
class Layout(var positions:List[Position]) {
def this() = this(List())

//Is this layout safe for placement of a queen at position p?
def isSafeFor(p:Position) = {
positions.forall(p.isSafeFrom _)
}

// Return a new layout with a queen added at the given position.
def add(p:Position) = new Layout(p::positions)

override def toString:String = {
var sorted = positions.sort((x, y) => x.row < y.row)
var rowStrings = for (s <- sorted) yield "| "*(s.col-1) + "|
*" + "| " *(positions.length-s.col+1)
rowStrings = "\n------" :: rowStrings
rowStrings.mkString("\n")
}
}

object nqueens {

// Place N queens on an NxN board
def placeN(dimension:Int) = {
// divide and conquer. Row is the row on which we are
// placing a queen.
def place(row:Int):List[Layout] = {
// If this is row 0 (of a 0x0 board), the puzzle is
solved by
// a null Layout
if (row == 0) List(new Layout())
// otherwise, row >= 1; place everything safely in rows
0...row-1,
// for each column in the current row, try to place a
queen, and if
// successful, yield the result for inclusion in the
results.
else for(
layout <- place(row - 1);
col <- 1 to dimension;
p = Position(row, col);
if layout.isSafeFor(p)
)
yield layout.add(p)
}

// Start the main 'place' function with the dimension of the
board.
place(dimension)
}
def main(args: Array[String]) = {
println("Hello, world!")
println(placeN(6).mkString)
}

}

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland