[Instructions] [Search] [Current] [Changes] [Syllabus] [Handouts] [Outlines] [Labs] [Assignments] [Examples] [Bailey Docs] [SamR Docs] [Tutorial] [API]
What are some of the issues we should consider in the design of an Othello game?
Object-oriented design suggests that you put logically separate components of the game into separate classes. This helps ensure that each component can be developed independently and also allows us to reuse components in new ways. For our Othello game, we might want to change the way pieces flip, the size of the board, the rules, and the interface.
This consideration of "things we might want to change" suggests one way of segmenting the program into different classes.
Board class will be in charge of the game
board. It will permit us to place pieces, remove pieces, check for pieces,
and apply actions to pieces.
Piece class will represent the individual
pieces. We might also want to create a separate OthelloPiece
class that resembles Othello pieces (in that it can be flipped).
BoardLocation class will
represent legal
locations on the board. This will make it easier to do strange things
like switch to other three-dimensional Othello.
Rules class will represent most of
the rules
of the game. Some of the rules might also be represented within the
Piece class (or subclass). For example, the instructions for
flipping a piece might reside within the OthelloPiece class.
Play class implements some of the
interface for our game.
There are (at least) two basic strategies for interaction. We can build a text-based game, in which we repeatedly draw the board and ask the player to select where to move. We can build a more graphics-based game, in which the player can click on the appropriate point of the screen. To begin with, we will build a text-based version, since it will be easier to implement at this stage of our career.
The main "loop" of the program will be something like
// while the game isn't over (that is, there are still legal moves
// and neither play has quite)
// determine the current player
// give the current player a chance to move
// update as appropriate
This design also makes it easier to add a computerized opponent, as we
can have a Player class that we will
subclass for human and computer players.
It's likely that we'll only realize this once we go on to more specific
implementation details. However, it is likely that some Matrix
class will be useful for a representation of the board. I would choose to
use
rebelsky.util.Matrix
but you may find that you prefer one of your onw.
If we choose to do textual input and output, we'll need objects that support
this. We've been using
rebelsky.io.SimpleReader and
rebelsky.io.SimpleOutput.
It's likely that we'll need to worry about a few special cases having to do with the rules of the game. In particular,
It is likely that we won't be able to determine more about the exceptions until after we've designed the interfaces for our classes in more detail. Some of the exceptions we might consider are
IllegalMove - when an illegal move is made
GameOver - when the game is over
PlayerQuits - when a player quits prematurely
Board - the game boardGame boards will most likely need to support
Board(rows,columns) which creates a two-dimensional
rectangular game board. We'll worry about other constructors
as they are needed for more complicated games.
placePiece(Piece piece, BoardLocation loc) which puts a
piece on the board (replacing any piece that's already there).
removePiece(BoardLocation loc) which removes a piece
on the board. It makes sense to have our Board class
determine whether or not pieces are placed, and this also helps
differentiate it from the Matrix class.
piece(BoardLocation loc) which looks up the piece at
a particular location on the board.
empty(BoardLocation loc) which determines whether or
not there is a piece at a particular point on the board.
emptyLocations() which returns a list of empty locations
on the board.
BoardLocation - a location on the game board
It's not clear what we'll need to do with board locations except to set up
(row,column) pairs, at least at this stage of the design. We may also ask
ourselves whether we want to use BoardLocations in loops, in
which case we'll want to provide ways to change locations. My inclination
is to include as little as possible and not permit a change to a location.
Piece - one piece on the board
Pieces are likely to be rather simple. We'll need a
constructor that we can use to set their value, and that may be it.
While we could just use String or some such, use of
a Piece class helps
ensure that we only place things that we expect on the game board.
OthelloPiece - a piece for Othello
We can make the Piece class more
useful by subclassing it. An OthelloPiece can then
support flip(), black(), and white()
operations.
Rules - the rules of the game
If we think about the game from the perspective of the
interface given in the
Play class, we'll observe that the
Rules class can encapsulate a number of key issues in
the game.
turn(). This might
return a Player or an integer
representing which player is up next.
Player - a player
The Player class might handle interactions with both
user and "automatic" players. We can subclass this class for each
type of interaction (initially for regular players, later for
automatic players).
The primary method for Player will be
BoardLocation selectLocation(Board board, Rules rules)
which requests that the player select a location on the board.
This might throw an PlayerQuits exception when the player
quits prematurely.
Human - a human player
How will we implement selectLocation for a human player?
We could print out the board and continue to ask for a location until
the player quits or selects a legal location.
Play - the interface
In our discussion of the interface, we've already
seen many of the key issues for this class. I expect that this class will
have only a main routine that
Board,
Rules, and
Players.
Has this multi-object design made our task harder? Yes and no. Clearly, we'll need to spend more time worrying about the interaction between object. However, it is likely that we'll be able to test parts separately, which often makes it easier to track down bugs. Since this is likely to be a multi-person project, we can use the separation of objects to provide a mechanism for separating work.
[Instructions] [Search] [Current] [Changes] [Syllabus] [Handouts] [Outlines] [Labs] [Assignments] [Examples] [Bailey Docs] [SamR Docs] [Tutorial] [API]
Disclaimer Often, these pages were created "on the fly" with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.
Source text last modified Sun Feb 22 22:53:29 1998.
This page generated on Tue Jan 12 11:44:37 1999 by SiteWeaver.
Contact our webmaster at rebelsky@math.grin.edu