Click presentation screen icon to the right to see the slide show.
How do you find your way to downtown Fort Collins?
How do you find your way to downtown Fort Collins?
Start out in general direction. You will know when you have found it.
What do you do if you hit a dead end road, or you find yourself in La Porte?
How do you find your way to downtown Fort Collins?
Start out in general direction. You will know when you have found it.
What do you do if you hit a dead end road, or you find yourself in La Porte?
Right. Go back a few blocks and make a different decision.
Continue like this until you find downtown.
That's “backtracking”.
On a chess board, Queens attack along diagonals, rows, and columns.
The Eight Queens Problem is to place eight queens on the board so that no queen is attacking another.
Each queen must be in a column. Thank goodness a chess board has eight columns.
Now what?
On a chess board, Queens attack along diagonals, rows, and columns.
The Eight Queens Problem is to place eight queens on the board so that no queen is attacking another.
Each queen must be in a column. Thank goodness a chess board has eight columns.
Now what?
Must figure out which row in which to place each queen.
If we place the first queen in row 1, how many rows are left for the other seven queens?
On a chess board, Queens attack along diagonals, rows, and columns.
The Eight Queens Problem is to place eight queens on the board so that no queen is attacking another.
Each queen must be in a column. Thank goodness a chess board has eight columns.
Now what?
Must figure out which row in which to place each queen.
If we place the first queen in row 1, how many rows are left for the other seven queens?
Yes….seven, so put the second queen in row 2.
If we place the first queen in row 1, how many rows are left for the other seven queens?
Yes….seven, so put the second queen in row 2.
Oops. Yep. First and second queen attack each other along diagonal, so put second queen in third row.
Can keep going this way, or just punt.
If we place the first queen in row 1, how many rows are left for the other seven queens?
Yes….seven, so put the second queen in row 2.
Oops. Yep. First and second queen attack each other along diagonal, so put second queen in third row.
Can keep going this way, or just punt.
There are 8 rows to choose for the first queen, 7 for the second, 6 for the third, …..
So, possible row assignments. Is that too big to think about?
If we place the first queen in row 1, how many rows are left for the other seven queens?
Yes….seven, so put the second queen in row 2.
Oops. Yep. First and second queen attack each other along diagonal, so put second queen in third row.
Can keep going this way, or just punt.
There are 8 rows to choose for the first queen, 7 for the second, 6 for the third, …..
So, possible row assignments. Is that too big to think about?
. Maybe we can succeed by trying some row assignments, then varying some decisions when we hit a dead end.
Backtracking!
The backtracking step:
At least three ways to go back to column
The third choice may be most intuitive.
Use recursive calls to work on next column, and return to go back to previous column.
Basic idea:
public class EightQueens { protected int[] rows; public EightQueens() { rows = new int[8]; } public boolean placeQueens(int column) { // Base case if (column > 8) return true; // YIPPEE // Try each row sequentially, for current column. for (int row = 1; row <= 8; row++) { rows[column-1] = row; // Remember which row used in current column. if (!attacked(row,column) && // Check for attack from previously placed queens. placeQueens(column+1)) // Recursive call, one fewer columns return true; } return false; }
How would you code the attacked method?
public boolean attacked(int row,int column) { . . . }
How would you code the attacked method?
public boolean attacked(int row,int column) { . . . }
Don't need to check for same column, since we are assigning to different columns sequentially.
Must examine queen placements in each of the previous columns.
public boolean attacked(int row,int column){ for (int c = 0; c < column-1; c++) { . . . }
Must examine queen placements in each of the previous columns.
Check for same row.
public boolean attacked(int row,int column){ for (int c = 0; c < column-1; c++) { if (rows[c] == row) return true; . . . }
Now for the diagonals. How?
Now for the diagonals. How?
public boolean attacked(int row,int column){ for (int c = 0; c < column-1; c++) { if (rows[c] == row) return true; if (Math.abs(rows[c] - row) == Math.abs(c+1-column)) return true; } . . . }
Now for the diagonals. How?
public boolean attacked(int row,int column){ for (int c = 0; c < column-1; c++) { if (rows[c] == row) return true; if (Math.abs(rows[c] - row) == Math.abs(c+1-column)) return true; } . . . }
And what if we drop out of bottom of for loop?
And what if we drop out of bottom of for loop?
public boolean attacked(int row,int column){ for (int c = 0; c < column-1; c++) { if (rows[c] == row) return true; if (Math.abs(rows[c] - row) == Math.abs(c+1-column)) return true; } return false; }
Don't forget to
import java.lang.Math;
(The compiler won't let you forget!)
One more bit of code for fun. How do we print a chess board with the queens placed?
One more bit of code for fun. How do we print a chess board with the queens placed?
public String toString() { String oneRow = "--------\n"; StringBuffer board = new StringBuffer(oneRow + oneRow + oneRow + oneRow + oneRow + oneRow + oneRow + oneRow); for (int i = 0; i < 8; i++) { if (rows[i] > 0) board.setCharAt((rows[i]-1)*9 + i, 'Q'); } return new String(board); }
Now, a main to try it all out.
public static void main(String [] args) { EightQueens q = new EightQueens(); boolean result = q.placeQueens(1); if (result) System.out.println("Success"); else System.out.println("Failure"); System.out.println(q); }
And, ta-da, we get
Success Q------- ------Q- ----Q--- -------Q -Q------ ---Q---- -----Q-- --Q-----