From c9f91288f00b58db2ff3990d1feec072cb4201a5 Mon Sep 17 00:00:00 2001 From: Aldrin Misquitta Date: Sun, 24 Mar 2024 16:12:10 +0000 Subject: [PATCH] 72. Queen ported to Java --- 72_Queen/java/Queen.java | 370 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 370 insertions(+) create mode 100644 72_Queen/java/Queen.java diff --git a/72_Queen/java/Queen.java b/72_Queen/java/Queen.java new file mode 100644 index 000000000..7dfb6353c --- /dev/null +++ b/72_Queen/java/Queen.java @@ -0,0 +1,370 @@ +import java.util.List; +import java.util.Optional; +import java.util.Scanner; + +/** + * QUEEN + *

+ * Converted from BASIC to Java by Aldrin Misquitta (@aldrinm) + */ +public class Queen { + + public static final int WINNING_POSITION = 158; + public static final int FORFEIT_MOVE = 0; + + // @formatter:off + private static final int[] S = { + 81, 71, 61, 51, 41, 31, 21, 11, + 92, 82, 72, 62, 52, 42, 32, 22, + 103, 93, 83, 73, 63, 53, 43, 33, + 114, 104, 94, 84, 74, 64, 54, 44, + 125, 115, 105, 95, 85, 75, 65, 55, + 136, 126, 116, 106, 96, 86, 76, 66, + 147, 137, 127, 117, 107, 97, 87, 77, + 158, 148, 138, 128, 118, 108, 98, 88 + }; + // @formatter:on + + private static final Scanner scanner = new Scanner(System.in); + + + public static void main(String[] args) { + printWithTab("QUEEN", 33); + printWithTab("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY", 15); + System.out.println("\n\n"); + + askAndShowInstructions(); + + boolean anotherGame; + do { + printBoard(); + + Move firstMove = getUserFirstMove(); + if (firstMove.move == 0) { + printWonByForfeit(); + } + + if (isTopmostRowOrRightmostColumn(firstMove)) { + playOneGame(firstMove); + } + + anotherGame = askForAnotherGame(); + + } while (anotherGame); + + + System.out.println("\nOK --- THANKS AGAIN."); + } + + /** + * Play one game starting with the first move from the user + */ + private static void playOneGame(Move firstMove) { + boolean gameInProgress = true; + Move userMove = firstMove; + + while (gameInProgress) { + + if (userMove.move == WINNING_POSITION) { + //players wins + printCongratulatoryMessage(); + gameInProgress = false; + } else { + + ComputerMove computerMove = getComputerMove(userMove); + + System.out.printf("COMPUTER MOVES TO SQUARE %d\n", computerMove.move); + + if (computerMove.move == WINNING_POSITION) { + printComputerWins(); + gameInProgress = false; + } else { + userMove = getValidUserMove(computerMove); + + if (userMove.move == FORFEIT_MOVE) { + printWonByForfeit(); + gameInProgress = false; + } else if (userMove.move == WINNING_POSITION) { + printCongratulatoryMessage(); + gameInProgress = false; + } + } + } + } + } + + /** + * Get the user's first move + */ + private static Move getUserFirstMove() { + boolean validMove; + Move move; + do { + System.out.print("WHERE WOULD YOU LIKE TO START? "); + int movePosition = scanner.nextInt(); + move = new Move(movePosition); + validMove = false; + if (!isTopmostRowOrRightmostColumn(move)) { + System.out.println("PLEASE READ THE DIRECTIONS AGAIN."); + System.out.println("YOU HAVE BEGUN ILLEGALLY."); + System.out.println(); + } else { + validMove = true; + } + scanner.nextLine(); + } while (!validMove); + return move; + } + + /** + * Prompt and get a valid move from the user. Uses the computer's latest move to validate the next move. + */ + private static Move getValidUserMove(ComputerMove latestComputerMove) { + boolean validUserMove = false; + Move userMove = null; + while (!validUserMove) { + userMove = getUserMove(); + if (!validateUserMove(userMove, latestComputerMove)) { + System.out.println("\nY O U C H E A T . . . TRY AGAIN"); + } else { + validUserMove = true; + } + } + return userMove; + } + + private static void printWonByForfeit() { + System.out.println("\nIT LOOKS LIKE I HAVE WON BY FORFEIT.\n"); + } + + private static boolean validateUserMove(Move userMove, ComputerMove computerMove) { + if (userMove.move <= computerMove.move) { + return false; + } + + if (userMove.move == FORFEIT_MOVE || userMove.move == WINNING_POSITION) { + return true; + } + + int tensValueUser = userMove.move / 10; + int unitsValueUser = userMove.move - (tensValueUser * 10); + int unitsValueComputer = computerMove.u; + int tensValueComputer = computerMove.t; + int p = unitsValueUser - unitsValueComputer; + if (p != 0) { + if ((tensValueUser - tensValueComputer) != p) { + return (tensValueUser - tensValueComputer) == 2 * p; + } else { + return true; + } + } else { + int l = tensValueUser - tensValueComputer; + return l > 0; + } + } + + private static Move getUserMove() { + System.out.print("WHAT IS YOUR MOVE? "); + int movePosition = scanner.nextInt(); + scanner.nextLine(); + return new Move(movePosition); + } + + private static void printComputerWins() { + System.out.println("\nNICE TRY, BUT IT LOOKS LIKE I HAVE WON."); + System.out.println("THANKS FOR PLAYING.\n"); + } + + private static boolean askForAnotherGame() { + System.out.print("ANYONE ELSE CARE TO TRY? "); + do { + String response = Queen.scanner.nextLine(); + if (response.equals("NO")) { + return false; + } else if (response.equals("YES")) { + return true; + } else { + System.out.println("PLEASE ANSWER 'YES' OR 'NO'."); + } + } while (true); + } + + private static boolean isTopmostRowOrRightmostColumn(Move move) { + return move.unitsPlaceValue == 1 || move.unitsPlaceValue == move.tensPlaceValue; + } + + private static ComputerMove getComputerMove(Move userMove) { + int unitsValueUser = userMove.unitsPlaceValue; + int tensValueUser = userMove.tensPlaceValue; + + List moveRandomlyFromPositions = List.of(41, 44, 73, 75, 126, 127); + + if (moveRandomlyFromPositions.contains(userMove.move)) { + //random move + return getMovePositionInRandomDirection(unitsValueUser, tensValueUser); + } else { + + for (int k = 7; k >= 1; k--) { + // consider same row first, left-most position + Optional move = evaluatePositionAndGetMove(unitsValueUser, tensValueUser + k); + if (move.isPresent()) return move.get(); + + //try same column, bottom-most + move = evaluatePositionAndGetMove(unitsValueUser + k, tensValueUser + k); + if (move.isPresent()) return move.get(); + + //now left-most at the bottom-most + move = evaluatePositionAndGetMove(unitsValueUser + k, tensValueUser + k + k); + if (move.isPresent()) return move.get(); + } + + //else move one step in a random direction + return getMovePositionInRandomDirection(unitsValueUser, tensValueUser); + } + + } + + private static Optional evaluatePositionAndGetMove(int newUnitsValue, int newTensValue) { + EvaluationResult result = evaluateComputerMove(newUnitsValue, newTensValue); + if (result.favourablePosition) { + return Optional.of(new ComputerMove(result.move)); + } + return Optional.empty(); + } + + private static EvaluationResult evaluateComputerMove(int u, int t) { + int m = 10 * t + u; + if (m == 158 || m == 127 || m == 126 || m == 75 || m == 73) { + return new EvaluationResult(m, true); + } else { + return new EvaluationResult(m, false); + } + } + + private static void printCongratulatoryMessage() { + System.out.println(); + System.out.println("C O N G R A T U L A T I O N S . . ."); + System.out.println(); + System.out.println("YOU HAVE WON--VERY WELL PLAYED."); + System.out.println("IT LOOKS LIKE I HAVE MET MY MATCH."); + System.out.println("THANKS FOR PLAYING---I CAN'T WIN ALL THE TIME."); + System.out.println(); + + } + + private static ComputerMove getMovePositionInRandomDirection(int u1, int t1) { + double randomValue = Math.random(); + + if (randomValue > 0.6) { + // Move directly down + return new ComputerMove(calculateMove(u1, t1, 1, 1)); + } else if (randomValue > 0.3) { + // Move down left + return new ComputerMove(calculateMove(u1, t1, 1, 2)); + } else { + // Move left + return new ComputerMove(calculateMove(u1, t1, 0, 1)); + } + } + + private static int calculateMove(int u, int t, int uChange, int tChange) { + int newU = u + uChange; + int newT = t + tChange; + return 10 * newT + newU; // Combine units and tens to corresponding position value + } + + + private static void printBoard() { + System.out.println(); + for (int A = 0; A <= 7; A++) { + for (int B = 0; B <= 7; B++) { + int I = 8 * A + B; + System.out.printf(" %d ", S[I]); + } + System.out.println(); + System.out.println(); + System.out.println(); + } + System.out.println(); + } + + private static void askAndShowInstructions() { + do { + System.out.print("DO YOU WANT INSTRUCTIONS? "); + String wish = scanner.nextLine(); + if (wish.equals("NO")) { + break; + } else if (wish.equals("YES")) { + showInstructions(); + break; + } else { + System.out.println("PLEASE ANSWER 'YES' OR 'NO'."); + } + } while (true); + } + + private static void printWithTab(String message, int tab) { + for (int i = 0; i < tab; i++) { + System.out.print(" "); + } + System.out.println(message); + } + + + private static void showInstructions() { + System.out.println("WE ARE GOING TO PLAY A GAME BASED ON ONE OF THE CHESS"); + System.out.println("MOVES. OUR QUEEN WILL BE ABLE TO MOVE ONLY TO THE LEFT,"); + System.out.println("DOWN, OR DIAGONALLY DOWN AND TO THE LEFT."); + System.out.println(); + System.out.println("THE OBJECT OF THE GAME IS TO PLACE THE QUEEN IN THE LOWER"); + System.out.println("LEFT HAND SQUARE BY ALTERNATING MOVES BETWEEN YOU AND THE"); + System.out.println("COMPUTER. THE FIRST ONE TO PLACE THE QUEEN THERE WINS."); + System.out.println(); + System.out.println("YOU GO FIRST AND PLACE THE QUEEN IN ANY ONE OF THE SQUARES"); + System.out.println("ON THE TOP ROW OR RIGHT HAND COLUMN."); + System.out.println("THAT WILL BE YOUR FIRST MOVE."); + System.out.println("WE ALTERNATE MOVES."); + System.out.println("YOU MAY FORFEIT BY TYPING '0' AS YOUR MOVE."); + System.out.println("BE SURE TO PRESS THE RETURN KEY AFTER EACH RESPONSE."); + System.out.println(); + } + + + private static class ComputerMove { + private final int move; + private final int u; + private final int t; + + private ComputerMove(int move) { + this.move = move; + this.t = move / 10; + this.u = move - (t * 10); + } + + } + + private static class EvaluationResult { + private final int move; + private final boolean favourablePosition; + + public EvaluationResult(int move, boolean favourablePosition) { + this.move = move; + this.favourablePosition = favourablePosition; + } + + + } + + private static class Move { + private final int move; + private final int unitsPlaceValue; + private final int tensPlaceValue; + + private Move(int move) { + this.move = move; + this.tensPlaceValue = move / 10; + this.unitsPlaceValue = move % 10; + } + + } +}