CSE142
Project #7
Board Games
November 21, 2003
Due Date: Electronic deadline: Sunday Dec. 7, 9:00pm.
Receipts due in class the following Monday, the 8th.
Intermediate (step by step--just to avoid procrastination)
deadlines:
Tuesday Nov. 25, 9:00pm -- Hook up with partners,
decide on which game, and submit a stub implementation of the
interfaces.
Tuesday Dec. 2, 9:00pm -- Submit something
that at least displays your game board, with no game play required.
The Project
In this project we will implement a board game. What game you
implement is up to you. It could even be one of your own
invention (something perhaps with some very simple rules).
The only requirement is that your game program needs to implement the
given interfaces.
This requirement implies that your game should be played on a gridded
board, like a checker board. Possible games that fit this
requirement range from very simple, such as Tic Tac Toe (a good choice if
you want to keep it simple!) to more challenging options such as Othello
(also a good and recommended choice for people wanting a challenge),
Checkers, Go,
some variant of the Game Of Life,
or even Chess. The game you chose to implement being up to you is
intended to let you choose something at a level of challenge to which
you feel prepared to rise. To learn more about games you may not
be familiar with, follow the links above. Needless to say, the more
complex games will call for more work on the AI end of things.
But since the minimum bar for successful completion of the project is
really to create concrete implementations of the given interfaces, and
work a little with two dimensional arrays, then even a trivial game in
which I plunk down a piece on the board and the computer answers by
plunking down another one on a random square could be considered
minimally acceptable, though not a very interesting game. If you
do choose to make up your own game or find some obscure thing we don't
know about, please document in comments the rules of play that you are
implementing.
What is the point of this exercise?
The purpose of this project is to work with Java interfaces and to get
a sense of their power, and to work with two dimensional arrays.
Also, to see how
to implement mouse event driven input using a library interface.
The interfaces
The interfaces that your game needs to implement are four:
Cell
// representing, for
example, a square on a
checkerboard, or a space,
Board
// representing a game board, consisting
of a 2-D
array of Cells, such as a checker-board,
Game
// being the wrapper object holding it all
together, and embodying the game-play, the players' moves, and
Opponent // representing
the "AI" player, against whom the human plays.
The code for these four interface definitions can be found by
following the links on them above. Note and beware! Do not
change theses interface declarations! The reason why is that when
you turn in your code, your code will be compiled against these
declarations and only these declarations as they appear on the turn in
server. In other words, if you modified them and included them in
your turn in, that will not work.
The interfaces should all be
loaded into your Java environment.
Your job is then to implement four concrete classes that implement
these interfaces. For example if your game is Tic Tac Toe
("TTT" for short) you would create the classes TTTCell, TTTBoard,
TTTGame, and TTTOpponent. Each class definition
would begin
like:
public class TTTCell implements Cell { ... },
etc.
So how is this supposed to work? You can tell a lot just by
reading the interfaces. If you look at the Board interface you can see
that the intent is to hold and give access to a two dimensional array
of Cell objects (see the parameters and return types to setCell and
getCell). Each Cell is has a mark indicating how it has been
marked or what kind of piece is on it. A simple marking scheme
might be zero for empty squares, -1 for spaces with pieces belonging to
the AI player, and +1 for the human's pieces. Of course if you
are doing chess or Stratego or something with more and different pieces
you could expand this scheme. The Board knows how
to display itself on a GWindow, (in the manner to which you have become
accustomed, even though it was admittedly unnecessary before) by
iterating through its array of Cells (hint: nested
for-loops are good for 2-D arrays) and telling each of these to display
itself on the GWindow, which gets passed along. A Cell can do the
trivial thing of adding its rectangle to the GWindow, or any other
fancy thing like O' and X's or drawings of chess pieces, or just
coloring the cells depending on what its mark is.
But there is stuff to implement that may not be clear from the
interface specs. Cheifly this would be in the constructors, which
need to set things up. (Also of course the reasoning that needs
to be implemented to embody the game-play.)
In particular:
- Your Board class (TTTBoard or OthelloBoard) should have a 2-D
array of
cells as an instance variable. The constructor (no parameters
needed) should initialize this array (probably with a nested pair of
for loops) by instantiating a Cell for each slot in the 2-D array.
- Your Cell class should have a constructor that takes a pair of
indices
indicating that Cell's position in the 2-D array (this is easy since
the
Board constructor's nested for loop counters can just be passed in when
the Cell is instantiated.) So a Cell needs instance variables for
column and row index as well as one for its mark, which should also be
initialized in the constructor.
- Your Opponent class doesn't need much to begin with. It is
almost
just a place holder for the AI. An acceptable and even
recommended first pass implementation would be to compute the AI's next
move by making a random choice of available freeCells (gotten by
querying the Board for its freeCells).
- Your Game class should have instance variables to hold a Board, a
GWindow and an Opponent. These should be instantiated in the Game
constructor, and an initial call to board.displayOn(gWindow); should
probably be done at the end of the constructor. Game play
proceeds by the user initiating a call to game.userMove(col, row);
which should set the chosen cell with the user's mark (if it's a legal
move!) and ask the opponent for his nextMove(), set that, and then
display the board on the window again. Also as it's being created
your Game constructor should register itself with the GWindow it just
created, as the object that's going to handle user events, as described
below.
User Mouse Input
You could play your game by successively typing game.userMove(x, y);
into the Interactions Pane, and while this a fine way to test things,
it just isn't much fun to play. What you want surely is to be
able to click on the board to indicate your move. This is
surprisingly easy to do using a very little bit of magic that is
available to you in the uwcse graphics package. This package
defines an interface called GWindowEventHandler, which if you have your
Game class implement that too, you're almost set up to capture user
events. Thus, your game class will implement two interfaces, thus for example:
public class OthelloGame implements Game,
GWindowEventHandler {...}
So you look at the API docs on GWindowEventHandler and you say, gee,
there are 6 methods there, do I have to implement all of them?
The answer is "yes", but do not despair, since all but one can be empty
no op methods like:
public void mouseDragged(GWindowEvent e) {} //note:
literally nothing between the square brackets.
the only one you really need to implement is mousePressed(). In
fact, why don't you just go ahead and use this code:
public void
mousePressed(GWindowEvent e) {
ArrayList Set
freeCells = this.board.getFreeCells();
//my bad. Should have been
Set, not ArrayList
Iterator cellsIter = freeCells.iterator();
while (cellsIter.hasNext())
{
Cell aCell = (Cell)cellsIter.next();
Rectangle r = aCell.getRectangle();
if ( (r.getX() <= e.getX()) //determine whether click was in this
cell
&&(r.getY() <= e.getY()) //since events know where they occured
in the window
&&(r.getX() + r.getWidth() >= e.getX())
&&(r.getY() + r.getHeight() >= e.getY()) ) {
this.userMove(aCell.getColumn(),
aCell.getRow()); //if so,
this is the user's move
}
}
}
The final bit of magic to get this to work is that you have to
tell the GWindow to send events within it to your game object which
will handle the events, which it is prepared to do since it implements
the GWindowEventHandler interface. So in your Game class
constructor just invoke something rather like the following magical
incantation (among others):
public OthelloGame() {
gameWindow = new GWindow(500,
500);
gameWindow.addEventHandler(this);
//so the window will send events
to your game.
// Yes! The 'this' reference is valid,
even though the object
// is only in the process of being created at
this point!
...
}
That should do it. It makes things much more fun. Can you
get a sense of how powerful using interfaces is from this? The
GWindow class knows nothing at all about my Game class. But since
I've entered into a contract stating that I'm implementing the
GWindowEventHandler interface, then when I pass my Game object in to
the window (with .addEventHandler(this)) then the Window can refer to
my game thing with a reference of type GWindowEventHandler and work its
magic.
What you are asked to do:
- Implement and turn-in four files named something like
YourGame.java, YourCell.java,
YourBoard.java, and YourOpponent.java, where "Your" stands in for
something like "Othello", or "Checkers", etc.
- This is a pairs programming project again, if that works for you.
- The first turn-in form is here.
The first turn in should consist of the four implementation files,
which should make it clear what game you and your partner (if you have
one) have agreed on implementing. But there is no expectation
that anything should actually work, though your code must
compile. This means at the very least that all the methods
declared in the interfaces that your classes implement must at least be
stubbed in, i.e. be defined with the correct signatures, but empty
curly braces {}. But you are certainly free to turn in as much as
you've got by this time, if you get a start on your constructors of
display routines for example.
- The second turn-in form is here.
The second turn in should at least display the board when you start a
game. Again it consists of the four main java files for your
classes and any other helper classes you may have defined.
- The final turn-in form is here.
- If you would like to face your game off in an AI vs. AI
tournament let us know.
Good luck and have fun!