CMPS 144 Summer 2020
Prog. Assg. #5: Eight Queens Board

Background

Among the best known puzzle-type problems in computer science is the Eight Queens Problem. The goal is to place eight queens on a chessboard so that no two of them are "attacking" each other. Which is to say that no two queens can be placed in the same row, the same column, or the same diagonal. (In chess, a queen can attack an opponent's piece along a row, column, or diagonal.) Because a chessboard has eight rows and eight columns of squares, any solution will have exactly one queen in each row and one queen in each column.

4 | - - Q - -
3 | - - - - Q
2 | - Q - - -
1 | - - - Q -
0 | Q - - - -
  +----------
    0 1 2 3 4
To make the problem more interesting, we generalize it to consider N-by-N boards, for any N≥1. As an example, to the right is shown one solution for the 5-by-5 board. We follow the convention of numbering the rows and columns starting at zero and displaying a board so that row numbers increase going from "south" to "north" and column numbers increase going from "west" to "east".

Assignment

You are to complete the implementation of the Java class EightQueensBoard, several of whose methods are stubbed. An instance of this class does not, by itself, solve the N-Queens problem described above. Rather, it is intended to provide a convenient representation of a chessboard, occupied by zero or more queens, to a client program whose purpose is to solve that problem.

Useful to such a client program would be (mutator) methods for placing queens onto the board and for removing them, as the program searched through various placements of queens in its search for a solution. Also useful would be (observer) methods able to answer such questions as

How many queens are on the board?
May a queen be placed onto square (4,6)?
Is there a queen in row 2?
In which column is the queen who is in row 5?

The EightQueensBoard class includes methods that provide answers to such questions.

For testing purposes, you are provided with the Java application EightQueensBoardTester.


Representation

As provided, the EightQueensBoard class includes instance variables rowToCol[] and colToRow[], each of which is an array of integers. (The square brackets following the names are intended to indicate that they are arrays.)

Suppose that an object of this class represents a board of size N (meaning one having N rows and N columns). The intent is that, for each i in [0..N), the value of rowToCol[i] will identify the column in which lies the queen occupying row i, if any. Similarly, the value of colToRow[j] will identify the row in which lies the queen occupying column j, if any. (−1 is used to indicate "none".)1

Because at most one queen can occupy any row or column, either of these arrays, by itself, is sufficient to fully describe the current state of the board. Consider, for example, the board shown below. The corresponding arrays are shown next to it.

BoardRepresentation
 5 | - - - - - -
 4 | - - - - - Q
 3 | - Q - - - -
 2 | - - - - Q -
 1 | Q - - - - -
 0 | - - - Q - -
   +------------
     0 1 2 3 4 5
           0   1   2   3   4   5
         +---+---+---+---+---+---+
rowToCol | 3 | 0 | 4 | 1 | 5 | -1|
         +---+---+---+---+---+---+

           0   1   2   3   4   5
         +---+---+---+---+---+---+
colToRow | 1 | 3 | -1| 0 | 2 | 4 |
         +---+---+---+---+---+---+

If either array, by itself, is sufficient to describe any legal placement of queens on a board, then why are both arrays included? The answer is that, by using a second array, we gain speed at the expense of using extra space (i.e., the memory occupied by the second array). For example, consider how to go about computing the answer to the question, "Is there a queen in column 3?". Using the colToRow[] array, that reduces to evaluating the boolean expression colToRow[3] != -1. But what if that array did not exist. Then it would be necessary to iterate through the elements of rowToCol[] in search of the value 3.

Diagonals: Consider the question, "Can a queen be placed onto square (5,2)?". Clearly, for the answer to be "yes" requires that no queen lies in row 5 or column 2. However, that is not a sufficient condition, because the answer should be "no" if a queen occupies either of the two diagonals that includes square (5,2), even if both row 5 and column 2 are queen-less.

There are two categories of diagonals, those that run northwest to southeast (NW-SE) and those that run northeast to southwest (NE-SW). The NW-SE diagonals are uniquely identified by the sum of their row and column coordinates. Thus, for example, squares (5,2) and (4,3) lie on the same NW-SE diagonal, namely the one containing all squares (r,c) where r+c = 7.

The NE-SW diagonals, on the other hand, are uniquely identified by the difference between row and column coordinates. For example, squares (2,5) and (0,3) lie on the same NE-SW diagonal, namely the one containing all squares (r,c) where r−c = −3.

Summarizing, to verify that a queen can be placed upon a specified square (r,c), one must verify that there are no queens in any of

To check a diagonal, one can iterate through all the squares on that diagonal, checking each one for an occupying queen. On the other hand, one can make another time/space tradeoff by introducing two arrays, one of which keeps track of which NW-SE diagonals include a square occupied by a queen and the other of which serves the same purpose for NE-SW diagonals. The indexing is straightforward for NW-SE diagonals, because the range of r+c sums goes from 0 to 2(N−1). The indexing for NE-SW diagonals must involve an offset, because the range of r−c values goes from −(N−1) to +(N−1).

The student is encouraged to pursue this idea in completing this assignment.


Footnote

[1] Ignoring the −1's, the two arrays represent one-to-one functions that are inverses of each other.


Program Submission

Using the file submission system (see link on course web page), you are to submit the relevant Java class source code file to the prog5_dir folder.