Strategy #31
|
@ -54,6 +54,7 @@ public class Game implements GameSpecification {
|
||||||
moveStrategies.add("User Move Strategy");
|
moveStrategies.add("User Move Strategy");
|
||||||
moveStrategies.add("Move List Strategy");
|
moveStrategies.add("Move List Strategy");
|
||||||
moveStrategies.add("Path Follow Move Strategy");
|
moveStrategies.add("Path Follow Move Strategy");
|
||||||
|
moveStrategies.add("Path Finder Move Strategy");
|
||||||
for (int i = 0; i < track.getCarCount(); i++) {
|
for (int i = 0; i < track.getCarCount(); i++) {
|
||||||
Car car = track.getCar(i);
|
Car car = track.getCar(i);
|
||||||
MoveStrategy moveStrategy = null;
|
MoveStrategy moveStrategy = null;
|
||||||
|
@ -61,14 +62,14 @@ public class Game implements GameSpecification {
|
||||||
String filePath;
|
String filePath;
|
||||||
int moveStrategie = userInterface.selectOption(
|
int moveStrategie = userInterface.selectOption(
|
||||||
"Select Strategy for Car " + i + " (" + track.getCarId(i) + ")", moveStrategies);
|
"Select Strategy for Car " + i + " (" + track.getCarId(i) + ")", moveStrategies);
|
||||||
switch (moveStrategie + 1) {
|
switch (moveStrategie) {
|
||||||
case 1:
|
case 0:
|
||||||
moveStrategy = new DoNotMoveStrategy();
|
moveStrategy = new DoNotMoveStrategy();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 1:
|
||||||
moveStrategy = new UserMoveStrategy(userInterface, i, track.getCarId(i));
|
moveStrategy = new UserMoveStrategy(userInterface, i, track.getCarId(i));
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 2:
|
||||||
filePath = ".\\moves\\" + selectedTrack.getName().split("\\.")[0] + "-car-" + track.getCar(i).getID() + ".txt";
|
filePath = ".\\moves\\" + selectedTrack.getName().split("\\.")[0] + "-car-" + track.getCar(i).getID() + ".txt";
|
||||||
try {
|
try {
|
||||||
moveStrategy = new MoveListStrategy(filePath);
|
moveStrategy = new MoveListStrategy(filePath);
|
||||||
|
@ -76,7 +77,7 @@ public class Game implements GameSpecification {
|
||||||
userInterface.printInformation("There is no Move-List implemented. Choose another Strategy!");
|
userInterface.printInformation("There is no Move-List implemented. Choose another Strategy!");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 3:
|
||||||
filePath = ".\\follower\\" + selectedTrack.getName().split("\\.")[0] + "_points.txt";
|
filePath = ".\\follower\\" + selectedTrack.getName().split("\\.")[0] + "_points.txt";
|
||||||
try {
|
try {
|
||||||
moveStrategy = new PathFollowerMoveStrategy(filePath, track.getCarPos(i));
|
moveStrategy = new PathFollowerMoveStrategy(filePath, track.getCarPos(i));
|
||||||
|
@ -84,6 +85,9 @@ public class Game implements GameSpecification {
|
||||||
userInterface.printInformation("There is no Point-List implemented. Choose another Strategy!");
|
userInterface.printInformation("There is no Point-List implemented. Choose another Strategy!");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 4:
|
||||||
|
moveStrategy = new PathFinderMoveStrategy(track, i);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
selectMoveStrategy(car, moveStrategy);
|
selectMoveStrategy(car, moveStrategy);
|
||||||
|
@ -165,14 +169,14 @@ public class Game implements GameSpecification {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int getWinner() {
|
public int getWinner() {
|
||||||
if (onlyOneCarLeft()) {
|
|
||||||
return currentCarIndex;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < track.getCarCount(); i++) {
|
for (int i = 0; i < track.getCarCount(); i++) {
|
||||||
if (track.getCar(i).getWinPoints() == 1) {
|
if (track.getCar(i).getWinPoints() == 1) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (onlyOneCarLeft()) {
|
||||||
|
return currentCarIndex;
|
||||||
|
}
|
||||||
return NO_WINNER;
|
return NO_WINNER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,10 +221,15 @@ public class Game implements GameSpecification {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int newWinPoints = track.calculateNewWinPoints(track.getCarPos(currentCarIndex), track.getCar(currentCarIndex).nextPosition());
|
||||||
|
if(newWinPoints == 1){
|
||||||
|
track.getCar(currentCarIndex).increaseWinPoints();
|
||||||
|
}else if(newWinPoints == -1){
|
||||||
|
track.getCar(currentCarIndex).deductWinPoints();
|
||||||
|
}
|
||||||
if (crashPosition != null) {
|
if (crashPosition != null) {
|
||||||
track.carDoesCrash(currentCarIndex, crashPosition);
|
track.carDoesCrash(currentCarIndex, crashPosition);
|
||||||
} else {
|
} else {
|
||||||
calculateWinner(track.getCarPos(currentCarIndex), track.getCar(currentCarIndex).nextPosition(), currentCarIndex);
|
|
||||||
track.moveCar(currentCarIndex);
|
track.moveCar(currentCarIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,6 +123,7 @@ public class Track implements TrackSpecification {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
//TODO: THIS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the finish line and saves it in a list, throws an Exception if none is found.
|
* Determines the finish line and saves it in a list, throws an Exception if none is found.
|
||||||
|
@ -276,8 +277,6 @@ public class Track implements TrackSpecification {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Config.SpaceType getSpaceType(PositionVector position) {
|
public Config.SpaceType getSpaceType(PositionVector position) {
|
||||||
//TODO: TO BE DELETED??
|
|
||||||
//isPositionVectorOnTrack(position); Should be used but we are not allowed to change method head. We don't use function anyway
|
|
||||||
char charAtPosition = track.get(position.getY()).charAt(position.getX());
|
char charAtPosition = track.get(position.getY()).charAt(position.getX());
|
||||||
ConfigSpecification.SpaceType[] spaceTypes = ConfigSpecification.SpaceType.values();
|
ConfigSpecification.SpaceType[] spaceTypes = ConfigSpecification.SpaceType.values();
|
||||||
for (ConfigSpecification.SpaceType spaceType : spaceTypes) {
|
for (ConfigSpecification.SpaceType spaceType : spaceTypes) {
|
||||||
|
@ -286,7 +285,7 @@ public class Track implements TrackSpecification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return ConfigSpecification.SpaceType.WALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -432,6 +431,53 @@ public class Track implements TrackSpecification {
|
||||||
return pathList;
|
return pathList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will check if a car is passing the finishline.
|
||||||
|
* If the car is passing the finishline in the wrong direction, the car will lose a winpoint.
|
||||||
|
* If the car is passing the finishline in the correct direction, the car will gain a winpoint.
|
||||||
|
* @param start the startposition of the car
|
||||||
|
* @param finish the expected finishpositon of the car after the move
|
||||||
|
* @return Number of new Winpoints for the current player.
|
||||||
|
*/
|
||||||
|
public int calculateNewWinPoints(PositionVector start, PositionVector finish) {
|
||||||
|
List<PositionVector> path = calculatePointsOnPath(start, finish);
|
||||||
|
for (PositionVector point : path) {
|
||||||
|
switch (getSpaceType(point)) {
|
||||||
|
case FINISH_UP:
|
||||||
|
if (start.getY() > finish.getY()) {
|
||||||
|
return 1;
|
||||||
|
} else if (start.getY() < finish.getY()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FINISH_DOWN:
|
||||||
|
if (start.getY() < finish.getY()) {
|
||||||
|
return 1;
|
||||||
|
} else if (start.getY() > finish.getY()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FINISH_RIGHT:
|
||||||
|
if (start.getX() < finish.getX()) {
|
||||||
|
return 1;
|
||||||
|
} else if (start.getX() > finish.getX()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FINISH_LEFT:
|
||||||
|
if (start.getX() > finish.getX()) {
|
||||||
|
return 1;
|
||||||
|
} else if (start.getX() < finish.getX()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a String representation of the track, including the car locations.
|
* Return a String representation of the track, including the car locations.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,169 @@
|
||||||
|
package ch.zhaw.pm2.racetrack.strategy;
|
||||||
|
|
||||||
|
import ch.zhaw.pm2.racetrack.PositionVector;
|
||||||
|
import ch.zhaw.pm2.racetrack.Track;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PathFinderMoveStrategy implements MoveStrategy{
|
||||||
|
private Track track;
|
||||||
|
private int carIndex;
|
||||||
|
private List<PositionVector.Direction> moveList;
|
||||||
|
private int pointer;
|
||||||
|
private List<PositionVector.Direction> allDirections;
|
||||||
|
private List<State> calculatedStates;
|
||||||
|
|
||||||
|
|
||||||
|
public PathFinderMoveStrategy(Track track, int carIndex) {
|
||||||
|
this.track = track;
|
||||||
|
this.carIndex = carIndex;
|
||||||
|
allDirections = Arrays.asList(PositionVector.Direction.values());
|
||||||
|
createMoveList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createMoveList(){
|
||||||
|
pointer = -1;
|
||||||
|
calculatedStates = new ArrayList<>();
|
||||||
|
PossibleMove finishedMove = null;
|
||||||
|
List<PossibleMove> possibleMoves= new ArrayList<>();
|
||||||
|
for(PositionVector.Direction direction : allDirections){
|
||||||
|
PossibleMove newMove = new PossibleMove(null, direction);
|
||||||
|
if(! newMove.crashed()){
|
||||||
|
possibleMoves.add(newMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
while(finishedMove == null){
|
||||||
|
List<PossibleMove> newMoves = new ArrayList<>();
|
||||||
|
for(PossibleMove previousMove : possibleMoves){
|
||||||
|
for(PositionVector.Direction direction : allDirections){
|
||||||
|
PossibleMove newMove = new PossibleMove(previousMove, direction);
|
||||||
|
State newState = new State(newMove.endPosition, newMove.endVelocity);
|
||||||
|
if(! (newMove.crashed() || alreadyCalculated(newState) || finishedMove != null)){
|
||||||
|
if(newMove.finished()){
|
||||||
|
finishedMove = newMove;
|
||||||
|
} else {
|
||||||
|
calculatedStates.add(newState);
|
||||||
|
newMoves.add(newMove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
possibleMoves = newMoves;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
moveList = finishedMove.directions;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean alreadyCalculated(State state){
|
||||||
|
for(State calculatedState: calculatedStates){
|
||||||
|
if(state.equals(calculatedState)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class State{
|
||||||
|
PositionVector position;
|
||||||
|
PositionVector velocity;
|
||||||
|
|
||||||
|
public State(PositionVector position, PositionVector velocity){
|
||||||
|
this.position = position;
|
||||||
|
this.velocity = velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(State compareState){
|
||||||
|
if(compareState.position.equals(position) && compareState.velocity.equals(velocity)){
|
||||||
|
return true;
|
||||||
|
} else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class PossibleMove {
|
||||||
|
List<PositionVector.Direction> directions;
|
||||||
|
PositionVector startPosition;
|
||||||
|
PositionVector endPosition;
|
||||||
|
PositionVector endVelocity;
|
||||||
|
|
||||||
|
|
||||||
|
public PossibleMove(PossibleMove previousMove, PositionVector.Direction nextDirection){
|
||||||
|
PositionVector startVelocity;
|
||||||
|
|
||||||
|
directions = new ArrayList<>();
|
||||||
|
if(previousMove != null){
|
||||||
|
directions.addAll(previousMove.directions);
|
||||||
|
startPosition = previousMove.endPosition;
|
||||||
|
startVelocity = previousMove.endVelocity;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
startPosition = track.getCarPos(carIndex);
|
||||||
|
startVelocity = track.getCar(carIndex).getVelocity();
|
||||||
|
}
|
||||||
|
directions.add(nextDirection);
|
||||||
|
endVelocity = new PositionVector(startVelocity.getX() + nextDirection.vector.getX(), startVelocity.getY() + nextDirection.vector.getY());
|
||||||
|
endPosition = new PositionVector(startPosition.getX() + endVelocity.getX(), startPosition.getY() + endVelocity.getY());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean finished(){
|
||||||
|
if(track.calculateNewWinPoints(startPosition, endPosition) == 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean crashed() {
|
||||||
|
List<PositionVector> points = track.calculatePointsOnPath(startPosition, endPosition);
|
||||||
|
for(PositionVector point : points) {
|
||||||
|
if (track.willCrashAtPosition(carIndex, point)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(track.calculateNewWinPoints(startPosition, endPosition) == -1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionVector.Direction nextMove() { //TODO check for crash and recreate movelist if crash
|
||||||
|
pointer += 1;
|
||||||
|
if (pointer < moveList.size()) {
|
||||||
|
PositionVector.Direction direction = moveList.get(pointer);
|
||||||
|
PositionVector currentVelocity = track.getCarVelocity(carIndex);
|
||||||
|
PositionVector newVelocity = new PositionVector(currentVelocity.getX() + direction.vector.getX(), currentVelocity.getY() + direction.vector.getY());
|
||||||
|
PositionVector currentPosition = track.getCarPos(carIndex);
|
||||||
|
PositionVector newPosition = new PositionVector(currentPosition.getX() + newVelocity.getX(), currentPosition.getY() + newVelocity.getY());
|
||||||
|
System.out.println("currentVelocity:" + currentVelocity.getX()+ ","+ currentVelocity.getY());
|
||||||
|
System.out.println("newVelocity:" + newVelocity.getX()+ ","+ newVelocity.getY());
|
||||||
|
for(PositionVector point : track.calculatePointsOnPath(currentPosition, newPosition)){
|
||||||
|
if(track.willCrashAtPosition(carIndex, point)){
|
||||||
|
createMoveList();
|
||||||
|
pointer = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return moveList.get(pointer);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -178,7 +178,7 @@ class GameTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void crashA() {
|
void crashA() {
|
||||||
game = new Game(new interFace("Test",new Integer[]{0,1,1},new PositionVector.Direction[]{UP}));
|
game = new Game(new interFace("Test",new Integer[]{0,1,0},new PositionVector.Direction[]{UP}));
|
||||||
game.initPhase();
|
game.initPhase();
|
||||||
Assertions.assertEquals("b",game.gamePhase());
|
Assertions.assertEquals("b",game.gamePhase());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue