123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. import java.util.Arrays;
  2. import java.util.ArrayList;
  3. public class EightQueens {
  4. public static void main(String[] args) {
  5. solveNQueens(8);
  6. ArrayList<char[][]> solutions = getAllNQueens(8);
  7. System.out.println( solutions.size() );
  8. for( int i = 0; i < solutions.size(); i++){
  9. System.out.println("\n\nSolution " + (i+1));
  10. if( queensAreSafe(solutions.get(i)) )
  11. printBoard(solutions.get(i));
  12. else
  13. System.out.println("UH OH!!!!! BETTER FIX IT!!!!!");
  14. }
  15. /**
  16. * determine if the chess board represented by board is a safe set up
  17. * <p>pre: board != null, board.length > 0, board is a square matrix.
  18. * (In other words all rows in board have board.length columns.),
  19. * all elements of board == 'q' or '.'. 'q's represent queens, '.'s
  20. * represent open spaces.<br>
  21. * <p>post: return true if the configuration of board is safe,
  22. * that is no queen can attack any other queen on the board.
  23. * false otherwise.
  24. * @param board the chessboard
  25. * @return true if the configuration of board is safe,
  26. * that is no queen can attack any other queen on the board.
  27. * false otherwise.
  28. */
  29. public static boolean queensAreSafe(char[][] board)
  30. { char[] validChars = {'q', '.'};
  31. assert (board != null) && (board.length > 0)
  32. && isSquare(board) && onlyContains(board, validChars)
  33. : "Violation of precondition: queensAreSafe";
  34. return true;
  35. }
  36. public static ArrayList<char[][]> getAllNQueens(int size){
  37. ArrayList<char[][]> solutions = new ArrayList<char[][]>();
  38. char[][] board = blankBoard(size);
  39. solveAllNQueens(board, 0, solutions);
  40. return solutions;
  41. }
  42. public static void solveAllNQueens(char[][] board, int col, ArrayList<char[][]> solutions){
  43. // am I done? if so, add this solution to the ArrayList of solutions
  44. if( col == board.length){
  45. solutions.add( makeCopy(board));
  46. // all done
  47. } else {
  48. for(int row = 0; row < board.length; row++){
  49. // place queen
  50. board[row][col] = 'q';
  51. if( queensAreSafe(board) )
  52. // if safe go on to next column
  53. solveAllNQueens(board, col + 1, solutions);
  54. board[row][col] = '.';
  55. }
  56. }
  57. }
  58. // pre: mat != null, mat is rectangular
  59. public static char[][] makeCopy(char[][] mat){
  60. assert mat != null;
  61. char[][] copy = new char[mat.length][mat[0].length];
  62. for(int r = 0; r < mat.length; r++)
  63. for(int c = 0; c < mat[0].length; c++)
  64. copy[r][c] = mat[r][c];
  65. return copy;
  66. }
  67. public static void printBoard(char[][] board){
  68. for(int r = 0; r < board.length; r++){
  69. for(int c = 0; c < board[r].length; c++)
  70. System.out.print(board[r][c]);
  71. System.out.println();
  72. }
  73. }
  74. public static void solveNQueens(int n){
  75. char[][] board = blankBoard(n);
  76. //start in column 0
  77. boolean solved = canSolve(board, 0);
  78. if( solved ){
  79. System.out.println("Solved the " + n + " queen problem.");
  80. printBoard(board);
  81. }
  82. else
  83. System.out.println("Can't solve the " + n + " queen problem.");
  84. }
  85. public static boolean
  86. canSolve(char[][] board, int col){
  87. //know when you are done!
  88. if( col == board.length)
  89. return true; // solved!!!!!
  90. // not done, try all the rows
  91. boolean solved = false;
  92. for(int row = 0; row < board.length && !solved; row++){
  93. //System.out.println(row + " " + col);
  94. // place queen
  95. board[row][col] = 'q';
  96. if( queensAreSafe(board) )
  97. solved = canSolve(board, col + 1);
  98. if( !solved )
  99. board[row][col] = '.';
  100. }
  101. return solved; //could be true(solved) or false(not solved)!!
  102. }
  103. private static char[][] blankBoard(int size){
  104. char[][] result = new char[size][size];
  105. for(int r = 0; r < size; r++)
  106. Arrays.fill(result[r], '.');
  107. return result;
  108. }
  109. private static boolean inbounds(int row, int col, char[][] mat){
  110. return row >= 0 && row < mat.length && col >= 0 && col < mat[0].length;
  111. }
  112. /* pre: mat != null
  113. post: return true if mat is a square matrix, false otherwise
  114. */
  115. private static boolean isSquare(char[][] mat)
  116. { assert mat != null : "Violation of precondition: isSquare";
  117. final int numRows = mat.length;
  118. int row = 0;
  119. boolean square = true;
  120. while( square && row < numRows )
  121. { square = ( mat[row] != null) && (mat[row].length == numRows);
  122. row++;
  123. }
  124. return square;
  125. }
  126. /* pre: mat != null, valid != null
  127. post: return true if all elements in mat are one of the characters in valid
  128. */
  129. private static boolean onlyContains(char[][] mat, char[] valid)
  130. { assert mat != null && valid != null : "Violation of precondition: onlyContains";
  131. int row = 0;
  132. int col;
  133. boolean correct = true;
  134. while( correct && row < mat.length)
  135. { col = 0;
  136. while(correct && col < mat[row].length)
  137. { correct = contains(valid, mat[row][col]);
  138. col++;
  139. }
  140. row++;
  141. }
  142. return correct;
  143. }
  144. /* pre: list != null
  145. post: return true if c is in list
  146. */
  147. private static boolean contains(char[] list, char c)
  148. { assert ( list != null ) : "Violation of precondition: contains";
  149. boolean found = false;
  150. int index = 0;
  151. while( !found && index < list.length)
  152. { found = list[index] == c;
  153. index++;
  154. }
  155. return found;
  156. }
  157. }