man kann speichern und laden, nur nicht während eines laufenden spiels laden

git-svn-id: svn://sunsvr01.isp.uni-luebeck.de/swproj13/trunk@386 72836036-5685-4462-b002-a69064685172
This commit is contained in:
Ida Massow 2011-06-08 16:29:13 +02:00
parent ce1b716e12
commit 3ff911ab93
10 changed files with 258 additions and 47 deletions

View file

@ -1,8 +1,11 @@
package jrummikub.control; package jrummikub.control;
import jrummikub.model.GameSettings; import jrummikub.model.GameSettings;
import jrummikub.model.GameState;
import jrummikub.model.IRoundState;
import jrummikub.util.IListener; import jrummikub.util.IListener;
import jrummikub.util.IListener1; import jrummikub.util.IListener1;
import jrummikub.util.IListener3;
import jrummikub.view.IView; import jrummikub.view.IView;
import jrummikub.view.IView.BottomPanelType; import jrummikub.view.IView.BottomPanelType;
@ -18,7 +21,7 @@ public class ApplicationControl {
* Creates a new application control * Creates a new application control
* *
* @param view * @param view
* the view to use * the view to use
*/ */
public ApplicationControl(IView view) { public ApplicationControl(IView view) {
this.view = view; this.view = view;
@ -38,25 +41,48 @@ public class ApplicationControl {
public void startApplication() { public void startApplication() {
view.showScorePanel(false); view.showScorePanel(false);
view.setBottomPanel(BottomPanelType.START_GAME_PANEL); view.setBottomPanel(BottomPanelType.START_GAME_PANEL);
SettingsControl settingsControl = new SettingsControl(view, saveControl.setGameSettings(null);
saveControl.setGameState(null);
final SettingsControl settingsControl = new SettingsControl(view,
new GameSettings()); new GameSettings());
saveControl.getLoadEvent().add(
new IListener3<GameSettings, GameState, IRoundState>() {
@Override
public void handle(GameSettings settings,
GameState gameState, IRoundState roundState) {
settingsControl.abort();
// TODO alles ordentlich beenden (controls)
GameControl gameControl = new GameControl(settings,
saveControl, view);
addGameControlListeners(gameControl);
gameControl.continueGame(gameState, roundState);
}
});
settingsControl.getStartGameEvent().add(new IListener1<GameSettings>() { settingsControl.getStartGameEvent().add(new IListener1<GameSettings>() {
@Override @Override
public void handle(GameSettings settings) { public void handle(GameSettings settings) {
saveControl.setGameSettings(settings); saveControl.setGameSettings(settings);
GameControl gameControl = new GameControl(settings, saveControl, view); GameControl gameControl = new GameControl(settings,
gameControl.getEndOfGameEvent().add(new IListener() { saveControl, view);
@Override addGameControlListeners(gameControl);
public void handle() {
startApplication();
}
});
gameControl.startGame();
gameControl.startGame();
} }
}); });
settingsControl.startSettings(); settingsControl.startSettings();
} }
private void addGameControlListeners(GameControl gameControl) {
gameControl.getEndOfGameEvent().add(new IListener() {
@Override
public void handle() {
startApplication();
}
});
}
} }

View file

@ -33,11 +33,11 @@ public class GameControl {
* Constructor * Constructor
* *
* @param gameSettings * @param gameSettings
* the game settings * the game settings
* @param saveControl * @param saveControl
* the save control * the save control
* @param view * @param view
* the view * the view
*/ */
public GameControl(GameSettings gameSettings, SaveControl saveControl, public GameControl(GameSettings gameSettings, SaveControl saveControl,
IView view) { IView view) {
@ -96,6 +96,16 @@ public class GameControl {
startRound(); startRound();
} }
public void continueGame(GameState gameState, IRoundState roundState) {
this.gameState = gameState;
if (roundState == null) {
showScorePanel();
} else {
prepareRound(roundState);
roundControl.continueRound();
}
}
private void startRound() { private void startRound() {
if (roundControl != null) { if (roundControl != null) {
return; return;
@ -104,6 +114,11 @@ public class GameControl {
view.showScorePanel(false); view.showScorePanel(false);
IRoundState roundState = new RoundState(gameSettings); IRoundState roundState = new RoundState(gameSettings);
prepareRound(roundState);
roundControl.startRound();
}
private void prepareRound(IRoundState roundState) {
saveControl.setRoundState(roundState); saveControl.setRoundState(roundState);
roundState.setActivePlayerNumber(gameState.getFirstRoundFirstPlayer() roundState.setActivePlayerNumber(gameState.getFirstRoundFirstPlayer()
@ -125,8 +140,6 @@ public class GameControl {
restartRound(); restartRound();
} }
}); });
roundControl.startRound();
} }
private void restartRound() { private void restartRound() {
@ -136,13 +149,19 @@ public class GameControl {
private void endOfRound(Score roundScore) { private void endOfRound(Score roundScore) {
gameState.getScores().add(roundScore); gameState.getScores().add(roundScore);
saveControl.setRoundState(null);
roundControl = null; roundControl = null;
showScorePanel();
}
private void showScorePanel() {
view.setBottomPanel(BottomPanelType.WIN_PANEL); view.setBottomPanel(BottomPanelType.WIN_PANEL);
view.getScorePanel().setPlayers(gameSettings.getPlayerList()); view.getScorePanel().setPlayers(gameSettings.getPlayerList());
view.getScorePanel().setScores(gameState.getScores()); view.getScorePanel().setScores(gameState.getScores());
view.getScorePanel().setAccumulatedScore(gameState.getAccumulatedScore()); view.getScorePanel().setAccumulatedScore(
gameState.getAccumulatedScore());
view.getScorePanel().update(); view.getScorePanel().update();
view.showScorePanel(true); view.showScorePanel(true);
} }

View file

@ -47,9 +47,9 @@ public class RoundControl {
* Create a new RoundControl using the given gameState and view * Create a new RoundControl using the given gameState and view
* *
* @param roundState * @param roundState
* initial round state * initial round state
* @param view * @param view
* view used for user interaction * view used for user interaction
*/ */
public RoundControl(IRoundState roundState, IView view) { public RoundControl(IRoundState roundState, IView view) {
this.roundState = roundState; this.roundState = roundState;
@ -70,7 +70,10 @@ public class RoundControl {
*/ */
public void startRound() { public void startRound() {
deal(); deal();
continueRound();
}
public void continueRound() {
connections.add(view.getStartTurnEvent().add(new IListener() { connections.add(view.getStartTurnEvent().add(new IListener() {
@Override @Override
public void handle() { public void handle() {
@ -91,11 +94,12 @@ public class RoundControl {
: BottomPanelType.COMPUTER_HAND_PANEL); : BottomPanelType.COMPUTER_HAND_PANEL);
view.getTablePanel().setStoneSets(clonedTable.clone()); view.getTablePanel().setStoneSets(clonedTable.clone());
view.setCurrentPlayerName(roundState.getActivePlayer().getPlayerSettings() view.setCurrentPlayerName(roundState.getActivePlayer()
.getName()); .getPlayerSettings().getName());
view.setCurrentPlayerColor(roundState.getActivePlayer().getPlayerSettings() view.setCurrentPlayerColor(roundState.getActivePlayer()
.getColor()); .getPlayerSettings().getColor());
view.setCurrentPlayerHasLaidOut(roundState.getActivePlayer().getLaidOut()); view.setCurrentPlayerHasLaidOut(roundState.getActivePlayer()
.getLaidOut());
if (!isHuman) if (!isHuman)
startTurn(); startTurn();
@ -120,11 +124,11 @@ public class RoundControl {
view.getPlayerPanel().setEndTurnMode(turnMode); view.getPlayerPanel().setEndTurnMode(turnMode);
} }
turnControl = TurnControlFactory.getFactory( turnControl = TurnControlFactory.getFactory(
roundState.getActivePlayer().getPlayerSettings().getTurnControlType()) roundState.getActivePlayer().getPlayerSettings()
.create(); .getTurnControlType()).create();
turnControl.setup(new ITurnControl.TurnInfo(clonedTable, clonedHand, turnControl.setup(new ITurnControl.TurnInfo(clonedTable, clonedHand,
roundState.getActivePlayer().getLaidOut(), turnMode), roundState roundState.getActivePlayer().getLaidOut(), turnMode),
.getGameSettings(), view); roundState.getGameSettings(), view);
turnControl.getEndOfTurnEvent().add(new IListener() { turnControl.getEndOfTurnEvent().add(new IListener() {
@Override @Override
public void handle() { public void handle() {
@ -144,8 +148,10 @@ public class RoundControl {
void deal() { void deal() {
for (int i = 0; i < roundState.getPlayerCount(); i++) { for (int i = 0; i < roundState.getPlayerCount(); i++) {
IHand hand = roundState.getNthNextPlayer(i).getHand(); IHand hand = roundState.getNthNextPlayer(i).getHand();
for (int j = 0; j < roundState.getGameSettings().getNumberOfStonesDealt(); j++) { for (int j = 0; j < roundState.getGameSettings()
hand.drop(roundState.getGameHeap().drawStone(), new Position(0, 0)); .getNumberOfStonesDealt(); j++) {
hand.drop(roundState.getGameHeap().drawStone(), new Position(0,
0));
} }
} }
} }
@ -156,11 +162,13 @@ public class RoundControl {
int totalValue = 0; int totalValue = 0;
for (StoneSet set : newSets) { for (StoneSet set : newSets) {
totalValue += set.classify(roundState.getGameSettings()).getSecond(); totalValue += set.classify(roundState.getGameSettings())
.getSecond();
} }
return totalValue == 0 return totalValue == 0
|| totalValue >= roundState.getGameSettings().getInitialMeldThreshold(); || totalValue >= roundState.getGameSettings()
.getInitialMeldThreshold();
} }
private void endOfTurn() { private void endOfTurn() {
@ -200,7 +208,8 @@ public class RoundControl {
} }
if (!roundState.getActivePlayer().getLaidOut()) { if (!roundState.getActivePlayer().getLaidOut()) {
// Player touched forbidden stones // Player touched forbidden stones
if (!tableSetDifference(clonedTable, roundState.getTable()).isEmpty()) { if (!tableSetDifference(clonedTable, roundState.getTable())
.isEmpty()) {
rejectMove(); rejectMove();
return; return;
} }
@ -209,7 +218,8 @@ public class RoundControl {
return; return;
} }
} }
Set<Stone> tableDiff = tableDifference(roundState.getTable(), clonedTable); Set<Stone> tableDiff = tableDifference(roundState.getTable(),
clonedTable);
roundState.setTable(clonedTable); roundState.setTable(clonedTable);
@ -225,7 +235,8 @@ public class RoundControl {
} }
private void rejectMove() { private void rejectMove() {
Set<Stone> tableDiff = tableDifference(roundState.getTable(), clonedTable); Set<Stone> tableDiff = tableDifference(roundState.getTable(),
clonedTable);
// deal penalty, reset // deal penalty, reset
roundState.getGameHeap().putBack(tableDiff); roundState.getGameHeap().putBack(tableDiff);
dealPenalty(tableDiff.size()); dealPenalty(tableDiff.size());
@ -315,10 +326,12 @@ public class RoundControl {
stonePoints = playerHand.isInitialMeldPossible(roundState stonePoints = playerHand.isInitialMeldPossible(roundState
.getGameSettings()) ? 200 : 100; .getGameSettings()) ? 200 : 100;
} else { } else {
stonePoints = playerHand.getStonePoints(roundState.getGameSettings()); stonePoints = playerHand.getStonePoints(roundState
.getGameSettings());
} }
bestScore = updateBestScore(bestScore, -stonePoints, playerHand.getSize()); bestScore = updateBestScore(bestScore, -stonePoints,
playerHand.getSize());
points.add(-stonePoints); points.add(-stonePoints);
pointSum += stonePoints; pointSum += stonePoints;

View file

@ -1,12 +1,16 @@
package jrummikub.control; package jrummikub.control;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import jrummikub.model.GameSettings; import jrummikub.model.GameSettings;
import jrummikub.model.GameState; import jrummikub.model.GameState;
import jrummikub.model.IRoundState; import jrummikub.model.IRoundState;
import jrummikub.util.Event3;
import jrummikub.util.IEvent3;
import jrummikub.util.IListener1; import jrummikub.util.IListener1;
import jrummikub.view.IView; import jrummikub.view.IView;
@ -17,12 +21,13 @@ public class SaveControl {
private GameSettings gameSettings; private GameSettings gameSettings;
private GameState gameState; private GameState gameState;
private IRoundState roundState; private IRoundState roundState;
private Event3<GameSettings, GameState, IRoundState> loadEvent = new Event3<GameSettings, GameState, IRoundState>();
/** /**
* Creates a new SaveControl * Creates a new SaveControl
* *
* @param view * @param view
* the view to use * the view to use
*/ */
public SaveControl(IView view) { public SaveControl(IView view) {
view.getSaveEvent().add(new IListener1<File>() { view.getSaveEvent().add(new IListener1<File>() {
@ -31,13 +36,24 @@ public class SaveControl {
save(file); save(file);
} }
}); });
view.getLoadEvent().add(new IListener1<File>() {
@Override
public void handle(File file) {
load(file);
}
});
}
public IEvent3<GameSettings, GameState, IRoundState> getLoadEvent() {
return loadEvent;
} }
/** /**
* Sets the current game settings * Sets the current game settings
* *
* @param gameSettings * @param gameSettings
* the game settings * the game settings
*/ */
public void setGameSettings(GameSettings gameSettings) { public void setGameSettings(GameSettings gameSettings) {
this.gameSettings = gameSettings; this.gameSettings = gameSettings;
@ -47,7 +63,7 @@ public class SaveControl {
* Sets the current game state * Sets the current game state
* *
* @param gameState * @param gameState
* the game state * the game state
*/ */
public void setGameState(GameState gameState) { public void setGameState(GameState gameState) {
this.gameState = gameState; this.gameState = gameState;
@ -57,16 +73,45 @@ public class SaveControl {
* Sets the current round state * Sets the current round state
* *
* @param roundState * @param roundState
* the round state * the round state
*/ */
public void setRoundState(IRoundState roundState) { public void setRoundState(IRoundState roundState) {
this.roundState = roundState; this.roundState = roundState;
} }
private void save(File file) { private void load(File file) {
try { try {
ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream( ObjectInputStream stream = new ObjectInputStream(
file)); new FileInputStream(file));
gameSettings = (GameSettings) stream.readObject();
gameState = (GameState) stream.readObject();
roundState = (IRoundState) stream.readObject();
stream.close();
if (gameState == null || gameSettings == null) {
// TODO Fehlermeldung
System.err.println("laden ging nicht");
return;
}
loadEvent.emit(gameSettings, gameState, roundState);
} catch (Exception e) {
e.printStackTrace();
}
}
private void save(File file) {
if (gameState == null || gameSettings == null) {
// TODO Menüpunkt ausgrauen
System.err.println("kein aktives Spiel");
return;
}
try {
ObjectOutputStream stream = new ObjectOutputStream(
new FileOutputStream(file));
stream.writeObject(gameSettings); stream.writeObject(gameSettings);
stream.writeObject(gameState); stream.writeObject(gameState);

View file

@ -333,4 +333,12 @@ public class SettingsControl {
} }
startGameEvent.emit(settings); startGameEvent.emit(settings);
} }
public void abort() {
// TODO Auto-generated method stub
view.showSettingsPanel(false);
for (Connection c : connections) {
c.remove();
}
}
} }

View file

@ -1,5 +1,6 @@
package jrummikub.model; package jrummikub.model;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
@ -11,10 +12,12 @@ import jrummikub.util.Pair;
import static jrummikub.model.StoneSet.Type.*; import static jrummikub.model.StoneSet.Type.*;
/** Class managing {@link Stone}s joined together to form sets */ /** Class managing {@link Stone}s joined together to form sets */
public class StoneSet implements Iterable<Stone>, Sizeable { public class StoneSet implements Iterable<Stone>, Sizeable, Serializable {
private static final long serialVersionUID = -3852631195648599398L;
static final float VERTICAL_BORDER = 0.5f; static final float VERTICAL_BORDER = 0.5f;
static final float HORIZONTAL_BORDER = 0.125f; static final float HORIZONTAL_BORDER = 0.125f;
private List<Stone> stones; private ArrayList<Stone> stones;
/** /**
* Create a new single stone stone set * Create a new single stone stone set
@ -23,7 +26,7 @@ public class StoneSet implements Iterable<Stone>, Sizeable {
* single stone of the set * single stone of the set
*/ */
public StoneSet(Stone stone) { public StoneSet(Stone stone) {
stones = Collections.singletonList(stone); stones = new ArrayList<Stone>(Collections.singletonList(stone));
} }
/** /**

View file

@ -13,8 +13,9 @@ import jrummikub.util.Pair;
* @param <E> * @param <E>
* Type of positioned objects (must implement Sizeable) * Type of positioned objects (must implement Sizeable)
*/ */
@SuppressWarnings("serial")
public class StoneTray<E extends Sizeable> implements IStoneTray<E> { public class StoneTray<E extends Sizeable> implements IStoneTray<E> {
private static final long serialVersionUID = -6329309928640027222L;
protected HashMap<E, Pair<E, Position>> objects = new HashMap<E, Pair<E, Position>>(); protected HashMap<E, Pair<E, Position>> objects = new HashMap<E, Pair<E, Position>>();
/** Possible move directions in case of overlapping Stones/Sets */ /** Possible move directions in case of overlapping Stones/Sets */

View file

@ -0,0 +1,46 @@
package jrummikub.util;
import java.util.HashSet;
/**
* Simple single parameter event generator
*
* @param <T1>
* type of the first event parameter
* @param <T2>
* type of the second event parameter
*/
public class Event3<T1, T2, T3> implements IEvent3<T1, T2, T3> {
private HashSet<IListener3<T1, T2, T3>> listeners = new HashSet<IListener3<T1, T2, T3>>();
@Override
public Connection add(final IListener3<T1, T2, T3> listener) {
listeners.add(listener);
return new Connection() {
@Override
public void remove() {
Event3.this.remove(listener);
}
};
}
@Override
public void remove(IListener3<T1, T2, T3> listener) {
listeners.remove(listener);
}
/**
* Generate a single event
*
* @param value1
* the first event parameter
* @param value2
* the second event parameter
*/
public void emit(T1 value1, T2 value2, T3 value3) {
for (IListener3<T1, T2, T3> listener : listeners) {
listener.handle(value1, value2, value3);
}
}
}

View file

@ -0,0 +1,28 @@
package jrummikub.util;
/**
* Interface for classes that can generate events having a two parameters
*
* @param <T1>
* type of the first event parameter
* @param <T2>
* type of the second event parameter
*/
public interface IEvent3<T1, T2, T3> {
/**
* Start to publish all events to a given listener
*
* @param listener
* target listener
* @return a connection to remove the listener
*/
public Connection add(IListener3<T1, T2, T3> listener);
/**
* Stop publishing events to a given listener
*
* @param listener
* target listener
*/
public void remove(IListener3<T1, T2, T3> listener);
}

View file

@ -0,0 +1,22 @@
package jrummikub.util;
/**
* Interface for classes that can receive parameterless events having a two
* parameters
*
* @param <T1>
* type of the first event parameter
* @param <T2>
* type of the first event parameter
*/
public interface IListener3<T1, T2, T3> {
/**
* This method is called whenever a class we're listening to emits an event
*
* @param value1
* the first event parameter
* @param value2
* the second event parameter
*/
public void handle(T1 value1, T2 value2, T3 value3);
}