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