diff --git a/64 Nicomachus/java/src/Nicomachus.java b/64 Nicomachus/java/src/Nicomachus.java new file mode 100644 index 00000000..53bbbedd --- /dev/null +++ b/64 Nicomachus/java/src/Nicomachus.java @@ -0,0 +1,185 @@ +import java.util.Arrays; +import java.util.Scanner; + +/** + * Game of Nichomachus + *

+ * Based on the Basic game of Nichomachus here + * https://github.com/coding-horror/basic-computer-games/blob/main/64%20Nicomachus/nicomachus.bas + *

+ * Note: The idea was to create a version of the 1970's Basic game in Java, without introducing + * new features - no additional text, error checking, etc has been added. + */ + +public class Nicomachus { + + public static final long TWO_SECONDS = 2000; + + // Used for keyboard input + private final Scanner kbScanner; + + private enum GAME_STATE { + START_GAME, + GET_INPUTS, + RESULTS, + PLAY_AGAIN + } + + int remainderNumberDividedBy3; + int remainderNumberDividedBy5; + int remainderNumberDividedBy7; + + // Current game state + private GAME_STATE gameState; + + public Nicomachus() { + kbScanner = new Scanner(System.in); + gameState = GAME_STATE.START_GAME; + } + + /** + * Main game loop + */ + public void play() throws Exception { + + do { + switch (gameState) { + + case START_GAME: + intro(); + gameState = GAME_STATE.GET_INPUTS; + break; + + case GET_INPUTS: + + System.out.println("PLEASE THINK OF A NUMBER BETWEEN 1 AND 100."); + remainderNumberDividedBy3 = displayTextAndGetNumber("YOUR NUMBER DIVIDED BY 3 HAS A REMAINDER OF? "); + remainderNumberDividedBy5 = displayTextAndGetNumber("YOUR NUMBER DIVIDED BY 5 HAS A REMAINDER OF? "); + remainderNumberDividedBy7 = displayTextAndGetNumber("YOUR NUMBER DIVIDED BY 7 HAS A REMAINDER OF? "); + + gameState = GAME_STATE.RESULTS; + + case RESULTS: + System.out.println("LET ME THINK A MOMENT..."); + // Simulate the basic programs for/next loop to delay things. + // Here we are sleeping for one second. + Thread.sleep(TWO_SECONDS); + + // Calculate the number the player was thinking of. + int answer = (70 * remainderNumberDividedBy3) + (21 * remainderNumberDividedBy5) + + (15 * remainderNumberDividedBy7); + + // Something similar was in the original basic program + // (to test if the answer was 105 and deducting 105 until it was <= 105 + while (answer > 105) { + answer -= 105; + } + + do { + String input = displayTextAndGetInput("YOUR NUMBER WAS " + answer + ", RIGHT? "); + if (yesEntered(input)) { + System.out.println("HOW ABOUT THAT!!"); + break; + } else if (noEntered(input)) { + System.out.println("I FEEL YOUR ARITHMETIC IS IN ERROR."); + break; + } else { + System.out.println("EH? I DON'T UNDERSTAND '" + input + "' TRY 'YES' OR 'NO'."); + } + } while (true); + + gameState = GAME_STATE.PLAY_AGAIN; + break; + + case PLAY_AGAIN: + System.out.println("LET'S TRY ANOTHER"); + gameState = GAME_STATE.GET_INPUTS; + break; + } + + // Original basic program looped until CTRL-C + } while (true); + } + + private void intro() { + System.out.println(addSpaces(33) + "NICOMA"); + System.out.println(addSpaces(15) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"); + System.out.println(); + System.out.println("BOOMERANG PUZZLE FROM ARITHMETICA OF NICOMACHUS -- A.D. 90!"); + System.out.println(); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * Converts input to an Integer + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private int displayTextAndGetNumber(String text) { + return Integer.parseInt(displayTextAndGetInput(text)); + } + + /* + * Print a message on the screen, then accept input from Keyboard. + * + * @param text message to be displayed on screen. + * @return what was typed by the player. + */ + private String displayTextAndGetInput(String text) { + System.out.print(text); + return kbScanner.nextLine(); + } + + /** + * Return a string of x spaces + * + * @param spaces number of spaces required + * @return String with number of spaces + */ + private String addSpaces(int spaces) { + char[] spacesTemp = new char[spaces]; + Arrays.fill(spacesTemp, ' '); + return new String(spacesTemp); + } + + /** + * Checks whether player entered Y or YES to a question. + * + * @param text player string from kb + * @return true of Y or YES was entered, otherwise false + */ + private boolean yesEntered(String text) { + return stringIsAnyValue(text, "Y", "YES"); + } + + /** + * Checks whether player entered N or NO to a question. + * + * @param text player string from kb + * @return true of N or NO was entered, otherwise false + */ + private boolean noEntered(String text) { + return stringIsAnyValue(text, "N", "NO"); + } + + /** + * Check whether a string equals one of a variable number of values + * Useful to check for Y or YES for example + * Comparison is case insensitive. + * + * @param text source string + * @param values a range of values to compare against the source string + * @return true if a comparison was found in one of the variable number of strings passed + */ + private boolean stringIsAnyValue(String text, String... values) { + + return Arrays.stream(values).anyMatch(str -> str.equalsIgnoreCase(text)); + } + + public static void main(String[] args) throws Exception { + + Nicomachus nicomachus = new Nicomachus(); + nicomachus.play(); + } +} \ No newline at end of file