Skip to content

Commit

Permalink
Merge pull request #913 from aldrinm/queen
Browse files Browse the repository at this point in the history
72. Queen ported to Java
  • Loading branch information
coding-horror committed Mar 24, 2024
2 parents 8b40cc8 + c9f9128 commit d824b73
Showing 1 changed file with 370 additions and 0 deletions.
370 changes: 370 additions & 0 deletions 72_Queen/java/Queen.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,370 @@
import java.util.List;
import java.util.Optional;
import java.util.Scanner;

/**
* QUEEN
* <p>
* 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<Integer> 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<ComputerMove> 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<ComputerMove> 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;
}

}
}

0 comments on commit d824b73

Please sign in to comment.