Introduction to Object Oriented Programming, 3rd Ed

Timothy A. Budd

Chapter 6

A Case Study : Eight Queens

Outline

  1. Statement of the Problem
  2. OOP Approach
  3. Observations
  4. Pointers
  5. CRC Card for Queen
  6. CRC Card for Queen - Backside
  7. Initialization
  8. Finding First Solution
  9. Advancing to Next Position
  10. Printing Solution
  11. Can Attack
  12. The Last Queen
  13. Chapter Summary

Source Code

Other Material

Intro OOP, Chapter 6, Slide 1

Statement of the Problem

Problem - how to place eight queens on a chessboard so that no two queens can attack each other:

chessboard with 8 queens

Intro OOP, Chapter 6, Slide 1


OOP Approach

More than just solving the problem, we want to solve the problem in an OOP manner.

Intro OOP, Chapter 6, Slide 2


Observations

Here are a few observations we can make concerning this problem:

Intro OOP, Chapter 6, Slide 3


Pointers

We can make each queen point to the next on the left, then send messages only to the rightmost queen. Each queen will in turn send messages only to the neighbor it points to.

picture of queens pointing to each other

Intro OOP, Chapter 6, Slide 4


CRC Card for Queen

CRC card for queen class
Intro OOP, Chapter 6, Slide 5


CRC Card for Queen - Backside


back side of CRC card
Intro OOP, Chapter 6, Slide 6


Initialization

Initialization will set each queen to point to a neighbor, and set column value. C++ version is shown:


main() {
	Queen * lastQueen = 0;

	for (int i = 1; i <= 8; i++) {
		lastQueen = new Queen(i, lastQueen);
		if (! lastQueen->findSolution())
			cout << "no solution";
	}
	
	if (lastQueen->first()) 
		lastQueen->print();
}

Queen::Queen (int col, Queen * ngh)
{
	column = col;
	neighbor = ngh;
	row = 1;
}

Intro OOP, Chapter 6, Slide 7


Finding First Solution

Finding first solution, in pseudo-code:


function queen.findSolution -> boolean
	
	while neighbor.canAttack (row, column) do
		if not self.advance then
			return false;

		// found a solution
	return true;
end

We ignore for the moment the question of what to do if you don't have a neighbor
Intro OOP, Chapter 6, Slide 8


Advancing to Next Position


function queen.advance -> boolean

	if row < 8 then begin
		row := row + 1;
		return self.findSolution
	end

		// cannot go further, move neighbor
	if not neighbor.advance then
		return false

	row := 1
	return self findSolution

end
Intro OOP, Chapter 6, Slide 9


Printing Solution

Just recursively ripple down the list of queens, asking each to print itself.

procedure print
	neighbor.print
	write row, column
end

Intro OOP, Chapter 6, Slide 10


Can Attack


function canAttack(r, c)
	if r = row then
		return true
	cd := column - c;
	if (row + cd = r) or (row - cd = r) then
		return true;
	return neighbor.canAttack(r, c)
end
For a diagonal, the difference in row must equal the difference in columns.
Intro OOP, Chapter 6, Slide 11


The Last Queen

Two approaches to handling the leftmost queen -

Both versions are described in text.

Intro OOP, Chapter 6, Slide 12

The complete solutions in each language are not described in the slides, but are presented in detail in the text.
A Java applet version is available.

Chapter Summary

Important not for the problem being solved, but how it is solved.

Intro OOP, Chapter 6, Slide 13