import java.util.Random; import java.util.Scanner; class Nim { private static final int NUM_PILES = 5; private static final int MAX_PILE_HEIGHT = 6; public static void main(String[] args) { // storage for piles; each element has a pile count int[] piles = new int[NUM_PILES]; // allocate piles setupGame(piles); // current player int playerNum = 1; // init Scanner Scanner s = new Scanner(System.in); // keep playing while we're not done while(!done(piles)) { // print board printPiles(piles); // ask the user to take their turn int pile; int rem; boolean isValid = false; do { pile = promptMovePile(playerNum, s); rem = promptMoveNum(playerNum, s); // is the move valid? isValid = validMove(piles, pile, rem); // if bad, complain if (!isValid) { System.out.println("Invalid move, player " + playerNum + "!"); continue; } // otherwise update board piles[pile] = piles[pile] - rem; } while (!isValid); // flip the player playerNum = flipPlayer(playerNum); } // somebody won! who? playerNum = flipPlayer(playerNum); System.out.println("Player " + playerNum + " wins!"); } /** * Flip the player number. * @param The current player. * @returns The new player. */ public static int flipPlayer(int n) { if (n == 1) { return 2; } else { return 1; } } /** * Allocates a random number, but at least one, * matchstick to each pile on the board. Updates * the board in place. */ public static void setupGame(int[] piles) { Random r = new Random(); for (int i = 0; i < piles.length; i++) { piles[i] = r.nextInt(MAX_PILE_HEIGHT - 1) + 1; } } /** * Print out the game board. * @param piles Game state. */ public static void printPiles(int[] piles) { for (int i = 0; i < piles.length; i++) { System.out.print(i + ": "); for (int j = 0; j < piles[i]; j++) { System.out.print("|"); } System.out.println(); } } /** * Is the game done? * @param piles Game state. * @returns True iff the game is done. */ public static boolean done(int[] piles) { for (int i = 0; i < piles.length; i++) { if (piles[i] != 0) { return false; } } return true; } /** * Is the move valid given the game board? * @param piles Game state. * @param pile The chosen pile. * @param rem The number to remove. * @returns True iff the move is valid. */ public static boolean validMove(int[] piles, int pile, int rem) { // Did the user choose a valid pile? if (pile < 0 || pile >= piles.length) { return false; } // Did the user try to remove more than was in the pile? if (rem > piles[pile]) { return false; } // Did the user try to remove nothing? if (rem < 1) { return false; } return true; } /** * Prompt player n for which pile they want to * remove matchsticks from. * @param n player number * @param c Scanner * @returns The chosen pile. */ public static int promptMovePile(int n, Scanner s) { while(true) { try { System.out.print("Player " + n + ", which pile? "); return s.nextInt(); } catch (Exception e) { System.out.println("Bad input. Try again."); s.next(); } } } /** * Prompt player n for how many matchsticks to * remove. * @param n player number * @param c Scanner * @returns The number to remove. */ public static int promptMoveNum(int n, Scanner s) { System.out.print("Player " + n + ", how many to remove? "); return s.nextInt(); } }