Tested and implemented scoring
git-svn-id: svn://sunsvr01.isp.uni-luebeck.de/swproj13/trunk@272 72836036-5685-4462-b002-a69064685172
This commit is contained in:
parent
e3b5a0790d
commit
157bd4f606
8 changed files with 283 additions and 29 deletions
|
@ -104,4 +104,13 @@ public class MockRoundState implements IRoundState {
|
||||||
}
|
}
|
||||||
activePlayer = j;
|
activePlayer = j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPlayer getNthPlayer(int i) {
|
||||||
|
int j = i % players.size();
|
||||||
|
if (j < 0) {
|
||||||
|
j += players.size();
|
||||||
|
}
|
||||||
|
return players.get(j);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,10 @@ import jrummikub.model.GameSettings;
|
||||||
import jrummikub.model.GameState;
|
import jrummikub.model.GameState;
|
||||||
import jrummikub.model.IRoundState;
|
import jrummikub.model.IRoundState;
|
||||||
import jrummikub.model.RoundState;
|
import jrummikub.model.RoundState;
|
||||||
|
import jrummikub.model.Score;
|
||||||
import jrummikub.util.Connection;
|
import jrummikub.util.Connection;
|
||||||
import jrummikub.util.IListener;
|
import jrummikub.util.IListener;
|
||||||
|
import jrummikub.util.IListener1;
|
||||||
import jrummikub.view.IView;
|
import jrummikub.view.IView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,10 +70,10 @@ public class GameControl {
|
||||||
roundState.setActivePlayerNumber(gameState.getFirstRoundFirstPlayer());
|
roundState.setActivePlayerNumber(gameState.getFirstRoundFirstPlayer());
|
||||||
|
|
||||||
roundControl = new RoundControl(roundState, view);
|
roundControl = new RoundControl(roundState, view);
|
||||||
roundControl.getEndOfRoundEvent().add(new IListener() {
|
roundControl.getEndOfRoundEvent().add(new IListener1<Score>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle() {
|
public void handle(Score roundScore) {
|
||||||
endOfRound();
|
endOfRound();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,15 +6,17 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import jrummikub.model.Hand;
|
import jrummikub.model.Hand;
|
||||||
import jrummikub.model.IRoundState;
|
|
||||||
import jrummikub.model.IHand;
|
import jrummikub.model.IHand;
|
||||||
|
import jrummikub.model.IPlayer;
|
||||||
|
import jrummikub.model.IRoundState;
|
||||||
import jrummikub.model.ITable;
|
import jrummikub.model.ITable;
|
||||||
import jrummikub.model.Position;
|
import jrummikub.model.Position;
|
||||||
|
import jrummikub.model.Score;
|
||||||
import jrummikub.model.Stone;
|
import jrummikub.model.Stone;
|
||||||
import jrummikub.model.StoneSet;
|
import jrummikub.model.StoneSet;
|
||||||
import jrummikub.util.Connection;
|
import jrummikub.util.Connection;
|
||||||
import jrummikub.util.Event;
|
import jrummikub.util.Event1;
|
||||||
import jrummikub.util.IEvent;
|
import jrummikub.util.IEvent1;
|
||||||
import jrummikub.util.IListener;
|
import jrummikub.util.IListener;
|
||||||
import jrummikub.util.Pair;
|
import jrummikub.util.Pair;
|
||||||
import jrummikub.view.IView;
|
import jrummikub.view.IView;
|
||||||
|
@ -26,7 +28,7 @@ public class RoundControl {
|
||||||
private IRoundState roundState;
|
private IRoundState roundState;
|
||||||
private IView view;
|
private IView view;
|
||||||
private ITable clonedTable;
|
private ITable clonedTable;
|
||||||
private Event endOfRoundEvent = new Event();
|
private Event1<Score> endOfRoundEvent = new Event1<Score>();
|
||||||
private List<Connection> connections = new ArrayList<Connection>();
|
private List<Connection> connections = new ArrayList<Connection>();
|
||||||
private boolean roundFinished;
|
private boolean roundFinished;
|
||||||
|
|
||||||
|
@ -48,7 +50,7 @@ public class RoundControl {
|
||||||
*
|
*
|
||||||
* @return endOfRoundEvent
|
* @return endOfRoundEvent
|
||||||
*/
|
*/
|
||||||
public IEvent getEndOfRoundEvent() {
|
public IEvent1<Score> getEndOfRoundEvent() {
|
||||||
return endOfRoundEvent;
|
return endOfRoundEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +136,6 @@ public class RoundControl {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (roundState.getActivePlayer() == roundState.getLastPlayer()) {
|
if (roundState.getActivePlayer() == roundState.getLastPlayer()) {
|
||||||
// TODO check who has won
|
|
||||||
endOfRound();
|
endOfRound();
|
||||||
} else {
|
} else {
|
||||||
roundState.nextPlayer();
|
roundState.nextPlayer();
|
||||||
|
@ -237,11 +238,65 @@ public class RoundControl {
|
||||||
dealStones(count + 3);
|
dealStones(count + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void endOfRound() {
|
void endOfRound() {
|
||||||
for (Connection c : connections) {
|
for (Connection c : connections) {
|
||||||
c.remove();
|
c.remove();
|
||||||
}
|
}
|
||||||
endOfRoundEvent.emit();
|
Score roundScore = score();
|
||||||
|
endOfRoundEvent.emit(roundScore);
|
||||||
roundFinished = true;
|
roundFinished = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Score score() {
|
||||||
|
List<Boolean> winners = new ArrayList<Boolean>();
|
||||||
|
List<Integer> points = new ArrayList<Integer>();
|
||||||
|
|
||||||
|
boolean foundRegularWinner = false;
|
||||||
|
int winnerPlayerNumber = 0;
|
||||||
|
Pair<Integer, Integer> bestScore = new Pair<Integer, Integer>(Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||||
|
int pointSum = 0;
|
||||||
|
for (int i = 0; i < roundState.getPlayerCount(); i++) {
|
||||||
|
IPlayer player = roundState.getNthPlayer(i);
|
||||||
|
IHand playerHand = player.getHand();
|
||||||
|
boolean isWinner = playerHand.getSize() == 0;
|
||||||
|
winners.add(isWinner);
|
||||||
|
if (isWinner) {
|
||||||
|
foundRegularWinner = true;
|
||||||
|
winnerPlayerNumber = i;
|
||||||
|
}
|
||||||
|
int stonePoints = 0;
|
||||||
|
|
||||||
|
if (!player.getLaidOut()) {
|
||||||
|
stonePoints = playerHand.isInitialMeldPossible() ? 200 : 100;
|
||||||
|
} else {
|
||||||
|
stonePoints = playerHand.getStonePoints();
|
||||||
|
}
|
||||||
|
|
||||||
|
bestScore = updateBestScore(bestScore, -stonePoints, playerHand.getSize());
|
||||||
|
|
||||||
|
points.add(-stonePoints);
|
||||||
|
pointSum += stonePoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundRegularWinner) {
|
||||||
|
points.set(winnerPlayerNumber, pointSum);
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < roundState.getPlayerCount(); i++) {
|
||||||
|
if (bestScore.equals(new Pair<Integer, Integer>(points.get(i), roundState.getNthPlayer(i).getHand().getSize()))) {
|
||||||
|
winners.set(i, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Score(winners, points);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Pair<Integer, Integer> updateBestScore(
|
||||||
|
Pair<Integer, Integer> bestScore, int stonePoints, int size) {
|
||||||
|
if (bestScore.getFirst() == stonePoints) {
|
||||||
|
return new Pair<Integer, Integer>(stonePoints, Math.min(bestScore.getSecond(), size));
|
||||||
|
} else if (bestScore.getFirst() < stonePoints) {
|
||||||
|
return new Pair<Integer, Integer>(stonePoints, size);
|
||||||
|
}
|
||||||
|
return bestScore;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,15 @@ public interface IRoundState {
|
||||||
*/
|
*/
|
||||||
public IPlayer getNthNextPlayer(int i);
|
public IPlayer getNthNextPlayer(int i);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the nth player
|
||||||
|
*
|
||||||
|
* @param i
|
||||||
|
* player number
|
||||||
|
* @return nth player
|
||||||
|
*/
|
||||||
|
public IPlayer getNthPlayer(int i);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the player that will make the last turn before the round ends when
|
* Sets the player that will make the last turn before the round ends when
|
||||||
* the heap is empty
|
* the heap is empty
|
||||||
|
|
|
@ -71,6 +71,15 @@ public class RoundState implements IRoundState {
|
||||||
return players.get(j);
|
return players.get(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPlayer getNthPlayer(int i) {
|
||||||
|
int j = i % players.size();
|
||||||
|
if (j < 0) {
|
||||||
|
j += players.size();
|
||||||
|
}
|
||||||
|
return players.get(j);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPlayer getActivePlayer() {
|
public IPlayer getActivePlayer() {
|
||||||
return players.get(activePlayer);
|
return players.get(activePlayer);
|
||||||
|
|
42
src/jrummikub/model/Score.java
Normal file
42
src/jrummikub/model/Score.java
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
package jrummikub.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Score of a single round
|
||||||
|
*/
|
||||||
|
public class Score {
|
||||||
|
List<Boolean> winners;
|
||||||
|
List<Integer> points;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new round score
|
||||||
|
*
|
||||||
|
* @param winners
|
||||||
|
* set for each player among the winners
|
||||||
|
* @param points
|
||||||
|
* points of each player
|
||||||
|
*/
|
||||||
|
public Score(List<Boolean> winners, List<Integer> points) {
|
||||||
|
this.winners = winners;
|
||||||
|
this.points = points;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the winner list
|
||||||
|
*
|
||||||
|
* @return set for each player among the winners
|
||||||
|
*/
|
||||||
|
public List<Boolean> getWinners() {
|
||||||
|
return winners;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the point list
|
||||||
|
*
|
||||||
|
* @return points of each player
|
||||||
|
*/
|
||||||
|
public List<Integer> getPoints() {
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,4 +48,35 @@ public class Pair<T1, T2> {
|
||||||
return "Pair [first=" + first + ", second=" + second + "]";
|
return "Pair [first=" + first + ", second=" + second + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((first == null) ? 0 : first.hashCode());
|
||||||
|
result = prime * result + ((second == null) ? 0 : second.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Pair other = (Pair) obj;
|
||||||
|
if (first == null) {
|
||||||
|
if (other.first != null)
|
||||||
|
return false;
|
||||||
|
} else if (!first.equals(other.first))
|
||||||
|
return false;
|
||||||
|
if (second == null) {
|
||||||
|
if (other.second != null)
|
||||||
|
return false;
|
||||||
|
} else if (!second.equals(other.second))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,11 @@ import jrummikub.model.MockTable;
|
||||||
import jrummikub.model.PlayerSettings;
|
import jrummikub.model.PlayerSettings;
|
||||||
import jrummikub.model.Position;
|
import jrummikub.model.Position;
|
||||||
import jrummikub.model.RoundState;
|
import jrummikub.model.RoundState;
|
||||||
|
import jrummikub.model.Score;
|
||||||
import jrummikub.model.Stone;
|
import jrummikub.model.Stone;
|
||||||
import jrummikub.model.StoneSet;
|
import jrummikub.model.StoneSet;
|
||||||
import jrummikub.model.Table;
|
import jrummikub.model.Table;
|
||||||
import jrummikub.util.IListener;
|
import jrummikub.util.IListener1;
|
||||||
import jrummikub.util.Pair;
|
import jrummikub.util.Pair;
|
||||||
import jrummikub.view.MockView;
|
import jrummikub.view.MockView;
|
||||||
|
|
||||||
|
@ -53,6 +54,7 @@ public class RoundControlTest {
|
||||||
private RoundControl roundControl;
|
private RoundControl roundControl;
|
||||||
|
|
||||||
private boolean roundEnded;
|
private boolean roundEnded;
|
||||||
|
private Score roundScore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For each test create a round control initialized by a mock model and view
|
* For each test create a round control initialized by a mock model and view
|
||||||
|
@ -161,7 +163,6 @@ public class RoundControlTest {
|
||||||
roundControl.startRound();
|
roundControl.startRound();
|
||||||
view.startTurnEvent.emit();
|
view.startTurnEvent.emit();
|
||||||
|
|
||||||
|
|
||||||
IHand hand = roundState.getActivePlayer().getHand();
|
IHand hand = roundState.getActivePlayer().getHand();
|
||||||
|
|
||||||
assertFalse(roundState.getActivePlayer().getLaidOut());
|
assertFalse(roundState.getActivePlayer().getLaidOut());
|
||||||
|
@ -589,9 +590,9 @@ public class RoundControlTest {
|
||||||
@Test
|
@Test
|
||||||
public void testWinning() {
|
public void testWinning() {
|
||||||
|
|
||||||
testRound.getEndOfRoundEvent().add(new IListener() {
|
testRound.getEndOfRoundEvent().add(new IListener1<Score>() {
|
||||||
@Override
|
@Override
|
||||||
public void handle() {
|
public void handle(Score roundScore) {
|
||||||
roundEnded = true;
|
roundEnded = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -622,7 +623,9 @@ public class RoundControlTest {
|
||||||
|
|
||||||
view.tablePanel.clickEvent.emit(new Position(0, 0));
|
view.tablePanel.clickEvent.emit(new Position(0, 0));
|
||||||
|
|
||||||
testRoundState.players.get(0).hand = new Hand(gameSettings);
|
for (int i = 0; i < 4; i++) {
|
||||||
|
testRoundState.players.get(i).hand = new Hand(gameSettings);
|
||||||
|
}
|
||||||
resetTurnStart();
|
resetTurnStart();
|
||||||
|
|
||||||
assertFalse(roundEnded);
|
assertFalse(roundEnded);
|
||||||
|
@ -718,9 +721,9 @@ public class RoundControlTest {
|
||||||
/** */
|
/** */
|
||||||
@Test
|
@Test
|
||||||
public void heapIsEmpty() {
|
public void heapIsEmpty() {
|
||||||
roundControl.getEndOfRoundEvent().add(new IListener() {
|
roundControl.getEndOfRoundEvent().add(new IListener1<Score>() {
|
||||||
@Override
|
@Override
|
||||||
public void handle() {
|
public void handle(Score roundScore) {
|
||||||
roundEnded = true;
|
roundEnded = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -742,4 +745,98 @@ public class RoundControlTest {
|
||||||
}
|
}
|
||||||
assertTrue(roundEnded);
|
assertTrue(roundEnded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
@Test
|
||||||
|
public void testScore() {
|
||||||
|
|
||||||
|
testRound.getEndOfRoundEvent().add(new IListener1<Score>() {
|
||||||
|
@Override
|
||||||
|
public void handle(Score score) {
|
||||||
|
roundEnded = true;
|
||||||
|
roundScore = score;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
testRound.startRound();
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
testRoundState.players.get(i).hand = new Hand(gameSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
testRoundState.players.get(0).laidOut = true;
|
||||||
|
testRoundState.players.get(0).hand.drop(new Stone(1, RED),
|
||||||
|
new Position(0, 0));
|
||||||
|
testRoundState.players.get(0).hand.drop(new Stone(2, RED),
|
||||||
|
new Position(0, 0));
|
||||||
|
testRoundState.players.get(1).laidOut = true;
|
||||||
|
testRoundState.players.get(1).hand.drop(new Stone(RED), new Position(0,
|
||||||
|
0));
|
||||||
|
testRoundState.players.get(2).laidOut = false;
|
||||||
|
testRoundState.players.get(2).hand.drop(new Stone(9, RED),
|
||||||
|
new Position(0, 0));
|
||||||
|
testRoundState.players.get(2).hand.drop(new Stone(10, RED),
|
||||||
|
new Position(0, 0));
|
||||||
|
testRoundState.players.get(2).hand.drop(new Stone(11, RED),
|
||||||
|
new Position(0, 0));
|
||||||
|
testRoundState.players.get(3).laidOut = true;
|
||||||
|
|
||||||
|
testRound.endOfRound();
|
||||||
|
assertTrue(roundEnded);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
assertTrue(roundScore.getWinners().get(i) == (i == 3));
|
||||||
|
}
|
||||||
|
assertEquals(-3, (int) roundScore.getPoints().get(0));
|
||||||
|
assertEquals(-50, (int) roundScore.getPoints().get(1));
|
||||||
|
assertEquals(-200, (int) roundScore.getPoints().get(2));
|
||||||
|
assertEquals(253, (int) roundScore.getPoints().get(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** */
|
||||||
|
@Test
|
||||||
|
public void testScoreWhenHeapEmpty() {
|
||||||
|
|
||||||
|
testRound.getEndOfRoundEvent().add(new IListener1<Score>() {
|
||||||
|
@Override
|
||||||
|
public void handle(Score score) {
|
||||||
|
roundEnded = true;
|
||||||
|
roundScore = score;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
testRound.startRound();
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
testRoundState.players.get(i).hand = new Hand(gameSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
testRoundState.players.get(0).laidOut = true;
|
||||||
|
testRoundState.players.get(0).hand.drop(new Stone(1, RED),
|
||||||
|
new Position(0, 0));
|
||||||
|
testRoundState.players.get(0).hand.drop(new Stone(2, RED),
|
||||||
|
new Position(0, 0));
|
||||||
|
testRoundState.players.get(1).laidOut = true;
|
||||||
|
testRoundState.players.get(1).hand.drop(new Stone(3, RED),
|
||||||
|
new Position(0, 0));
|
||||||
|
testRoundState.players.get(2).laidOut = true;
|
||||||
|
testRoundState.players.get(2).hand.drop(new Stone(3, BLUE),
|
||||||
|
new Position(0, 0));
|
||||||
|
testRoundState.players.get(3).laidOut = false;
|
||||||
|
testRoundState.players.get(3).hand.drop(new Stone(13, RED),
|
||||||
|
new Position(0, 0));
|
||||||
|
|
||||||
|
testRound.endOfRound();
|
||||||
|
assertTrue(roundEnded);
|
||||||
|
|
||||||
|
assertFalse(roundScore.getWinners().get(0));
|
||||||
|
assertTrue(roundScore.getWinners().get(1));
|
||||||
|
assertTrue(roundScore.getWinners().get(2));
|
||||||
|
assertFalse(roundScore.getWinners().get(3));
|
||||||
|
|
||||||
|
assertEquals(-3, (int) roundScore.getPoints().get(0));
|
||||||
|
assertEquals(-3, (int) roundScore.getPoints().get(1));
|
||||||
|
assertEquals(-3, (int) roundScore.getPoints().get(2));
|
||||||
|
assertEquals(-100, (int) roundScore.getPoints().get(3));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue