Design, implement, and test three AI robots that implement the
IRobot
interface. A RandomRobot will
play correctly (i.e., respect all the rules), but will choose
randomly among all legal options whenever a choice is required. A
PredictableRobot will play always with the same
strategy: of all the legal moves, plays the highest-scoring (or
highest-ranked) card that is guaranteed not to win the trick. If none is
available and at least one more player will play, play the lowest card; Otherwise, play the highest-scoring card. If a suit must be chosen, choose in
order: Clubs, Diamonds, Spades, Hearts. Finally, a
SmartRobot will play correctly, and also display some
evidence of strategy (e.g., by inspecting the game state to determine
what others have played and acting appropriately).
Your SmartRobot must be demonstrably superior to RandomRobot and PredictableRobot (see below).
Implement a game engine module that can store all game state a provide
public methods to allow clients to modify the state of the game and
react to it through observers. This module should be made
accessible through class hearts.game.GameEngine
that will control
the state and playing of the game for one human and 3 computer
players. This state should include, for example, the cards played,
the state of the deck, the score of each player, which player is the
dealer, etc. This module should have no
GUI, but should provide an API allowing clients to "play" the
game, i.e., change the state of the object to allow it to control the
playing one complete game (which involves multiple hands). The Game Engine should support playing multiple games without restarting the application.
It is your responsibility to design a module with an interface meeting the principles seen in class, and that will make it as convenient as possible to create the user interface. It should also be possible to register observers of the game state.
Note that the game engine should be purely reactive. It should not control the flow of the program (e.g., through an event loop.
Besides the main GameEngine
class, you can create as many
helper classes as necessary to solve the problem.
It should be possible to log all the actions of the game engines through a logger. For this functionality, use the popular Log4J API (hint: it is already linked in your project). You need to log all actions necessary to replicate games played, e.g., by hand using real cards.
You must provide a set of unit tests that demonstrate and test your
Game module. You should have unit tests for each public method of your
GameEngine
class (except trivial getters and setters).
main
method) that
simulates playing a game using GameEngine
. Note that the
role for the driver is not to allows humans to play interactively, but
merely to demonstrate you GameEngine
API in action. For
example, Driver code would typically look like:
GameEngine lEngine = new GameEngine();
lEngine.selectDealer()
lEngine.addPlayer(...);
...
lEngine.newGame();
...
// Display results
and so on. It should be possible to turn the logging of the game engine commands on or off, as needed. For example, your console output could look like this:
INFO - Entering application.
INFO - Dealer is Jenny (2)
INFO - Deck shuffled
INFO - Bobby:5C 8C 6D 7D TD QD KD 5S 7S TS AS 8H AH
INFO - Shorty:4C QC KC AC 4D 4S 6S 8S 2H 3H 5H QH KH
INFO - Jenny:2C 3D 5D JD AD 2S 9S JS QS 4H 7H 9H TH
INFO - Ziggy:3C 6C 7C 9C TC JC 2D 8D 9D 3S KS 6H JH
INFO - Bobby passes 6D TD 5S Shorty
INFO - Shorty passes 4C KC 5H Jenny
INFO - Jenny passes AD 2S QS Ziggy
INFO - Ziggy passes 7C 9D 3S Bobby
INFO - Bobby:5C 7C 8C 7D 9D QD KD 3S 7S TS AS 8H AH
INFO - Shorty:QC AC 4D 6D TD 4S 5S 6S 8S 2H 3H QH KH
INFO - Jenny:2C 4C KC 3D 5D JD 9S JS 4H 5H 7H 9H TH
INFO - Ziggy:3C 6C 9C TC JC 2D 8D AD 2S QS KS 6H JH
INFO - Jenny plays TWO of CLUBS
INFO - Ziggy plays SIX of CLUBS
...
INFO - Bobby's score: 8
INFO - Shorty's score: 2
INFO - Jenny's score: 14
INFO - Ziggy's score: 0
...
Your driver should allow autoplay between 4 robots as well as
play between 3 robots and a human. Think carefully how this can be
designed as effectively as possible. Program your driver to
automatically play 10000 games between four of your
IRobots
(two random, one predictable, one smart), record
the number of games won by each type of robot, and output the number
of games played and the number won by each type of robot. If your
smart robot does not win the highest number of games, keep working on
it.
GameEngine
class. The
diagram must be in jpeg format. Note that by state
diagram, we mean a state diagram, not a class diagram.