CS310 Core Game API: Game, Move, PlayerNumber
// Game.java
//
// Ethan Bolker, February 2003
package edu.umb.cs.game;
import java.util.Observable;
import java.util.Iterator;
/**
* Abstract class Game models an abstract two person game with perfect
* information - each player knows everything the other does.
* ... (history, etc., see file)
*/
public abstract class Game extends Observable { public final static PlayerNumber FIRST_PLAYER = PlayerNumber.ONE;
public final static PlayerNumber SECOND_PLAYER = PlayerNumber.TWO;
public final static PlayerNumber GAME_OVER = PlayerNumber.GAME_OVER;
public final static PlayerNumber GAME_NOT_OVER = PlayerNumber.GAME_NOT_OVER;
public final static PlayerNumber DRAW = PlayerNumber.DRAW;
/**
* What is the name of the Game? May be called before init/initObservable.
*
* @return the name of the Game.
*/
public abstract String getName();
/**
* Who wrote this Game?
*
* @return the name of the author. May be called before init/initObservable.
*/
public abstract String getAuthor();
/**
* Does this Game need information to set itself up before the first move is
* made? May be called before init/initObservable.
*
* @return true if so.
*/
public abstract boolean needSetup();
/**
* Configure the game before it starts
* Only needed if needSetup returns true
* Must be called before init/initObservable
* (or followed by call to init/initObservable)
*
* @param params
* @throws RuntimeException, GameException
*/
public void setup(int[] params) throws GameException { throw new RuntimeException("bug: need setup for this game"); }
/* init and initObservable: only the above methods, gameStrings.help(), and
* gameStrings.getSetupParamDefinitions() may be called before init or
* initObservable is called, i.e., before game's init is called.
*/
/**
* Set up the position ready to play.
* <p>
* This should <i>not<\i> be done in the constructor.
*/
public abstract void init();
/**
* Set up the position ready to play.
* <p>
* This should <i>not<\i> be done in the constructor.
*/
/**
* Set up the position ready to play and notify Observers.
* Note that the first notification signals that the game
* has just been init'd.
*/
public final void initObservable() { init();
setChanged();
notifyObservers();
}
/**
* Inform this Game that it is over.
*/
public abstract void gameOver();
/**
* Create a copy of the current position of this Game.
*
* @return the copy.
*/
public abstract Game copy();
/**
* Is this game new?
*
* @return true if yes.
*/
public abstract boolean isGameNew();
/**
* Is this game over?
*
* @return true if yes.
*/
public abstract boolean isGameOver();
/**
* Since Players need not alternate making moves, you must be able to query
* the current position to find out whose turn it is.
*
* If the game is over, return Game.GAME_OVER.
*
* @return the PlayerNumber who moves next.
*/
public abstract PlayerNumber whoseTurn();
/**
* Who has won the game? Returns one of Game.FIRST_PLAYER,
* Game.SECOND_PLAYER, Game.DRAW, Game.GAME_NOT_OVER.
*
* @return the winner.
*/
public abstract PlayerNumber winner();
/**
* Make a Move and notify this Game's Observers.
*
* @param m
* the Move to be made.
* @throws IllegalMoveException
* if m is illegal.
*/
public final void makeObservable(Move m) throws IllegalMoveException { make(m);
setChanged();
notifyObservers(m);
}
/**
* The rules of the game are encapsulated here: Change this position by
* making Move m.
*
* @param m
* the Move to be made.
* @throws IllegalMoveException
* if m is illegal.
*/
public abstract void make(Move m) throws IllegalMoveException;
/**
* The user can loop on the legal moves in any position.
*
* @return a Iterator for the legal moves.
*/
public abstract Iterator<Move> getMoves();
/**
* The Game implementation must override hashCode from class Object. As
* usual, it must be consistent with equals: two objects for which equals
* returns true must have the same hashCode.
*/
public abstract int hashCode();
/**
* The Game implementation must override equals from class Object. Two Game
* objects are equal if all the Game methods would return the same result,
* including whoseTurn(), winner(), and the move list from getMoves.
* The intention is that two not-over game states are equal if the
* board position is the same and the player to play next is the same.
* Concluded game states may lump various board positions together,
* but must differ based on winner() values.
*/
public abstract boolean equals(Object obj);
/**
* View this Game using Strings. Required support for game.
*
*/
public abstract GameStrings getGameStrings();
}
Move.java
// Move.java
//
// Ethan Bolker, February 2003
//
// More comments in file
package edu.umb.cs.game;
/**
* A Move in an abstract Game.
* The client must be able to copy a move.
*
*/
public abstract class Move
{ /**
* A client must be able to copy a move.
*/
public abstract Move copy();
/**
* The Move implementation must override equals
* from class Object.
*/
public abstract boolean equals( Object obj );
/**
* The Move implementation must override hashCode
* from class Object, and be consistent with equals.
*/
public abstract int hashCode();
}
PlayerNumber.java
// PlayerNumber.java
//
// Ethan Bolker, February 2003
// converted to enum by Betty O'Neil Jan 2009
package edu.umb.cs.game;
/**
* This class provides five constant values, so that PlayerNumber
* values can be compared with ==.
*/
public enum PlayerNumber { ONE("1", true), TWO("2", true), GAME_OVER("game is over", false), GAME_NOT_OVER("game not over", false), DRAW("draw", false);
private String name;
private boolean isRealPlayer;
private PlayerNumber(String name, boolean isRealPlayer) { this.name = name;
this.isRealPlayer = isRealPlayer;
}
/**
* Is this a Player in the Game, or some other identifier?
*
* @return true if ONE or TWO.
*/
public boolean isRealPlayer() { return isRealPlayer;
}
// override default toString based on ONE, TWO, etc.
public String toString() { return name;
}
}