The goal of this game is to not say the number 21.
Rules:
- You must only say numbers consecutive to the previous said number.
- You may say 1, 2, or 3 numbers at a time.
For example:
Player 1 says 1
Player 2 says 2, 3
Player 1 says 4, 5, 6
Player 2 says 7, 8
And so on...
You will be playing AI, and you will start. Try your best, but no matter how hard you try, you will lose!
I will personally give the one who can find a way to beat the AI (i.e. a bug in the program) with a 50 rep bounty.
Main.java
public class Main {
private static final int END = 21;
public static void main(String[] args) {
Game game = new Game(END);
game.startGame();
}
}
Game.java
import java.util.Scanner;
import java.util.regex.Pattern;
public class Game {
private static final Pattern NUMBER_LIST_PATTERN = Pattern.compile("(\\d+,)*\\d+");
private static final String HELP = "help";
private static final int MAX_NUMS_PER_TURN = 3;
private final int end;
public Game(int end) {
if (end % 4 != 1) {
throw new IllegalArgumentException("Nice try, this number will fail the AI.");
}
this.end = end;
}
public void startGame() {
Scanner scanner = new Scanner(System.in);
AI impossibleComputer = new AI();
displayHelp();
do {
boolean hasLost = false;
int previousNumber = 0;
do {
int[] numbers = getNumbers(scanner, previousNumber);
if (contains(numbers, end)) {
System.out.println("You lose!");
hasLost = true;
} else {
previousNumber = printAINumbers(impossibleComputer.getNextNumbers(numbers[numbers.length - 1]));
}
} while (!hasLost);
} while (doAgain(scanner));
System.out.println("Thanks for playing!");
}
private void displayHelp() {
System.out.println("The goal of this game is to not say the number 21.\n\n" + "Rules:\n"
+ "1. You must only say numbers consecutive to the previous said number.\n"
+ "2. You may say 1, 2, or 3 numbers at a time.\n\n" + "For example:\n\n" + "\tPlayer 1 says 1\n"
+ "\tPlayer 2 says 2, 3\n" + "\tPlayer 1 says 4, 5, 6\n" + "\tPlayer 2 says 7, 8\n"
+ "\tAnd so on...\n\n"
+ "You will be playing AI, and you will start. Try your best, but no matter how hard you try, you will lose!\n");
}
private int[] getNumbers(Scanner scanner, int previousNumber) {
System.out
.println("Enter your numbers, separated by commas only (e.g. \"1,2,3\"), or enter \"help\" for help.\n"
+ "Note that if you enter more than three numbers, this program will ignore the ones after the third one.");
while (true) {
String input = scanner.nextLine().trim();
if (input.equals(HELP)) {
displayHelp();
return null;
} else {
if (NUMBER_LIST_PATTERN.matcher(input).matches()) {
int[] result = toIntArray(input);
if (result != null && result[0] == previousNumber + 1) {
return result;
}
}
System.out.println("Oops, illegal input. Try again:");
}
}
}
private int[] toIntArray(String input) {
String[] array = input.split(",");
int length = array.length;
int[] result = new int[length > MAX_NUMS_PER_TURN ? MAX_NUMS_PER_TURN : length];
for (int i = 0; i < length && i < MAX_NUMS_PER_TURN; i++) {
result[i] = Integer.parseInt(array[i]);
if (i != 0 && result[i] != result[i - 1] + 1) {
return null;
}
}
return result;
}
private boolean contains(int[] numbers, int number) {
for (int num : numbers) {
if (num == number) {
return true;
}
}
return false;
}
private int printAINumbers(int[] nextNumbers) {
System.out.print("The AI says: ");
for (int number : nextNumbers) {
System.out.print(number + " ");
}
System.out.println();
return nextNumbers[nextNumbers.length - 1];
}
private boolean doAgain(Scanner scanner) {
System.out.println("Do you want to play again?");
while (true) {
char in = Character.toUpperCase(scanner.next().charAt(0));
if (in == 'Y') {
return true;
} else if (in == 'N') {
return false;
}
System.out.println("Oops, that was not valid input. Try again: ");
}
}
}
Now comes the part to reveal the secret...
AI.java
public class AI {
public int[] getNextNumbers(int lastNumber) {
if (lastNumber % 4 == 0) {
return new int[] {lastNumber + 1};
}
return list(lastNumber + 1, 4 * ((int) (lastNumber / 4) + 1));
}
private int[] list(int x, int y) {
int[] result = new int[y - x + 1];
for (int i = 0; x + i <= y; i++) {
result[i] = x + i;
}
return result;
}
}
If you don't understand why this works, all the AI does is counts up to the next multiple of 4. Why does this work? Well, this is what happens:
Player: 1, [2], [3]
AI: [2], [3], 4
Player: 5, [6], [7]
AI: [6], [7], 8
Player: 9, [10], [11]
AI: [10], [11], 12
Player: 13, [14], [15]
AI: [14], [15], 16
Player: 17, [18], [19]
AI: [18], [19], 20
Player: 21
Anything in the square brackets, if not said by the player, will be said by AI. No matter how you play, the AI will win (as long as it starts).
Concerns:
- Am I doing well OOP-wise?
- Are my variable names good?
- And as usual, anything else?