Design and implement the following strategies as
additional players:
-
PlayInitialWord: this player only plays when there are no
tiles on the board. It searches the dictionary for all
words that it can form with its tiles and then places the
one with the highest value on the initial
square. Otherwise, it passes.
-
PlayGoodWord: the player finds all of the
complete words in its tiles. Then, it searches all of the
squares in the board to see if any of the words fit on a
square. It then plays the word that scores the most
points.
This player can be improved in several ways. For
example, it might use the contents of the board to
search for words that it could not otherwise form (eg,
if there an “a” on the board and only a
“c” and a “t” are on the rack, the
strategy above would not find
“cat”,
“act”,
“ca”,
“at”, or
“ta”.)
(These improvements are not necessary.)
-
NoS : the player follows the same strategy as the PlayGoodWord player except when it has any "S"s on its rack. In that case, it exchanges the "S"s for different letters.
-
NoJQXZ : the player follows the same strategy as the PlayGoodWord player except when it has any "J"s, "Q"s, "X"s, or "Z"s on its rack. In that case, it exchanges them for different letters.
Build a stress test for your rules infrastructure that
registers players and plays games with them. Do this
over and over (all night long, say) and check for errors (in
the morning). Hint: print out the random seed before
each run so you can reproduce any bugs that you find. And,
of course, when you find a bug, turn it into a test
case first, before fixing it.
Run a tournament to find out how these strategies
perform. What is the relative ordering among all four
strategies (according to your tournament)?
Some hints on testing:
-
Separate out pieces of the player's functionality as
library routines and test these individually.
-
Build your tests as you build your players. That is, find
some small piece of the player that you can
implement. Implement and test that one piece (or, if you
prefer, write test cases and then implement them) before
moving on to the next one. Of course, that means that you
have to have some idea of the overall shape before you
begin.
-
Keep in mind that you are only testing your player -- if you
find mistakes in your board or move checking logic, add a
test case there.
- To build a test case, construct a board and pick a tile
that you know should make the player behave in a certain
manner. Then, call the players takeTurn method
with a TurnI object that expects its methods to
be called in a certain order with certain arguments, in
order to see if the moves produced matched what it should
have done in that situation.
-
Build many such test cases, starting with very simple ones and
building up to more and more complex ones, with the goal of
covering every different logical aspect of the player’s
behavior.
-
Automatically test if the player fails. Only use printouts
for debugging -- remove them when the tests pass! (In
general, don't leave junk like commented out code or
printouts in your code; that does not make it
easier to read.)
|