I'm trying to design the classes for the Wheel of Fortune game in Java. The below diagram represents the classes and the interaction between them.
.
Below is the partial implementation of it. I appreciate some feedback on my design and approach. I'm mainly interested in classes and their dependencies. In code I referred MoneyPrize
as DollarAmountSpinOutcome
.
1) Is Wheel dependency on Player correct? If not how can I redesign to avoid it?
2) In method WheelOfFortune.getSpinOutcomeProcessor(SpinOutCome outcome)
I am explicitly casting it to Specific spin out come. Is it a smell. Does it indicate a broken modeling?
public class WheelOfFortune {
private List<Player> players;
private Host host;
private Wheel wheel;
public WheelOfFortune(List<Player> players, Host host, Wheel wheel) {
this.players = players;
this.host = host;
this.wheel = wheel;
}
public static void main(String[] args) {
Player player1 = new Player("player1", new Account());
Player player2 = new Player("player2",new Account());
Player player3 = new Player("player3",new Account());
ArrayList<Player> players = new ArrayList<Player>();
players.add(player1);
players.add(player2);
players.add(player3);
Host host = new Host();
Wheel wheel = new Wheel();
WheelOfFortune wheelOfFortune = new WheelOfFortune(players, host, wheel);
wheelOfFortune.start();
}
public void start() {
int round = 0;
while (!isGameOver()) {
round++;
for (Player player : players) {
boolean isTurnOver = false;
while (!isTurnOver) {
Choice choice = player.makeChoice();
if (choice == Choice.SPIN_WHEEL) {
SpinOutCome spinOutCome = player.spinWheel(wheel, round);
isTurnOver = processSpinOutCome(spinOutCome);
} else if (choice == Choice.BUY_VOWEL) {
Character character = player.buyVowel();
isTurnOver = processOvalBuy(character);
}
}
}
}
}
private static boolean processVowelBuy(Character character) {
return false;
}
private boolean processSpinOutCome(SpinOutCome spinOutCome) {
SpinOutComeProcessor spinOutComeProcessor = getSpinOutcomeProcessor(spinOutCome);
return spinOutComeProcessor.process();
}
private SpinOutComeProcessor getSpinOutcomeProcessor(SpinOutCome spinOutCome) {
if (spinOutCome instanceof DollarAmoutSpinOutcome)
return new DollarAmoutSpinOutcomeProcessor(host, (DollarAmoutSpinOutcome) spinOutCome);
else
return null;
}
private static boolean isGameOver() {
return false;
}
}
Wheel
class Wheel {
public SpinOutCome spin(Player player, int round) {
// Return a random SpinOutcome;
return new DollarAmoutSpinOutcome(player, 500, round);
}
}
DollarAmoutSpinOutCome
class DollarAmoutSpinOutcome extends SpinOutCome {
private Integer dollarAmount;
public DollarAmoutSpinOutcome(Player player, int dollarAmount, Integer round) {
super(player, round);
this.dollarAmount = dollarAmount;
}
public Integer getAmount() {
return dollarAmount;
}
}
SpinOutCome
class SpinOutCome {
protected Player player;
protected Integer round;
public SpinOutCome(Player player, Integer round) {
this.player = player;
this.round = round;
}
public Player getPlayer() {
return player;
}
// DOLLAR_AMOUNT, LOSE_A_TURN, BANKRUPT, SOLVE_PUZZLE
}
Choice
enum Choice {
SPIN_WHEEL, BUY_VOWEL,
}
Account
class Account {
private Integer totalAmount;
public void debit(Integer amount) {
}
public void credit(Integer ammount) {
}
}
Host
class Host {
public List<Integer> getCharacterOccurences(Character c) {
return null;
}
public void uncoverConsonent(List<Integer> characterOccurences) {
}
}
SpinOutComeLoseATurn
class SpinOutComeLoseATurn extends SpinOutCome {
public SpinOutComeLoseATurn(Player player, Integer round) {
super(player, round);
}
}
SpinOutComeProcessor
class SpinOutComeProcessor {
private Host host;
private Player player;
public SpinOutComeProcessor(Host host, Player player) {
this.host = host;
this.player = player;
}
public Host getHost() {
return host;
}
public Player getPlayer() {
return player;
}
public boolean process() {
return false;
}
}
Player
class Player {
private Account account;
private final String name;
public Player(String name, Account account) {
this.name = name;
this.account = account;
}
public Choice makeChoice() {
return null;
}
public Character guessConsonant() {
return null;
}
public SpinOutCome spinWheel(Wheel wheel, int round) {
return wheel.spin(this, round);
}
public String solvePuzzle() {
return null;
}
public Character buyVowel() {
return null;
}
public void acceptCashGift(Integer amount) {
account.debit(amount);
}
}
DollarAmoutSpinOutcomeProcessor
class DollarAmoutSpinOutcomeProcessor extends SpinOutComeProcessor {
private DollarAmoutSpinOutcome dollarSpinOutCome;
public DollarAmoutSpinOutcomeProcessor(Host host, DollarAmoutSpinOutcome dollarSpinOutCome) {
super(host, dollarSpinOutCome.getPlayer());
this.dollarSpinOutCome = dollarSpinOutCome;
}
public boolean process() {
boolean isTurnOver;
Character character = getPlayer().guessConsonant();
List<Integer> characterOccurences = getHost().getCharacterOccurences(character);
if (characterOccurences.size() > 0) {
getPlayer().acceptCashGift(dollarSpinOutCome.getAmount() * characterOccurences.size());
getHost().uncoverConsonent(characterOccurences);
isTurnOver = false;
} else {
isTurnOver = true;
}
return isTurnOver;
}
}