Class: Spinner Responsibilities: getSpin() Collaborations: none Class: Board Responsibilities: getCellAt() checkWinningPosition() Collaborations: Cell Class: Player Responsibilities: takeATurn() checkWon() X getPosition() Collaborations: Spinner Board Cell Class: Cell Responsibilities: getDestination() Collaborations: none Class: Game Responsibilities: X checkEnd() ?? X getCurrentPlayer() startPlaying(); Collaborations: Player
public class Board {
private Cell cells[];
public Board() {
cells = new Cell[101];
for (int i=1;i < =100;i++)
cells[i] = new Cell(i);
cells[1].setDestination(38);
cells[4].setDestination(14);
...
}
public Cell getCellAt(int i) {
if ((i < 1) || (i > 100) ) return null;
return cells[i];
}
public boolean checkWinningPosition(int i) {
return (i==100);
}
}
Need to add the following responsibility to Cell: setDestination();
public class Game {
private Board board;
private Player players[];
private int numPlayers;
private int currentPlayerIndex;
private int moveCount;
public Game(int numPlayers) {
this.numPlayers = numPlayers;
board = new Board();
players = new Player[numPlayers];
for (int i=0;i < numPlayers;i++)
players[i] = new Player(board,"Player "+i);
}
public void startPlaying() {
currentPlayerIndex = numPlayers;
moveCount = 0;
while( ! players[currentPlayerIndex].checkWinningPosition() ) {
moveCount++;
currentPlayerIndex = (currentPlayerIndex + 1) % numPlayers;
players[currentPlayerIndex].takeATurn();
}
System.out.println("Player "+currentPlayerIndex+" won on "+
moveCount+" moves");
}
}
public class Player {
private int currentPosition;
private String name;
private Cell newCell;
private Board board;
public Player(Board board, String name) {
this.board = board;
this.name = name;
currentPosition = 0;
}
public void takeATurn() {
newCell = board.getCellAt(currentPosition + Spinner.getSpin());
if (newCell == null) return;
currentPosition = newCell.getDestination();
}
public boolean checkWon() {
return board.checkWon(currentPosition);
}
}
Note: getSpin is a static method of the class Spinner.
Revisions to CRC cards after implementation:
Class: Spinner no change (getSpin made static) Responsibilities: getSpin() Collaborations: none Class: Board no change Responsibilities: getCellAt() checkWinningPosition() Collaborations: Cell Class: Player Added responsibility: getName() Responsibilities: takeATurn() checkWon() X getPosition() Collaborations: Spinner Board Cell Class: Cell Added responsibility: setDestination() Responsibilities: getDestination() Collaborations: none Class: Game Added responsibilities: getMoves(), getWinner() Responsibilities: Added Collaboration: Board X checkEnd() ?? X getCurrentPlayer() startPlaying(); Collaborations: Player
Test Program 1:
class Tester {
public static void main(String args[]) {
Game g;
g = new Game(2);
g.startPlaying();
System.out.println("Player "+g.getWinner() + " won in "+
g.getMoves()+" moves.");
}
}
Example output:
Player Player 1 won in 32 moves.
Test Program 2:
class TestMany {
public static void main(String args[]) {
Game g;
int numGames;
double sumMoves;
double averageMoves;
int numMoves;
int minMoves;
int maxMoves;
long startTime;
long endTime;
long totalTime;
if (args.length != 1) {
System.out.println("Usage: TestMany n\n");
return;
}
numGames = Integer.parseInt(args[0]);
sumMoves = 0;
numMoves = 0;
minMoves = Integer.MAX_VALUE;
maxMoves = 0;
System.out.println("Starting simulation of "+numGames+" games:");
startTime = System.currentTimeMillis();
for (int i=0;i < numGames;i++) {
g = new Game(2);
g.startPlaying();
numMoves = g.getMoves();
if (minMoves > numMoves)
minMoves = numMoves;
if (maxMoves < numMoves)
maxMoves = numMoves;
sumMoves += numMoves;
}
endTime = System.currentTimeMillis();
totalTime = endTime - startTime;
averageMoves = sumMoves/numGames;
System.out.println("Statistics generated after "+numGames+ " games:");
System.out.println("Time for simulation: "+(totalTime/1000.0)+" seconds");
System.out.println("Minimum number of moves is "+minMoves);
System.out.println("Maximum number of moves is "+maxMoves);
System.out.println("Average number of moves is "+averageMoves);
}
}
Sample output:
java -version java version "1.2.1" Solaris VM (build Solaris_JDK_1.2.1_04, native threads, sunwjit) java TestMany 1000000 Starting simulation of 1000000 games: Statistics generated after 1000000 games: Time for simulation: 143.602 seconds Minimum number of moves is 13 Maximum number of moves is 411 Average number of moves is 52.460248
Here is what happens if you turn off the just-in-time compiler:
setenv JAVA_COMPILER NONE java -version java version "1.2.1" Solaris VM (build Solaris_JDK_1.2.1_04, native threads, nojit) java TestMany 1000000 Starting simulation of 1000000 games: Statistics generated after 1000000 games: Time for simulation: 1587.89 seconds Minimum number of moves is 13 Maximum number of moves is 335 Average number of moves is 52.371593This takes 11 times as long.