Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

72. Queen ported to Java #913

Merged
merged 1 commit into from
Mar 24, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}

}
}
Loading