import java.io.*; public class GameState { private int pile1, pile2; public GameState(int forPile1, int forPile2) { pile1 = forPile1; pile2 = forPile2; } public int getSizeOfPile(int pileNumber) { if (pileNumber == 1) return pile1; else return pile2; } public boolean isOver() { return (getSizeOfPile(1) == 0) && (getSizeOfPile(2) == 0); } public void display() { System.out.println(" Pile 1: " + getSizeOfPile(1)); System.out.println(" Pile 2: " + getSizeOfPile(2)); } } public class Move { private int pile, nCoins; public Move(int forPile, int forNCoins) { pile = forPile; nCoins = forNCoins; } public int getPile() { return pile; } public int getNCoins() { return nCoins; } } public abstract class Player { abstract Move nextMove(GameState gameState); } public class ComputerPlayer extends Player { public Move nextMove(GameState gameState) { if (gameState.getSizeOfPile(1) > 0) return new Move(1, 1); else return new Move(2, 1); } } public class HumanPlayer extends Player { private int prompt(String text) { System.out.println(text); { try { String line = new BufferedReader(new InputStreamReader(System.in)) .readLine(); return Integer.parseInt(line); } catch (IOException exception) { System.err.println("An I/O exception occurred: " + exception.getMessage()); return 23; } } } public Move nextMove(GameState gameState) { int pile = prompt("Which pile will you remove from?"); int nCoins = prompt("How many coins do you want to remove?"); return new Move(pile, nCoins); } } public class Nim { private static final Player humanPlayer = new HumanPlayer(), computerPlayer = new ComputerPlayer(); public void playNim(GameState gameState, Player player) { gameState.display(); while (!gameState.isOver()) { Move move = player.nextMove(gameState); announceMove(player, move); gameState = applyMove(move, gameState); player = otherPlayer(player); gameState.display(); } announceWinner(gameState, player); } private Player otherPlayer(Player player) { if (player == humanPlayer) return computerPlayer; else return humanPlayer; } public GameState applyMove(Move move, GameState gameState) { if (move.getPile() == 1) return new GameState(gameState.getSizeOfPile(1) - move.getNCoins(), gameState.getSizeOfPile(2)); else return new GameState(gameState.getSizeOfPile(1), gameState.getSizeOfPile(2) - move.getNCoins()); } private void announceMove(Player player, Move move) { if (player == humanPlayer) System.out.print("You"); else System.out.print("I"); System.out.print(" take "); System.out.print(move.getNCoins()); System.out.print(" coins from pile "); System.out.print(move.getPile()); System.out.println("."); } private void announceWinner(GameState gameState, Player player) { Player winner = otherPlayer(player); if (winner == humanPlayer) System.out.println("You win. Congratulations."); else System.out.println("You lose. Better luck next time."); } public static void main(String[] args) { new Nim().playNim(new GameState(4, 5), humanPlayer); } }