001 package aima.search.nqueens; 002 003 import java.util.ArrayList; 004 import java.util.List; 005 006 import aima.basic.XYLocation; 007 008 public class NQueensBoard { 009 010 /** 011 * X---> increases left to right with zero based index Y increases top to 012 * bottom with zero based index | | V 013 */ 014 int[][] board; 015 016 int size; 017 018 public NQueensBoard(int n) { 019 020 size = n; 021 board = new int[size][size]; 022 for (int i = 0; i < size; i++) { 023 for (int j = 0; j < size; j++) { 024 board[i][j] = 0; 025 } 026 } 027 } 028 029 public void addQueenAt(XYLocation l) { 030 031 if (!(queenExistsAt(l))) 032 board[l.getXCoOrdinate()][l.getYCoOrdinate()] = 1; 033 } 034 035 public void removeQueenFrom(XYLocation l) { 036 037 if (board[l.getXCoOrdinate()][l.getYCoOrdinate()] == 1) { 038 board[l.getXCoOrdinate()][l.getYCoOrdinate()] = 0; 039 } 040 } 041 042 private boolean queenExistsAt(int x, int y) { 043 044 return (board[x][y] == 1); 045 } 046 047 public boolean queenExistsAt(XYLocation l) { 048 049 return (queenExistsAt(l.getXCoOrdinate(), l.getYCoOrdinate())); 050 } 051 052 public void moveQueen(XYLocation from, XYLocation to) { 053 054 if ((queenExistsAt(from)) && (!(queenExistsAt(to)))) { 055 removeQueenFrom(from); 056 addQueenAt(to); 057 } 058 } 059 060 public void clear() { 061 062 for (int i = 0; i < size; i++) { 063 for (int j = 0; j < size; j++) { 064 board[i][j] = 0; 065 } 066 } 067 } 068 069 public void setBoard(List<XYLocation> al) { 070 071 clear(); 072 073 for (int i = 0; i < al.size(); i++) { 074 addQueenAt(al.get(i)); 075 } 076 } 077 078 public int getNumberOfQueensOnBoard() { 079 080 int count = 0; 081 for (int i = 0; i < size; i++) { 082 for (int j = 0; j < size; j++) { 083 if (board[i][j] == 1) { 084 count++; 085 } 086 } 087 } 088 return count; 089 } 090 091 public List<XYLocation> getQueenPositions() { 092 093 ArrayList<XYLocation> result = new ArrayList<XYLocation>(); 094 for (int i = 0; i < size; i++) { 095 for (int j = 0; j < size; j++) { 096 if (queenExistsAt(i, j)) { 097 result.add(new XYLocation(i, j)); 098 } 099 } 100 } 101 return result; 102 103 } 104 105 private boolean isSquareHorizontallyAttacked(int x, int y) { 106 107 return numberOfHorizontalAttacksOn(x, y) > 0; 108 } 109 110 private boolean isSquareVerticallyAttacked(int x, int y) { 111 return numberOfVerticalAttacksOn(x, y) > 0; 112 } 113 114 private boolean isSquareDiagonallyAttacked(int x, int y) { 115 return numberOfDiagonalAttacksOn(x, y) > 0; 116 } 117 118 public boolean isSquareUnderAttack(XYLocation l) { 119 120 int x = l.getXCoOrdinate(); 121 int y = l.getYCoOrdinate(); 122 return (isSquareHorizontallyAttacked(x, y) 123 || isSquareVerticallyAttacked(x, y) || isSquareDiagonallyAttacked( 124 x, y)); 125 } 126 127 public int getSize() { 128 129 return size; 130 } 131 132 public void print() { 133 134 System.out.println(getBoardPic()); 135 136 } 137 138 public String getBoardPic() { 139 140 StringBuffer buffer = new StringBuffer(); 141 for (int row = 0; (row < size); row++) { // row 142 for (int col = 0; (col < size); col++) { // col 143 if (queenExistsAt(col, row)) { 144 buffer.append(" Q "); 145 } else { 146 buffer.append(" - "); 147 } 148 } 149 buffer.append("\n"); 150 } 151 return buffer.toString(); 152 } 153 154 public int getNumberOfAttacksOn(XYLocation l) { 155 156 int x = l.getXCoOrdinate(); 157 int y = l.getYCoOrdinate(); 158 return numberOfHorizontalAttacksOn(x, y) 159 + numberOfVerticalAttacksOn(x, y) 160 + numberOfDiagonalAttacksOn(x, y); 161 } 162 163 private int numberOfHorizontalAttacksOn(int x, int y) { 164 165 int retVal = 0; 166 for (int i = 0; i < size; i++) { 167 if ((queenExistsAt(i, y))) { 168 if (i != x) 169 retVal++; 170 } 171 } 172 return retVal; 173 } 174 175 private int numberOfVerticalAttacksOn(int x, int y) { 176 177 int retVal = 0; 178 for (int j = 0; j < size; j++) { 179 if ((queenExistsAt(x, j))) { 180 if (j != y) 181 retVal++; 182 } 183 } 184 return retVal; 185 } 186 187 private int numberOfDiagonalAttacksOn(int x, int y) { 188 189 int retVal = 0; 190 191 int i; 192 int j; 193 // forward up diagonal 194 for (i = (x + 1), j = (y - 1); (i < size && (j > -1)); i++, j--) { 195 if (queenExistsAt(i, j)) { 196 retVal++; 197 } 198 } 199 // forward down diagonal 200 for (i = (x + 1), j = (y + 1); ((i < size) && (j < size)); i++, j++) { 201 if (queenExistsAt(i, j)) { 202 retVal++; 203 } 204 } 205 // backward up diagonal 206 for (i = (x - 1), j = (y - 1); ((i > -1) && (j > -1)); i--, j--) { 207 if (queenExistsAt(i, j)) { 208 retVal++; 209 } 210 } 211 212 // backward down diagonal 213 for (i = (x - 1), j = (y + 1); ((i > -1) && (j < size)); i--, j++) { 214 if (queenExistsAt(i, j)) { 215 retVal++; 216 } 217 } 218 219 return retVal; 220 } 221 222 @Override 223 public int hashCode() { 224 List<XYLocation> locs = getQueenPositions(); 225 226 int result = 17; 227 for (XYLocation loc : locs) { 228 result = 37 * loc.hashCode(); 229 } 230 return result; 231 } 232 233 @Override 234 public boolean equals(Object o) { 235 236 if (this == o) { 237 return true; 238 } 239 if ((o == null) || (this.getClass() != o.getClass())) { 240 return false; 241 } 242 NQueensBoard aBoard = (NQueensBoard) o; 243 boolean retVal = true; 244 List<XYLocation> locs = getQueenPositions(); 245 246 for (XYLocation loc : locs) { 247 if (!(aBoard.queenExistsAt(loc))) { 248 retVal = false; 249 } 250 } 251 return retVal; 252 } 253 254 @Override 255 public String toString() { 256 StringBuffer buf = new StringBuffer(); 257 for (int row = 0; row < size; row++) { // rows 258 for (int col = 0; col < size; col++) { // columns 259 if (queenExistsAt(col, row)) { 260 buf.append('Q'); 261 } else { 262 buf.append('-'); 263 } 264 } 265 buf.append("\n"); 266 } 267 return buf.toString(); 268 } 269 270 }