MT311 Java Application Development and Programming Languages Li Tak Sing ( 李德成 )
Some more examples in recursion The eight queens problems Eight queens are to be placed on a chess board so that they do not check each other. The program should print out the first solution it finds.
Eight queens problem So we would have a class like this: public class EightQueen {.... public void main(String st[]) {..... } }
Eight queens problem No two queens can be put into the same column, or the same row, or the same diagonal line. Since the chess board has 8 rows, 8 columns and 15 diagonal lines from top right to bottom left and 15 diagonal lines from top left to bottom right, so there should only be one queen in each row, one queen in each column and at most one queen in one diagonal line.
Eight queens problem Assume that we are putting a queen in one row from top to bottom. So we do not need to do any book keeping for queens in rows. But, we need to store information regarding which columns have already occupied so that the next move should not be put in those columns. Similarly, we also need to store information regarding which diagonal lines have been occupied.
Eight queens problem Let x, y represents the row and columns of a position in the chess board so that they are both from 0 to 7. So a particular value of x represents a row, a particular value of y represents a column, a particular value of x+y represents a diagonal line running the from top left to bottom right, a particular value of x-y represents a diagonal line running from top right to bottom left.
Eight queens problem As both x, y are from 0 to 7, so x+y can range from 0 to 14 and x-y can range from -7 to 7. So it is easy to use an array of boolean to represents whether a particular x+y type of diagonal line is occupied because x+y has values starting from 0 which is exactly what Java needs.
Eight queens problem However, for the x-y style of diagonal lines, the value ranges from -7 to 7. So the value is not suitable to be used directly as index of an array. So we need to add 7 to the value so that the value becomes from 0 to 14 as well.
Eight queens problem So we have 3 arrays of boolean that represents whether a column, an x+y style of diagonal line and an x-y style of diagonal line is occupied. Just to remain you that we do not need such an array to store information regarding whether a row is occupied or not because we are putting a queen on each row one by one.
Eight queen problem public class EightQueens { boolean column[]=new boolean[8]; boolean xaddy[]=new boolean[15]; //x+y style diagonal line boolean xsuby[]=new boolean[15]; //x-y style diagonal line public EightQueens() { for (int i=0;i<8;i++) { column[i]=false; } for (int i=0;i<15;i++) { xaddy[i]=xsuby[i]=false; }
Eight queens problem Now assume that we have a method to put the n-th move and the method should return true if this move will finally give a valid result. So in this method, we would try all the positions in the row to see if the we can put a queen in the positions. If the answer is yes, then we need to check whether this move is the last move. If it is, then we have successfully get a valid result.
Eight queens problem If the move is not the last move, then we need to recursively call the method again to make the next move. After returning from that method, if the result is false, this means that the last move is invalid, so we undo the move and try next position. If there is no more position left in the row, then this means that there is no hope to get a valid result and we just return false.
public boolean move(int y) { for (int x=0;x<8;x++) { if (column[x] || xaddy[x+y] || xsuby[7+x-y]) { continue; // the position is not valid, try another } column[x]=xaddy[x+y]=xsuby[7+x-y]=true; //try this position if (y==7) { System.out.println("A valid result is found"); System.out.println(x+" "+y); return true; //a valid result is found } else { if (move(y+1)) { System.out.println(x+" "+y); //print the result return true; } else { column[x]=xaddy[x+y]=xsuby[7+x-y]=false; //undo } return false; }
Eight Queens problem Now, we want to change the program so that it prints out all possible solutions.
Tower of hanoi There are three poles and a number of discs so that all the discs are of different sizes. Each disc has a hole so that they can be put onto the poles. Originally, all the discs are in one pole so that the discs increasing in size from bottom to top.
Tower of Hanoi Now, we want to move the discs from the first pole to the second so that when we move the discs, no disc is allowed to put on a disc with smaller size.
Tower of Hanoi public class Pole { int id; public Pole(int i) {id=i;} public void moveADiscFrom(Pole p) { System.out.println("move a disc from "+p.id+" to "+id); } public move(int noDisc, Pole p2, Pole p3) { //move top noDisc from this pole //to pole p2 with p3 as intermediate pole }
Tower of Hanoi If noDisc is 0, then the method would do nothing. move top noDisc-1 discs to pole3, then move the bottom disc to pole2, then move the noDisc-1 discs from pole3 to pole2.
Tower of Hanoi public void move(int disc, Pole p2, Pole p3) { if (disc==0) { return; } else { move(disc-1, p3,p2); System.out.println("move a disc from pole "+id+" to pole "+p2.id); p3.move(disc-1,p2,this ); }
Eight queens problem