/* Nim game */ /* Author: Carsten Schuermann */ /* Rules: There are two stacks of matches and two player. The game proceeds in turns. At each turn, each of the players can pick one or more matches from *one* stack. However takes the last match looses. */ import java.util.ArrayList; import java.io.IOException; import java.io.InputStreamReader; import java.io.BufferedReader; import java.util.Iterator; class Move { int x; /* How many matches from the first stack */ int y; /* How many matches from the second stack */ /* x=0 && y>0 || x>0 && y =0 */ Move (int x, int y) { this.x = x; this.y = y; } } class IllegalMove extends Exception { Move m; IllegalMove (Move m) { this.m = m; } } class Board { int n; /* the size of the first stack of matches */ int m; /* the size of the second stack of matches */ Move x; /* x = null: initial board */ /* x <> null: the move that got us to the current configuration */ Board (int n, int m, Move x) { this.n = m; this.m = n; this.x = x; } void insert (Move m) throws IllegalMove { if (this.isValid (m)) { this.n = this.n - m.x; this.m = this.m - m.y; } else { throw (new IllegalMove (m)); } } Boolean isValid (Move m) { if (m.x <= this.n && m.y ==0 || m.y <= this.m && m.x == 0) {return true;} else {return false;} } Boolean win () { if (n == 0 && m == 0) {return true;} else{return false;} } void print () { for (int i=1; i <= n; i++) {System.out.print ("|");} System.out.println (""); for (int i=1; i <= m; i++) {System.out.print ("|");} System.out.println (""); System.out.println (""); } } interface Player { void init (Board b); String name (); Move move (); void inform (Move m); } class Carsten implements Player{ BufferedReader console = new BufferedReader(new InputStreamReader(System.in)); public void init (Board b) {} public String name () { return "Carsten";} public Move move () { try { int i = Integer.parseInt(console.readLine()); int j = Integer.parseInt(console.readLine()); return (new Move (i, j)); } catch (Exception exn) { return (this.move ()); } } public void inform (Move m) {} } class Stage { ArrayList boards = new ArrayList (); Move best; int depth; Boolean gameOver; Stage (Board b, int depth) { this.depth = depth; if (b.win ()) {this.gameOver = true;} else { this.gameOver = false; for (int i=1; i <= b.n; i++) { boards.add (new Board (b.n - i, b.m , new Move (i, 0))); } for (int j=1; j <= b.m; j++) { boards.add (new Board (b.n, b.m - j, new Move (0, j))); } } } double max (double a, double b) { if (this.depth < 0) {return 0.0;} if (this.gameOver) {return 1.0;} else { double newa = a; best = boards.get (0).x; for (Iterator i = boards.iterator (); i.hasNext (); ) { Board board = i.next (); double n = new Stage (board, this.depth-1).min (a, b); if (newa < n) {newa = n; best = board.x;} if (b <= newa) {return newa;} } return newa; } } double min (double a, double b) { if (this.depth < 0) {return 0.0;} if (this.gameOver) {return -1.0;} else { double newb = b; best = boards.get (0).x; for (Iterator i = boards.iterator (); i.hasNext (); ) { Board board = i.next(); double n = new Stage (board, this.depth-1).max (a, b); if (n < newb) {newb = n; best=board.x;} if (newb <= a) {return newb;} } return newb; } } } class AutomaticCarsten implements Player { Board board; public String name () { return "Automatic Carsten";} public void init (Board b) { this.board = new Board(b.n, b.m, null); } public Move move () { Stage start= new Stage (board, 5); start.max (-100.0, 100.0); try {board.insert (start.best);} catch (IllegalMove exn) {}; return (start.best); } public void inform (Move i) { try {board.insert (i);} catch (IllegalMove exn) {}; } } class Nim { Board b; Player p1; /* p1 plays true */ Player p2; /* p2 plays false */ Nim (Player p1, Player p2, int n, int m) { b = new Board (n, m, null); this.p1 = p1; this.p2 = p2; p1.init(b); p2.init(b); } void illegal (String s, Move m) { System.out.println ("Illegal Move: Player " + s + " moved to (" + m.x + ", " + m.y +")"); } int move (Boolean player) { b.print (); if (player) {System.out.println (p1.name() + " please make your move");} else {System.out.println (p2.name() + " please make your move");} if (player) { Move m = p1.move (); try {b.insert (m); } catch (IllegalMove exn) {this.illegal (p1.name(), exn.m); return 2;} if (b.win ()) {System.out.println ("Winner:" + p2.name()); return 1;} p2.inform (m); } else { Move m = p2.move (); try {b.insert (m);} catch (IllegalMove exn) {this.illegal (p2.name(), exn.m); return 1;} if (b.win ()) {System.out.println ("Winner:" + p1.name()); return 2;} p1.inform (m); }; return (move (! player)); } int run () { int result = this.move (true); b.print (); return (result); } public static void main (String [] args) { Nim game = new Nim (new Carsten (), new AutomaticCarsten (), 10,10); game.run (); } }