|
| 1 | +import java.util.List; |
| 2 | +import java.util.Optional; |
| 3 | +import java.util.Scanner; |
| 4 | + |
| 5 | +/** |
| 6 | + * QUEEN |
| 7 | + * <p> |
| 8 | + * Converted from BASIC to Java by Aldrin Misquitta (@aldrinm) |
| 9 | + */ |
| 10 | +public class Queen { |
| 11 | + |
| 12 | + public static final int WINNING_POSITION = 158; |
| 13 | + public static final int FORFEIT_MOVE = 0; |
| 14 | + |
| 15 | + // @formatter:off |
| 16 | + private static final int[] S = { |
| 17 | + 81, 71, 61, 51, 41, 31, 21, 11, |
| 18 | + 92, 82, 72, 62, 52, 42, 32, 22, |
| 19 | + 103, 93, 83, 73, 63, 53, 43, 33, |
| 20 | + 114, 104, 94, 84, 74, 64, 54, 44, |
| 21 | + 125, 115, 105, 95, 85, 75, 65, 55, |
| 22 | + 136, 126, 116, 106, 96, 86, 76, 66, |
| 23 | + 147, 137, 127, 117, 107, 97, 87, 77, |
| 24 | + 158, 148, 138, 128, 118, 108, 98, 88 |
| 25 | + }; |
| 26 | + // @formatter:on |
| 27 | + |
| 28 | + private static final Scanner scanner = new Scanner(System.in); |
| 29 | + |
| 30 | + |
| 31 | + public static void main(String[] args) { |
| 32 | + printWithTab("QUEEN", 33); |
| 33 | + printWithTab("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY", 15); |
| 34 | + System.out.println("\n\n"); |
| 35 | + |
| 36 | + askAndShowInstructions(); |
| 37 | + |
| 38 | + boolean anotherGame; |
| 39 | + do { |
| 40 | + printBoard(); |
| 41 | + |
| 42 | + Move firstMove = getUserFirstMove(); |
| 43 | + if (firstMove.move == 0) { |
| 44 | + printWonByForfeit(); |
| 45 | + } |
| 46 | + |
| 47 | + if (isTopmostRowOrRightmostColumn(firstMove)) { |
| 48 | + playOneGame(firstMove); |
| 49 | + } |
| 50 | + |
| 51 | + anotherGame = askForAnotherGame(); |
| 52 | + |
| 53 | + } while (anotherGame); |
| 54 | + |
| 55 | + |
| 56 | + System.out.println("\nOK --- THANKS AGAIN."); |
| 57 | + } |
| 58 | + |
| 59 | + /** |
| 60 | + * Play one game starting with the first move from the user |
| 61 | + */ |
| 62 | + private static void playOneGame(Move firstMove) { |
| 63 | + boolean gameInProgress = true; |
| 64 | + Move userMove = firstMove; |
| 65 | + |
| 66 | + while (gameInProgress) { |
| 67 | + |
| 68 | + if (userMove.move == WINNING_POSITION) { |
| 69 | + //players wins |
| 70 | + printCongratulatoryMessage(); |
| 71 | + gameInProgress = false; |
| 72 | + } else { |
| 73 | + |
| 74 | + ComputerMove computerMove = getComputerMove(userMove); |
| 75 | + |
| 76 | + System.out.printf("COMPUTER MOVES TO SQUARE %d\n", computerMove.move); |
| 77 | + |
| 78 | + if (computerMove.move == WINNING_POSITION) { |
| 79 | + printComputerWins(); |
| 80 | + gameInProgress = false; |
| 81 | + } else { |
| 82 | + userMove = getValidUserMove(computerMove); |
| 83 | + |
| 84 | + if (userMove.move == FORFEIT_MOVE) { |
| 85 | + printWonByForfeit(); |
| 86 | + gameInProgress = false; |
| 87 | + } else if (userMove.move == WINNING_POSITION) { |
| 88 | + printCongratulatoryMessage(); |
| 89 | + gameInProgress = false; |
| 90 | + } |
| 91 | + } |
| 92 | + } |
| 93 | + } |
| 94 | + } |
| 95 | + |
| 96 | + /** |
| 97 | + * Get the user's first move |
| 98 | + */ |
| 99 | + private static Move getUserFirstMove() { |
| 100 | + boolean validMove; |
| 101 | + Move move; |
| 102 | + do { |
| 103 | + System.out.print("WHERE WOULD YOU LIKE TO START? "); |
| 104 | + int movePosition = scanner.nextInt(); |
| 105 | + move = new Move(movePosition); |
| 106 | + validMove = false; |
| 107 | + if (!isTopmostRowOrRightmostColumn(move)) { |
| 108 | + System.out.println("PLEASE READ THE DIRECTIONS AGAIN."); |
| 109 | + System.out.println("YOU HAVE BEGUN ILLEGALLY."); |
| 110 | + System.out.println(); |
| 111 | + } else { |
| 112 | + validMove = true; |
| 113 | + } |
| 114 | + scanner.nextLine(); |
| 115 | + } while (!validMove); |
| 116 | + return move; |
| 117 | + } |
| 118 | + |
| 119 | + /** |
| 120 | + * Prompt and get a valid move from the user. Uses the computer's latest move to validate the next move. |
| 121 | + */ |
| 122 | + private static Move getValidUserMove(ComputerMove latestComputerMove) { |
| 123 | + boolean validUserMove = false; |
| 124 | + Move userMove = null; |
| 125 | + while (!validUserMove) { |
| 126 | + userMove = getUserMove(); |
| 127 | + if (!validateUserMove(userMove, latestComputerMove)) { |
| 128 | + System.out.println("\nY O U C H E A T . . . TRY AGAIN"); |
| 129 | + } else { |
| 130 | + validUserMove = true; |
| 131 | + } |
| 132 | + } |
| 133 | + return userMove; |
| 134 | + } |
| 135 | + |
| 136 | + private static void printWonByForfeit() { |
| 137 | + System.out.println("\nIT LOOKS LIKE I HAVE WON BY FORFEIT.\n"); |
| 138 | + } |
| 139 | + |
| 140 | + private static boolean validateUserMove(Move userMove, ComputerMove computerMove) { |
| 141 | + if (userMove.move <= computerMove.move) { |
| 142 | + return false; |
| 143 | + } |
| 144 | + |
| 145 | + if (userMove.move == FORFEIT_MOVE || userMove.move == WINNING_POSITION) { |
| 146 | + return true; |
| 147 | + } |
| 148 | + |
| 149 | + int tensValueUser = userMove.move / 10; |
| 150 | + int unitsValueUser = userMove.move - (tensValueUser * 10); |
| 151 | + int unitsValueComputer = computerMove.u; |
| 152 | + int tensValueComputer = computerMove.t; |
| 153 | + int p = unitsValueUser - unitsValueComputer; |
| 154 | + if (p != 0) { |
| 155 | + if ((tensValueUser - tensValueComputer) != p) { |
| 156 | + return (tensValueUser - tensValueComputer) == 2 * p; |
| 157 | + } else { |
| 158 | + return true; |
| 159 | + } |
| 160 | + } else { |
| 161 | + int l = tensValueUser - tensValueComputer; |
| 162 | + return l > 0; |
| 163 | + } |
| 164 | + } |
| 165 | + |
| 166 | + private static Move getUserMove() { |
| 167 | + System.out.print("WHAT IS YOUR MOVE? "); |
| 168 | + int movePosition = scanner.nextInt(); |
| 169 | + scanner.nextLine(); |
| 170 | + return new Move(movePosition); |
| 171 | + } |
| 172 | + |
| 173 | + private static void printComputerWins() { |
| 174 | + System.out.println("\nNICE TRY, BUT IT LOOKS LIKE I HAVE WON."); |
| 175 | + System.out.println("THANKS FOR PLAYING.\n"); |
| 176 | + } |
| 177 | + |
| 178 | + private static boolean askForAnotherGame() { |
| 179 | + System.out.print("ANYONE ELSE CARE TO TRY? "); |
| 180 | + do { |
| 181 | + String response = Queen.scanner.nextLine(); |
| 182 | + if (response.equals("NO")) { |
| 183 | + return false; |
| 184 | + } else if (response.equals("YES")) { |
| 185 | + return true; |
| 186 | + } else { |
| 187 | + System.out.println("PLEASE ANSWER 'YES' OR 'NO'."); |
| 188 | + } |
| 189 | + } while (true); |
| 190 | + } |
| 191 | + |
| 192 | + private static boolean isTopmostRowOrRightmostColumn(Move move) { |
| 193 | + return move.unitsPlaceValue == 1 || move.unitsPlaceValue == move.tensPlaceValue; |
| 194 | + } |
| 195 | + |
| 196 | + private static ComputerMove getComputerMove(Move userMove) { |
| 197 | + int unitsValueUser = userMove.unitsPlaceValue; |
| 198 | + int tensValueUser = userMove.tensPlaceValue; |
| 199 | + |
| 200 | + List<Integer> moveRandomlyFromPositions = List.of(41, 44, 73, 75, 126, 127); |
| 201 | + |
| 202 | + if (moveRandomlyFromPositions.contains(userMove.move)) { |
| 203 | + //random move |
| 204 | + return getMovePositionInRandomDirection(unitsValueUser, tensValueUser); |
| 205 | + } else { |
| 206 | + |
| 207 | + for (int k = 7; k >= 1; k--) { |
| 208 | + // consider same row first, left-most position |
| 209 | + Optional<ComputerMove> move = evaluatePositionAndGetMove(unitsValueUser, tensValueUser + k); |
| 210 | + if (move.isPresent()) return move.get(); |
| 211 | + |
| 212 | + //try same column, bottom-most |
| 213 | + move = evaluatePositionAndGetMove(unitsValueUser + k, tensValueUser + k); |
| 214 | + if (move.isPresent()) return move.get(); |
| 215 | + |
| 216 | + //now left-most at the bottom-most |
| 217 | + move = evaluatePositionAndGetMove(unitsValueUser + k, tensValueUser + k + k); |
| 218 | + if (move.isPresent()) return move.get(); |
| 219 | + } |
| 220 | + |
| 221 | + //else move one step in a random direction |
| 222 | + return getMovePositionInRandomDirection(unitsValueUser, tensValueUser); |
| 223 | + } |
| 224 | + |
| 225 | + } |
| 226 | + |
| 227 | + private static Optional<ComputerMove> evaluatePositionAndGetMove(int newUnitsValue, int newTensValue) { |
| 228 | + EvaluationResult result = evaluateComputerMove(newUnitsValue, newTensValue); |
| 229 | + if (result.favourablePosition) { |
| 230 | + return Optional.of(new ComputerMove(result.move)); |
| 231 | + } |
| 232 | + return Optional.empty(); |
| 233 | + } |
| 234 | + |
| 235 | + private static EvaluationResult evaluateComputerMove(int u, int t) { |
| 236 | + int m = 10 * t + u; |
| 237 | + if (m == 158 || m == 127 || m == 126 || m == 75 || m == 73) { |
| 238 | + return new EvaluationResult(m, true); |
| 239 | + } else { |
| 240 | + return new EvaluationResult(m, false); |
| 241 | + } |
| 242 | + } |
| 243 | + |
| 244 | + private static void printCongratulatoryMessage() { |
| 245 | + System.out.println(); |
| 246 | + System.out.println("C O N G R A T U L A T I O N S . . ."); |
| 247 | + System.out.println(); |
| 248 | + System.out.println("YOU HAVE WON--VERY WELL PLAYED."); |
| 249 | + System.out.println("IT LOOKS LIKE I HAVE MET MY MATCH."); |
| 250 | + System.out.println("THANKS FOR PLAYING---I CAN'T WIN ALL THE TIME."); |
| 251 | + System.out.println(); |
| 252 | + |
| 253 | + } |
| 254 | + |
| 255 | + private static ComputerMove getMovePositionInRandomDirection(int u1, int t1) { |
| 256 | + double randomValue = Math.random(); |
| 257 | + |
| 258 | + if (randomValue > 0.6) { |
| 259 | + // Move directly down |
| 260 | + return new ComputerMove(calculateMove(u1, t1, 1, 1)); |
| 261 | + } else if (randomValue > 0.3) { |
| 262 | + // Move down left |
| 263 | + return new ComputerMove(calculateMove(u1, t1, 1, 2)); |
| 264 | + } else { |
| 265 | + // Move left |
| 266 | + return new ComputerMove(calculateMove(u1, t1, 0, 1)); |
| 267 | + } |
| 268 | + } |
| 269 | + |
| 270 | + private static int calculateMove(int u, int t, int uChange, int tChange) { |
| 271 | + int newU = u + uChange; |
| 272 | + int newT = t + tChange; |
| 273 | + return 10 * newT + newU; // Combine units and tens to corresponding position value |
| 274 | + } |
| 275 | + |
| 276 | + |
| 277 | + private static void printBoard() { |
| 278 | + System.out.println(); |
| 279 | + for (int A = 0; A <= 7; A++) { |
| 280 | + for (int B = 0; B <= 7; B++) { |
| 281 | + int I = 8 * A + B; |
| 282 | + System.out.printf(" %d ", S[I]); |
| 283 | + } |
| 284 | + System.out.println(); |
| 285 | + System.out.println(); |
| 286 | + System.out.println(); |
| 287 | + } |
| 288 | + System.out.println(); |
| 289 | + } |
| 290 | + |
| 291 | + private static void askAndShowInstructions() { |
| 292 | + do { |
| 293 | + System.out.print("DO YOU WANT INSTRUCTIONS? "); |
| 294 | + String wish = scanner.nextLine(); |
| 295 | + if (wish.equals("NO")) { |
| 296 | + break; |
| 297 | + } else if (wish.equals("YES")) { |
| 298 | + showInstructions(); |
| 299 | + break; |
| 300 | + } else { |
| 301 | + System.out.println("PLEASE ANSWER 'YES' OR 'NO'."); |
| 302 | + } |
| 303 | + } while (true); |
| 304 | + } |
| 305 | + |
| 306 | + private static void printWithTab(String message, int tab) { |
| 307 | + for (int i = 0; i < tab; i++) { |
| 308 | + System.out.print(" "); |
| 309 | + } |
| 310 | + System.out.println(message); |
| 311 | + } |
| 312 | + |
| 313 | + |
| 314 | + private static void showInstructions() { |
| 315 | + System.out.println("WE ARE GOING TO PLAY A GAME BASED ON ONE OF THE CHESS"); |
| 316 | + System.out.println("MOVES. OUR QUEEN WILL BE ABLE TO MOVE ONLY TO THE LEFT,"); |
| 317 | + System.out.println("DOWN, OR DIAGONALLY DOWN AND TO THE LEFT."); |
| 318 | + System.out.println(); |
| 319 | + System.out.println("THE OBJECT OF THE GAME IS TO PLACE THE QUEEN IN THE LOWER"); |
| 320 | + System.out.println("LEFT HAND SQUARE BY ALTERNATING MOVES BETWEEN YOU AND THE"); |
| 321 | + System.out.println("COMPUTER. THE FIRST ONE TO PLACE THE QUEEN THERE WINS."); |
| 322 | + System.out.println(); |
| 323 | + System.out.println("YOU GO FIRST AND PLACE THE QUEEN IN ANY ONE OF THE SQUARES"); |
| 324 | + System.out.println("ON THE TOP ROW OR RIGHT HAND COLUMN."); |
| 325 | + System.out.println("THAT WILL BE YOUR FIRST MOVE."); |
| 326 | + System.out.println("WE ALTERNATE MOVES."); |
| 327 | + System.out.println("YOU MAY FORFEIT BY TYPING '0' AS YOUR MOVE."); |
| 328 | + System.out.println("BE SURE TO PRESS THE RETURN KEY AFTER EACH RESPONSE."); |
| 329 | + System.out.println(); |
| 330 | + } |
| 331 | + |
| 332 | + |
| 333 | + private static class ComputerMove { |
| 334 | + private final int move; |
| 335 | + private final int u; |
| 336 | + private final int t; |
| 337 | + |
| 338 | + private ComputerMove(int move) { |
| 339 | + this.move = move; |
| 340 | + this.t = move / 10; |
| 341 | + this.u = move - (t * 10); |
| 342 | + } |
| 343 | + |
| 344 | + } |
| 345 | + |
| 346 | + private static class EvaluationResult { |
| 347 | + private final int move; |
| 348 | + private final boolean favourablePosition; |
| 349 | + |
| 350 | + public EvaluationResult(int move, boolean favourablePosition) { |
| 351 | + this.move = move; |
| 352 | + this.favourablePosition = favourablePosition; |
| 353 | + } |
| 354 | + |
| 355 | + |
| 356 | + } |
| 357 | + |
| 358 | + private static class Move { |
| 359 | + private final int move; |
| 360 | + private final int unitsPlaceValue; |
| 361 | + private final int tensPlaceValue; |
| 362 | + |
| 363 | + private Move(int move) { |
| 364 | + this.move = move; |
| 365 | + this.tensPlaceValue = move / 10; |
| 366 | + this.unitsPlaceValue = move % 10; |
| 367 | + } |
| 368 | + |
| 369 | + } |
| 370 | +} |
0 commit comments