Compare commits
No commits in common. "main" and "PathFollowerMoveStrategy" have entirely different histories.
main
...
PathFollow
Binary file not shown.
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 115 KiB |
53
README.md
53
README.md
|
@ -1,51 +1,2 @@
|
||||||
|
# team02-AngryNerds-projekt1-racetrack
|
||||||
# PM2 Team 02 Projekt 1 Racetrack
|
PM2 Team 02 Projekt 1 Racetrack
|
||||||
Racetrack is a pen and paper game that dates back to the early 1960s in this version of the game, the game is digitalized and the math behind it is done automatically rather than calculated by hand and the winner gets informed automatically as well.
|
|
||||||
|
|
||||||
The aim of the game is to finish the race faster than your opponent or win by being the only survivor in case the other cars crash.
|
|
||||||
|
|
||||||
In order to not crash you have to keep in mind the acceleration and other player's car to get to the finish line safely.
|
|
||||||
# Testing
|
|
||||||
#### All test can be run by the terminal command:
|
|
||||||
gradlew test
|
|
||||||
# Initialization:
|
|
||||||
#### The game can be initialized by the terminal command:
|
|
||||||
gradlew run
|
|
||||||
You will then be prompted to select a track file from the selection by entering the corresponding number.
|
|
||||||
|
|
||||||
#### For each car that is taking part in the race a strategy has to be chosen there are the following options:
|
|
||||||
|
|
||||||
+ Do not move Strategy
|
|
||||||
> This Strategy sets the car stationary, and it won't make any moves during the game staying at the start point indefinitely.
|
|
||||||
+ User Move Strategy
|
|
||||||
> The player is prompted for each move to make a choice the different choices you are able to take are as following:
|
|
||||||
> > 1=down-left <br> 2=down<br> 3=down-right<br> 4=left<br> 5=no acceleration<br> 6=right <br> 7=up-left<br> 8=up<br> 9=up-right<br> it is also possible to leave the game when it is your turn by entering 10
|
|
||||||
+ Move List Strategy
|
|
||||||
> For this strategy a predefined list of moves have to be given, the list may contain all allowed moves like mentioned in User Move Strategy
|
|
||||||
> > To create your own Move List strategy it needs to be located in /racetrack/moves and be named as *track_name*-car-*character_of_car*.txt and be a txt file.
|
|
||||||
+ Path Follow Move Strategy
|
|
||||||
> A list of points given in a txt file where on each lime a coordinate is placed like (X:24, Y:22) gets used to calculate a path which makes the car cross each point.
|
|
||||||
> > To create your own follow move strategy it needs to be located in /racetrack/moves and be named as *track_name*_points.txt and be a txt file.
|
|
||||||
+ Path Finder Strategy
|
|
||||||
> The pathfinder Strategy Calculates a route itself and follows it direction fully automatically.
|
|
||||||
|
|
||||||
The shown Track can be interpreted as following:<br>
|
|
||||||
'spaces' are part of the raceable track.<br>
|
|
||||||
'#' is a Wall<br>
|
|
||||||
'>,<,^,v' are finish line components<br>
|
|
||||||
'X' is shown if a car crashes at its crash location.<br>
|
|
||||||
And every other character represents a car.
|
|
||||||
> To create your own track it needs to be located inside /racetrack/tracks and be a txt file.
|
|
||||||
### Determining a winner
|
|
||||||
The winner gets determined automatically. <br> The car that first passes the finish line (doing a complete round) is given the win, if all car except one crash the surviving car will be crowned as the winner.<br>The game will inform you of this, and you will have the option to quit the game or play another match.
|
|
||||||
|
|
||||||
## Branching Model
|
|
||||||
We choose a simple branching model where all starting features got a branch and where merged into the main branch, some branches who needed unfinished code to be completed where taken from the game branch but merged into the main at the end as well.<br> Since there was just one end product we abstained from using a development branch and merges where done straight into main branch.<br>Commits which contain only documentation and doesn't change any functionality are committed directly into the Main branch.
|
|
||||||
|
|
||||||
## Class Diagramm
|
|
||||||
To create the best possible insight, all methods that are in the classes that we edited are shown completely. Including the private methods, since they can clearly be distinguished from the public ones through their prefix. <br>
|
|
||||||
However, the classes that were already given, i.e. not editable, are also in the class diagram for clarity, but the methods had been omitted since they can be found in the documentation, and the interfaces are just there for grading test purposes. <br><br>
|
|
||||||
![Classdiagram of this program](./Klassendiagramm.svg)
|
|
||||||
|
|
||||||
## GitHub Project
|
|
||||||
Our GitHub Project can be found here: [GitHubProject](https://github.zhaw.ch/PM2-IT21bWIN-ruiz-mach-krea/team02-AngryNerds-projekt1-racetrack/projects)
|
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
(X:28, Y:22)
|
|
||||||
(X:31, Y:22)
|
|
||||||
(X:34, Y:22)
|
|
||||||
(X:37, Y:22)
|
|
||||||
(X:40, Y:22)
|
(X:40, Y:22)
|
||||||
(X:43, Y:22)
|
(X:43, Y:22)
|
||||||
(X:46, Y:21)
|
(X:46, Y:21)
|
||||||
|
|
|
@ -35,3 +35,6 @@ UP_RIGHT
|
||||||
UP_RIGHT
|
UP_RIGHT
|
||||||
RIGHT
|
RIGHT
|
||||||
RIGHT
|
RIGHT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,14 @@ package ch.zhaw.pm2.racetrack;
|
||||||
import ch.zhaw.pm2.racetrack.given.CarSpecification;
|
import ch.zhaw.pm2.racetrack.given.CarSpecification;
|
||||||
import ch.zhaw.pm2.racetrack.strategy.MoveStrategy;
|
import ch.zhaw.pm2.racetrack.strategy.MoveStrategy;
|
||||||
|
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class representing a car on the racetrack.
|
* Class representing a car on the racetrack.
|
||||||
* Uses {@link PositionVector} to store current position on the track grid and current velocity vector.
|
* Uses {@link PositionVector} to store current position on the track grid and current velocity vector.
|
||||||
* Each car has an identifier character which represents the car on the racetrack board.
|
* Each car has an identifier character which represents the car on the race track board.
|
||||||
* Also keeps the state, if the car is crashed (not active anymore). The state can not be changed back to uncrashed.
|
* Also keeps the state, if the car is crashed (not active anymore). The state can not be changed back to uncrashed.
|
||||||
* The velocity is changed by providing an acceleration vector.
|
* The velocity is changed by providing an acelleration vector.
|
||||||
* The car is able to calculate the endpoint of its next position and on request moves to it.
|
* The car is able to calculate the endpoint of its next position and on request moves to it.
|
||||||
*/
|
*/
|
||||||
public class Car implements CarSpecification {
|
public class Car implements CarSpecification {
|
||||||
|
@ -44,8 +46,7 @@ public class Car implements CarSpecification {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for class Car
|
* Constructor for class Car
|
||||||
*
|
* @param id unique Car identification
|
||||||
* @param id unique Car identification
|
|
||||||
* @param position initial position of the Car
|
* @param position initial position of the Car
|
||||||
*/
|
*/
|
||||||
public Car(char id, PositionVector position) {
|
public Car(char id, PositionVector position) {
|
||||||
|
@ -58,29 +59,18 @@ public class Car implements CarSpecification {
|
||||||
*
|
*
|
||||||
* @return id of the car.
|
* @return id of the car.
|
||||||
*/
|
*/
|
||||||
public char getID() {
|
public char getID(){
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Increases the winpoints by one
|
|
||||||
*/
|
|
||||||
public void increaseWinPoints() {
|
public void increaseWinPoints() {
|
||||||
winPoints++;
|
winPoints ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Decreases the winpoints by one
|
|
||||||
*/
|
|
||||||
public void deductWinPoints() {
|
public void deductWinPoints() {
|
||||||
winPoints--;
|
winPoints --;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current value of winpoints.
|
|
||||||
*
|
|
||||||
* @return winpoints of the car
|
|
||||||
*/
|
|
||||||
public int getWinPoints() {
|
public int getWinPoints() {
|
||||||
return winPoints;
|
return winPoints;
|
||||||
}
|
}
|
||||||
|
@ -90,14 +80,13 @@ public class Car implements CarSpecification {
|
||||||
*
|
*
|
||||||
* @return velocity current velocity of the car.
|
* @return velocity current velocity of the car.
|
||||||
*/
|
*/
|
||||||
public PositionVector getVelocity() {
|
public PositionVector getVelocity(){
|
||||||
return velocity;
|
return velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set this Car position directly, regardless of current position and velocity.
|
* Set this Car position directly, regardless of current position and velocity.
|
||||||
* This should only be used by the game controller in rare cases to set the crash or winning position.
|
* This should only be used by the game controller in rare cases to set the crash or winning position.
|
||||||
* The next position is normally automatically calculated and set in the {@link #move()} method.
|
* The next position is normaly automatically calculated and set in the {@link #move()} method.
|
||||||
*
|
*
|
||||||
* @param position The new position to set the car directly to.
|
* @param position The new position to set the car directly to.
|
||||||
* @throws IllegalArgumentException if invalid PositionVector is given.
|
* @throws IllegalArgumentException if invalid PositionVector is given.
|
||||||
|
@ -106,7 +95,8 @@ public class Car implements CarSpecification {
|
||||||
public void setPosition(final PositionVector position) {
|
public void setPosition(final PositionVector position) {
|
||||||
if (position.getX() < 0 || position.getY() < 0) {
|
if (position.getX() < 0 || position.getY() < 0) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
this.position = position;
|
this.position = position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,7 +109,7 @@ public class Car implements CarSpecification {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public PositionVector nextPosition() {
|
public PositionVector nextPosition() {
|
||||||
return new PositionVector(position.getX() + velocity.getX(), position.getY() + velocity.getY());
|
return new PositionVector(position.getX() + velocity.getX(),position.getY() + velocity.getY());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -133,10 +123,11 @@ public class Car implements CarSpecification {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void accelerate(PositionVector.Direction acceleration) {
|
public void accelerate(PositionVector.Direction acceleration) {
|
||||||
if (acceleration.vector.getX() < -1 || acceleration.vector.getX() > 1 ||
|
if(acceleration.vector.getX() < -1 || acceleration.vector.getX() > 1||
|
||||||
acceleration.vector.getY() < -1 || acceleration.vector.getY() > 1) {
|
acceleration.vector.getY() < -1 || acceleration.vector.getY() > 1) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
velocity = new PositionVector(velocity.getX() + acceleration.vector.getX(),
|
velocity = new PositionVector(velocity.getX() + acceleration.vector.getX(),
|
||||||
velocity.getY() + acceleration.vector.getY());
|
velocity.getY() + acceleration.vector.getY());
|
||||||
}
|
}
|
||||||
|
@ -151,7 +142,7 @@ public class Car implements CarSpecification {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the car as crashed
|
* Mark this Car as being crashed.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void crash() {
|
public void crash() {
|
||||||
|
@ -159,7 +150,7 @@ public class Car implements CarSpecification {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether this Car has been marked as crashed or not
|
* Returns whether this Car has been marked as crashed.
|
||||||
*
|
*
|
||||||
* @return Returns true if crash() has been called on this Car, false otherwise.
|
* @return Returns true if crash() has been called on this Car, false otherwise.
|
||||||
*/
|
*/
|
||||||
|
@ -169,20 +160,18 @@ public class Car implements CarSpecification {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current move Strategy
|
* Set move strategy
|
||||||
*
|
|
||||||
* @return the current move Strategy
|
|
||||||
*/
|
|
||||||
public MoveStrategy getMoveStrategy() {
|
|
||||||
return this.moveStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the move Strategy of the car.
|
|
||||||
*
|
|
||||||
* @param moveStrategy Strategy to be implemented
|
* @param moveStrategy Strategy to be implemented
|
||||||
*/
|
*/
|
||||||
public void setMoveStrategy(MoveStrategy moveStrategy) {
|
public void setMoveStrategy(MoveStrategy moveStrategy) {
|
||||||
this.moveStrategy = moveStrategy;
|
this.moveStrategy = moveStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current move strategy
|
||||||
|
* @return MoveStrategy
|
||||||
|
*/
|
||||||
|
public MoveStrategy getMoveStrategy() {
|
||||||
|
return this.moveStrategy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import ch.zhaw.pm2.racetrack.strategy.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
import static ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
||||||
|
@ -20,133 +19,87 @@ public class Game implements GameSpecification {
|
||||||
public static final int NO_WINNER = -1;
|
public static final int NO_WINNER = -1;
|
||||||
private Track track;
|
private Track track;
|
||||||
private int currentCarIndex;
|
private int currentCarIndex;
|
||||||
private final Config config;
|
|
||||||
private final UserInterface userInterface;
|
|
||||||
|
|
||||||
public Game(UserInterface userInterface, Config config) {
|
UserInterface userInterface;
|
||||||
|
|
||||||
|
public Game(UserInterface userInterface) {
|
||||||
this.userInterface = userInterface;
|
this.userInterface = userInterface;
|
||||||
this.config = config;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method will initialize the game. Therefore, it interacts with the user via UserInterface
|
public boolean initPhase() throws InvalidTrackFormatException {
|
||||||
*
|
File folder = new File("tracks");
|
||||||
* @return true if the initialization is completed. Returns false if there is an error.
|
File[] listOfFiles = folder.listFiles();
|
||||||
*/
|
if (listOfFiles.length > 0) {
|
||||||
public boolean initPhase() {
|
List<String> tracks = new ArrayList<>();
|
||||||
if (config.getTrackDirectory().listFiles().length > 0) {
|
for (File file : listOfFiles) {
|
||||||
File selectedTrack = config.getTrackDirectory().listFiles()[userInterface.selectOption("Select Track file", Arrays.asList(config.getTrackDirectory().list()))];
|
tracks.add(file.getName());
|
||||||
try {
|
|
||||||
selectTrack(selectedTrack);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
userInterface.printInformation("There is an unexpected Error with the track file Path. Add track files only to tracks path. Exit the Game and Fix the Problem");
|
|
||||||
return false;
|
|
||||||
} catch (InvalidTrackFormatException e) {
|
|
||||||
userInterface.printInformation("There is an unexpected Error with the track file. Format does not match specifications! Exit the Game and Fix the Problem");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
File selectedTrack = listOfFiles[userInterface.selectOption("Select Track file", tracks)];
|
||||||
|
selectTrack(selectedTrack);
|
||||||
List<String> moveStrategies = new ArrayList<>();
|
List<String> moveStrategies = new ArrayList<>();
|
||||||
moveStrategies.add("Do not move Strategy");
|
moveStrategies.add("Do not move Strategy");
|
||||||
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 carIndex = 0; carIndex < track.getCarCount(); carIndex++) {
|
Car car = track.getCar(i);
|
||||||
Car car = track.getCar(carIndex);
|
|
||||||
MoveStrategy moveStrategy = null;
|
MoveStrategy moveStrategy = null;
|
||||||
while (moveStrategy == null) {
|
while (moveStrategy == null) {
|
||||||
|
String filePath;
|
||||||
int moveStrategie = userInterface.selectOption(
|
int moveStrategie = userInterface.selectOption(
|
||||||
"Select Strategy for Car " + carIndex + " (" + track.getCarId(carIndex) + ")", moveStrategies);
|
"Select Strategy for Car " + i + " (" + track.getCarId(i) + ")", moveStrategies);
|
||||||
switch (moveStrategie) {
|
switch (moveStrategie + 1) {
|
||||||
case 0 -> moveStrategy = new DoNotMoveStrategy();
|
case 1:
|
||||||
case 1 -> moveStrategy = new UserMoveStrategy(userInterface, carIndex, track.getCarId(carIndex));
|
moveStrategy = new DoNotMoveStrategy();
|
||||||
case 2 -> moveStrategy = getMoveListStrategy(selectedTrack, carIndex);
|
break;
|
||||||
case 3 -> moveStrategy = getPathFollowerMoveStrategy(selectedTrack, carIndex);
|
case 2:
|
||||||
case 4 -> moveStrategy = new PathFinderMoveStrategy(track, carIndex);
|
moveStrategy = new UserMoveStrategy(userInterface, i, track.getCarId(i));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
filePath = ".\\moves\\" + selectedTrack.getName().split("\\.")[0] + "-car-" + track.getCar(i).getID() + ".txt";
|
||||||
|
try {
|
||||||
|
moveStrategy = new MoveListStrategy(filePath);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
userInterface.printInformation("There is no Move-List implemented. Choose another Strategy!");
|
||||||
|
}
|
||||||
|
//TODO: Backslash kompatibel für Linux
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
filePath = ".\\follower\\" + selectedTrack.getName().split("\\.")[0] + "_points.txt";
|
||||||
|
try {
|
||||||
|
moveStrategy = new PathFollowerMoveStrategy(filePath, track.getCarPos(i));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
userInterface.printInformation("There is no Point-List implemented. Choose another Strategy!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
selectMoveStrategy(car, moveStrategy);
|
selectMoveStrategy(car, moveStrategy);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
userInterface.printInformation("No track file found!");
|
userInterface.printInformation("No Trackfile found!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a PathFollowerMoveStrategy for a specific track and a specific car
|
* The functionality was taken out of init to automate testing
|
||||||
* @param selectedTrack the selected Track
|
|
||||||
* @param carIndex the Index of the car
|
|
||||||
* @return the created Movestrategy, null if File not found or invalid
|
|
||||||
*/
|
|
||||||
private MoveStrategy getPathFollowerMoveStrategy(File selectedTrack, int carIndex) {
|
|
||||||
File selectedFile = null;
|
|
||||||
MoveStrategy moveStrategy = null;
|
|
||||||
for (File file : config.getFollowerDirectory().listFiles()) {
|
|
||||||
if (file.toString().equals(config.getFollowerDirectory().toString() + "\\" + selectedTrack.getName().split("\\.")[0] + "_points.txt")) {
|
|
||||||
selectedFile = file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (selectedFile != null) {
|
|
||||||
try {
|
|
||||||
moveStrategy = new PathFollowerMoveStrategy(selectedFile, track.getCarPos(carIndex));
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
userInterface.printInformation("There is no Point-List implemented. Choose another Strategy!");
|
|
||||||
} catch (InvalidFileFormatException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
userInterface.printInformation("Invalid Point-List format. Change Strategy and clean Point-List");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
userInterface.printInformation("There is no Point-List implemented. Choose another Strategy!");
|
|
||||||
}
|
|
||||||
return moveStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* creates a MoveListStrategy for a specific track and a specific car
|
|
||||||
* @param selectedTrack the selected Track
|
|
||||||
* @param carIndex the Index of the car
|
|
||||||
* @return the created Movestrategy, null if File not found or invalid
|
|
||||||
*/
|
|
||||||
private MoveStrategy getMoveListStrategy(File selectedTrack, int carIndex) {
|
|
||||||
File selectedFile = null;
|
|
||||||
MoveStrategy moveStrategy = null;
|
|
||||||
for (File file : config.getMoveDirectory().listFiles()) {
|
|
||||||
if (file.toString().equals(config.getMoveDirectory().toString() + "\\" + selectedTrack.getName().split("\\.")[0] + "-car-" + track.getCar(carIndex).getID() + ".txt")) {
|
|
||||||
selectedFile = file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (selectedFile != null) {
|
|
||||||
try {
|
|
||||||
moveStrategy = new MoveListStrategy(selectedFile);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
userInterface.printInformation("There is no Move-List implemented. Choose another Strategy!");
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvalidFileFormatException e) {
|
|
||||||
userInterface.printInformation("Invalid Data in Move-List. Choose another Strategy and clean the File");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
userInterface.printInformation("There is no Move-List implemented. Choose another Strategy!");
|
|
||||||
}
|
|
||||||
return moveStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Selects the desired track and returns it.
|
|
||||||
* The functionality was taken out of init to automate testing.
|
|
||||||
*
|
*
|
||||||
* @param selectedTrack the Track which was selected by user
|
* @param selectedTrack
|
||||||
*/
|
*/
|
||||||
Track selectTrack(File selectedTrack) throws InvalidTrackFormatException, FileNotFoundException {
|
Track selectTrack(File selectedTrack) {
|
||||||
track = new Track(selectedTrack);
|
try {
|
||||||
return track;
|
track = new Track(selectedTrack);
|
||||||
|
return track;
|
||||||
|
} catch (FileNotFoundException | PositionVectorNotValid | InvalidTrackFormatException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a desired move strategy for a desired car.
|
|
||||||
* The functionality was taken out of init to automate testing
|
* The functionality was taken out of init to automate testing
|
||||||
*
|
*
|
||||||
* @param car to set the MoveStrategy
|
* @param car to set the MoveStrategy
|
||||||
|
@ -168,7 +121,7 @@ public class Game implements GameSpecification {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the id of the specified car.
|
* Get the id of the specified car.
|
||||||
*
|
*
|
||||||
* @param carIndex The zero-based carIndex number
|
* @param carIndex The zero-based carIndex number
|
||||||
* @return A char containing the id of the car
|
* @return A char containing the id of the car
|
||||||
|
@ -207,14 +160,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,12 +194,13 @@ public class Game implements GameSpecification {
|
||||||
* <p>The calling method must check the winner state and decide how to go on. If the winner is different
|
* <p>The calling method must check the winner state and decide how to go on. If the winner is different
|
||||||
* than {@link Game#NO_WINNER}, or the current car is already marked as crashed the method returns immediately.</p>
|
* than {@link Game#NO_WINNER}, or the current car is already marked as crashed the method returns immediately.</p>
|
||||||
*
|
*
|
||||||
* @param acceleration A Direction containing the current car's acceleration vector (-1,0,1) in x and y direction
|
* @param acceleration A Direction containing the current cars acceleration vector (-1,0,1) in x and y direction
|
||||||
* for this turn
|
* for this turn
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void doCarTurn(Direction acceleration) {
|
public void doCarTurn(Direction acceleration) throws PositionVectorNotValid {
|
||||||
track.getCar(currentCarIndex).accelerate(acceleration);
|
track.getCar(currentCarIndex).accelerate(acceleration);
|
||||||
|
|
||||||
PositionVector crashPosition = null;
|
PositionVector crashPosition = null;
|
||||||
List<PositionVector> positionList = calculatePath(track.getCarPos(currentCarIndex), track.getCar(currentCarIndex).nextPosition());
|
List<PositionVector> positionList = calculatePath(track.getCarPos(currentCarIndex), track.getCar(currentCarIndex).nextPosition());
|
||||||
for (int i = 0; i < positionList.size(); i++) {
|
for (int i = 0; i < positionList.size(); i++) {
|
||||||
|
@ -259,45 +213,27 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public String gamePhase() throws PositionVectorNotValid {
|
||||||
* This method is in charge of changing the players and checking if a winner is found if there is no winner null will be returned.
|
while (carsMoving() && getWinner() == NO_WINNER) {
|
||||||
* If a winner is found the game will return the char of the winning player.
|
|
||||||
*
|
|
||||||
* @return the ID of the winning car return null if there is no winner.
|
|
||||||
*/
|
|
||||||
public String gamePhase() {
|
|
||||||
boolean quit = false;
|
|
||||||
while (carsMoving() && getWinner() == NO_WINNER && !quit) {
|
|
||||||
userInterface.printInformation("Player " + track.getCar(currentCarIndex).getID() + "'s turn!");
|
|
||||||
userInterface.printTrack(track);
|
userInterface.printTrack(track);
|
||||||
Direction direction;
|
Direction direction;
|
||||||
direction = track.getCar(currentCarIndex).getMoveStrategy().nextMove();
|
direction = track.getCar(currentCarIndex).getMoveStrategy().nextMove();
|
||||||
if (direction == null) {
|
if (direction == null) {
|
||||||
if (track.getCar(currentCarIndex).getMoveStrategy() instanceof UserMoveStrategy) {
|
track.getCar(currentCarIndex).setMoveStrategy(new DoNotMoveStrategy());
|
||||||
quit = true;
|
direction = track.getCar(currentCarIndex).getMoveStrategy().nextMove(); //TODO: Entfernen?
|
||||||
direction = Direction.NONE;
|
}else {
|
||||||
} else {
|
doCarTurn(direction);
|
||||||
track.getCar(currentCarIndex).setMoveStrategy(new DoNotMoveStrategy());
|
|
||||||
direction = track.getCar(currentCarIndex).getMoveStrategy().nextMove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
doCarTurn(direction);
|
|
||||||
switchToNextActiveCar();
|
switchToNextActiveCar();
|
||||||
}
|
}
|
||||||
userInterface.printInformation("The game has finished!");
|
|
||||||
userInterface.printTrack(track);
|
userInterface.printTrack(track);
|
||||||
int indexWinner = getWinner();
|
int indexWinner = getWinner();
|
||||||
if (indexWinner == NO_WINNER) {
|
if (indexWinner == NO_WINNER) {
|
||||||
|
@ -318,6 +254,7 @@ public class Game implements GameSpecification {
|
||||||
currentCarIndex++;
|
currentCarIndex++;
|
||||||
}
|
}
|
||||||
} while (track.getCar(currentCarIndex).isCrashed());
|
} while (track.getCar(currentCarIndex).isCrashed());
|
||||||
|
// TODO: evtl andere Kapselung
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -335,9 +272,104 @@ public class Game implements GameSpecification {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<PositionVector> calculatePath(PositionVector startPosition, PositionVector endPosition) {
|
public List<PositionVector> calculatePath(PositionVector startPosition, PositionVector endPosition) {
|
||||||
return track.calculatePointsOnPath(startPosition, endPosition);
|
ArrayList<PositionVector> pathList = new ArrayList<>();
|
||||||
|
// Use Bresenham's algorithm to determine positions.
|
||||||
|
int x = startPosition.getX();
|
||||||
|
int y = startPosition.getY();
|
||||||
|
|
||||||
|
// Relative Distance (x & y axis) between end- and starting position
|
||||||
|
int diffX = endPosition.getX() - startPosition.getX();
|
||||||
|
int diffY = endPosition.getY() - startPosition.getY();
|
||||||
|
|
||||||
|
// Absolute distance (x & y axis) between end- and starting position
|
||||||
|
int distX = Math.abs(diffX);
|
||||||
|
int distY = Math.abs(diffY);
|
||||||
|
|
||||||
|
// Direction of vector on x & y axis (-1: to left/down, 0: none, +1 : to right/up)
|
||||||
|
int dirX = Integer.signum(diffX);
|
||||||
|
int dirY = Integer.signum(diffY);
|
||||||
|
|
||||||
|
// Determine which axis is the fast direction and set parallel/diagonal step values
|
||||||
|
int parallelStepX, parallelStepY;
|
||||||
|
int diagonalStepX, diagonalStepY;
|
||||||
|
int distanceSlowAxis, distanceFastAxis;
|
||||||
|
if (distX > distY) {
|
||||||
|
// x axis is the 'fast' direction
|
||||||
|
parallelStepX = dirX;
|
||||||
|
parallelStepY = 0; // parallel step only moves in x direction
|
||||||
|
diagonalStepX = dirX;
|
||||||
|
diagonalStepY = dirY; // diagonal step moves in both directions
|
||||||
|
distanceSlowAxis = distY;
|
||||||
|
distanceFastAxis = distX;
|
||||||
|
} else {
|
||||||
|
// y axis is the 'fast' direction
|
||||||
|
parallelStepX = 0;
|
||||||
|
parallelStepY = dirY; // parallel step only moves in y direction
|
||||||
|
diagonalStepX = dirX;
|
||||||
|
diagonalStepY = dirY; // diagonal step moves in both directions
|
||||||
|
distanceSlowAxis = distX;
|
||||||
|
distanceFastAxis = distY;
|
||||||
|
}
|
||||||
|
|
||||||
|
int error = distanceFastAxis / 2;
|
||||||
|
for (int step = 0; step < distanceFastAxis; step++) {
|
||||||
|
error -= distanceSlowAxis;
|
||||||
|
if (error < 0) {
|
||||||
|
error += distanceFastAxis; // correct error value to be positive again
|
||||||
|
// step into slow direction; diagonal step
|
||||||
|
x += diagonalStepX;
|
||||||
|
y += diagonalStepY;
|
||||||
|
} else {
|
||||||
|
// step into fast direction; parallel step
|
||||||
|
x += parallelStepX;
|
||||||
|
y += parallelStepY;
|
||||||
|
}
|
||||||
|
|
||||||
|
pathList.add(new PositionVector(x, y));
|
||||||
|
}
|
||||||
|
return pathList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void calculateWinner(PositionVector start, PositionVector finish, int carIndex) {
|
||||||
|
List<PositionVector> path = calculatePath(start, finish);
|
||||||
|
for (PositionVector point : path) {
|
||||||
|
if (track.getSpaceType(point) != null) {
|
||||||
|
switch (track.getSpaceType(point)) {
|
||||||
|
case FINISH_UP:
|
||||||
|
if (start.getY() < finish.getY()) {
|
||||||
|
track.getCar(carIndex).increaseWinPoints();
|
||||||
|
} else if (start.getY() > finish.getY()) {
|
||||||
|
track.getCar(carIndex).deductWinPoints();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FINISH_DOWN:
|
||||||
|
if (start.getY() > finish.getY()) {
|
||||||
|
track.getCar(carIndex).increaseWinPoints();
|
||||||
|
} else if (start.getY() < finish.getY()) {
|
||||||
|
track.getCar(carIndex).deductWinPoints();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FINISH_RIGHT:
|
||||||
|
if (start.getX() < finish.getX()) {
|
||||||
|
track.getCar(carIndex).increaseWinPoints();
|
||||||
|
} else if (start.getX() > finish.getX()) {
|
||||||
|
track.getCar(carIndex).deductWinPoints();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FINISH_LEFT:
|
||||||
|
if (start.getX() > finish.getX()) {
|
||||||
|
track.getCar(carIndex).increaseWinPoints();
|
||||||
|
} else if (start.getX() < finish.getX()) {
|
||||||
|
track.getCar(carIndex).increaseWinPoints();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does indicate if a car would have a crash with a WALL space or another car at the given position.
|
* Does indicate if a car would have a crash with a WALL space or another car at the given position.
|
||||||
*
|
*
|
||||||
|
@ -346,15 +378,10 @@ public class Game implements GameSpecification {
|
||||||
* @return A boolean indicator if the car would crash with a WALL or another car.
|
* @return A boolean indicator if the car would crash with a WALL or another car.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean willCarCrash(int carIndex, PositionVector position) {
|
public boolean willCarCrash(int carIndex, PositionVector position) throws PositionVectorNotValid {
|
||||||
return track.willCrashAtPosition(carIndex, position);
|
return track.willCrashAtPosition(carIndex, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if there is just one player left in the game being able to make moves.
|
|
||||||
*
|
|
||||||
* @return true if there is just one car left false there are more than one car left in game
|
|
||||||
*/
|
|
||||||
public boolean onlyOneCarLeft() {
|
public boolean onlyOneCarLeft() {
|
||||||
int carsLeft = 0;
|
int carsLeft = 0;
|
||||||
for (int carIndex = 0; carIndex < track.getCarCount(); carIndex++) {
|
for (int carIndex = 0; carIndex < track.getCarCount(); carIndex++) {
|
||||||
|
@ -365,11 +392,6 @@ public class Game implements GameSpecification {
|
||||||
return !(carsLeft > 1);
|
return !(carsLeft > 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if all cars have implemented the do not move strategy, so the game can determine it will end in a draw.
|
|
||||||
*
|
|
||||||
* @return true if all players have implemented do not move false otherwise
|
|
||||||
*/
|
|
||||||
public boolean carsMoving() {
|
public boolean carsMoving() {
|
||||||
for (int carIndex = 0; carIndex < track.getCarCount(); carIndex++) {
|
for (int carIndex = 0; carIndex < track.getCarCount(); carIndex++) {
|
||||||
if (!(track.getCar(carIndex).isCrashed() || track.getCar(carIndex).getMoveStrategy().getClass() == DoNotMoveStrategy.class)) {
|
if (!(track.getCar(carIndex).isCrashed() || track.getCar(carIndex).getMoveStrategy().getClass() == DoNotMoveStrategy.class)) {
|
||||||
|
|
|
@ -1,19 +1,5 @@
|
||||||
package ch.zhaw.pm2.racetrack;
|
package ch.zhaw.pm2.racetrack;
|
||||||
|
|
||||||
/**
|
|
||||||
* Class for Exception when an invalid file format is used.
|
|
||||||
*/
|
|
||||||
public class InvalidFileFormatException extends Exception {
|
public class InvalidFileFormatException extends Exception {
|
||||||
public InvalidFileFormatException() {
|
// TODO: implementation
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor that is used when an error message is given with the exception.
|
|
||||||
*
|
|
||||||
* @param errorMessage is the message to be displayed
|
|
||||||
*/
|
|
||||||
public InvalidFileFormatException(String errorMessage) {
|
|
||||||
super(errorMessage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,5 @@
|
||||||
package ch.zhaw.pm2.racetrack;
|
package ch.zhaw.pm2.racetrack;
|
||||||
|
|
||||||
/**
|
|
||||||
* Class for Exception when invalid track format is used.
|
|
||||||
*/
|
|
||||||
public class InvalidTrackFormatException extends Exception {
|
public class InvalidTrackFormatException extends Exception {
|
||||||
public InvalidTrackFormatException() {
|
// TODO: implementation
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor that is used when an error message is given with the exception.
|
|
||||||
*
|
|
||||||
* @param errorMessage is the message to be displayed
|
|
||||||
*/
|
|
||||||
public InvalidTrackFormatException(String errorMessage) {
|
|
||||||
super(errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,15 @@
|
||||||
package ch.zhaw.pm2.racetrack;
|
package ch.zhaw.pm2.racetrack;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
|
||||||
* Class containing the main method
|
|
||||||
*
|
|
||||||
* @author Roman Schenk
|
|
||||||
*/
|
|
||||||
public class Main {
|
public class Main {
|
||||||
/**
|
|
||||||
* Method creating the game and initializing the Configs and Userinterface.
|
public static void main(String[] args) throws InvalidTrackFormatException, PositionVectorNotValid {
|
||||||
* Starts and initializes a new game until the user decides to stop the game.
|
|
||||||
* In charge of closing the user interface when user decides to stop the game
|
|
||||||
*
|
|
||||||
* @param args no arguments needed
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) {
|
|
||||||
UserInterface userInterface = new UserInterface("Hello and Welcome to Racetrack by Team02-\"AngryNerds\"");
|
UserInterface userInterface = new UserInterface("Hello and Welcome to Racetrack by Team02-\"AngryNerds\"");
|
||||||
Config config = new Config();
|
|
||||||
while (true) {
|
while (true) {
|
||||||
Game game = new Game(userInterface, config);
|
Game game = new Game(userInterface);
|
||||||
String winner;
|
String winner;
|
||||||
if (game.initPhase()) {
|
if (game.initPhase()) {
|
||||||
winner = game.gamePhase();
|
winner = game.gamePhase();
|
||||||
|
@ -28,17 +17,19 @@ public class Main {
|
||||||
optionsNewGame.add("exit");
|
optionsNewGame.add("exit");
|
||||||
optionsNewGame.add("new game");
|
optionsNewGame.add("new game");
|
||||||
String winnerText;
|
String winnerText;
|
||||||
if (winner == null) {
|
if(winner == null){
|
||||||
winnerText = "There was no winner.";
|
winnerText = "There was no winner.";
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
winnerText = "The Winner was Car " + winner;
|
winnerText = "The Winner was Car " + winner;
|
||||||
}
|
}
|
||||||
int selectedOption = userInterface.selectOption(winnerText + "\nStart new Game?", optionsNewGame);
|
int selectedOption = userInterface.selectOption(winnerText + "\nStart new Game?", optionsNewGame);
|
||||||
if (selectedOption == 0) {
|
if(selectedOption == 0) {
|
||||||
userInterface.quit("Thank you and goodbye\npress enter to close the application.");
|
userInterface.quit("Thank you and goodbye\npress enter to close the application.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
userInterface.quit("The initialisation of the game failed. Press enter to close the application.");
|
userInterface.quit("The initialisation of the game failed. Press enter to close the application.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package ch.zhaw.pm2.racetrack;
|
||||||
|
|
||||||
|
public class PositionVectorNotValid extends Throwable {
|
||||||
|
public PositionVectorNotValid(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PositionVectorNotValid() {}
|
||||||
|
}
|
|
@ -3,10 +3,7 @@ package ch.zhaw.pm2.racetrack;
|
||||||
import ch.zhaw.pm2.racetrack.given.ConfigSpecification;
|
import ch.zhaw.pm2.racetrack.given.ConfigSpecification;
|
||||||
import ch.zhaw.pm2.racetrack.given.TrackSpecification;
|
import ch.zhaw.pm2.racetrack.given.TrackSpecification;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
@ -45,9 +42,9 @@ import java.util.Scanner;
|
||||||
* There are 1 to {@link Config#MAX_CARS} allowed. </li>
|
* There are 1 to {@link Config#MAX_CARS} allowed. </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <p>All lines must have the same length, used to initialize the grid width.
|
* <p>All lines must have the same length, used to initialize the grid width).
|
||||||
* Beginning empty lines are skipped.
|
* Beginning empty lines are skipped.
|
||||||
* The tracks ends with the first empty line or the file end.<br>
|
* The the tracks ends with the first empty line or the file end.<br>
|
||||||
* An {@link InvalidTrackFormatException} is thrown, if
|
* An {@link InvalidTrackFormatException} is thrown, if
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>not all track lines have the same length</li>
|
* <li>not all track lines have the same length</li>
|
||||||
|
@ -55,25 +52,24 @@ import java.util.Scanner;
|
||||||
* <li>the file contains more than {@link Config#MAX_CARS} cars</li>
|
* <li>the file contains more than {@link Config#MAX_CARS} cars</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <p>The Track can return a String representing the current state of the race (including car positions)</p>
|
* <p>The Track can return a String representing the current state of the race (including car positons)</p>
|
||||||
*/
|
*/
|
||||||
public class Track implements TrackSpecification {
|
public class Track implements TrackSpecification {
|
||||||
|
|
||||||
public static final char CRASH_INDICATOR = 'X';
|
public static final char CRASH_INDICATOR = 'X';
|
||||||
private final List<String> track;
|
private List<String> track;
|
||||||
private final List<Car> cars;
|
private List<Car> cars;
|
||||||
private final List<PositionVector> finishLine;
|
private final List<PositionVector> finishLine;
|
||||||
private ConfigSpecification.SpaceType finishTyp;
|
private ConfigSpecification.SpaceType finishTyp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the Track from the given track File including the cars.
|
* Initialize a Track from the given track file.
|
||||||
* Throws a corresponding error if one of the conditions are not met to build a track.
|
|
||||||
*
|
*
|
||||||
* @param trackFile Reference to a file containing the track data
|
* @param trackFile Reference to a file containing the track data
|
||||||
* @throws FileNotFoundException if the given track file could not be found
|
* @throws FileNotFoundException if the given track file could not be found
|
||||||
* @throws InvalidTrackFormatException if the track file contains invalid data (no track lines, ...)
|
* @throws InvalidTrackFormatException if the track file contains invalid data (no tracklines, ...)
|
||||||
*/
|
*/
|
||||||
public Track(File trackFile) throws FileNotFoundException, InvalidTrackFormatException {
|
public Track(File trackFile) throws FileNotFoundException, InvalidTrackFormatException, PositionVectorNotValid {
|
||||||
track = new ArrayList<>();
|
track = new ArrayList<>();
|
||||||
cars = new ArrayList<>();
|
cars = new ArrayList<>();
|
||||||
finishLine = new ArrayList<>();
|
finishLine = new ArrayList<>();
|
||||||
|
@ -89,17 +85,13 @@ public class Track implements TrackSpecification {
|
||||||
* @throws FileNotFoundException if the FilePath is invalid.
|
* @throws FileNotFoundException if the FilePath is invalid.
|
||||||
*/
|
*/
|
||||||
private void readFile(File trackFile) throws FileNotFoundException {
|
private void readFile(File trackFile) throws FileNotFoundException {
|
||||||
Scanner scanner = new Scanner(new FileInputStream(trackFile), StandardCharsets.UTF_8);
|
Scanner scanner = new Scanner(new FileInputStream(trackFile),"UTF-8");
|
||||||
while (scanner.hasNextLine()) {
|
while (scanner.hasNextLine()) {
|
||||||
track.add(scanner.nextLine());
|
track.add(scanner.nextLine());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Goes through the track ArrayList and determines the locations of each car and initializes them at the location.
|
|
||||||
*
|
|
||||||
* @throws InvalidTrackFormatException is thrown if a car is found more than once inside the track.
|
|
||||||
*/
|
|
||||||
private void addCars() throws InvalidTrackFormatException {
|
private void addCars() throws InvalidTrackFormatException {
|
||||||
ConfigSpecification.SpaceType[] spaceTypes = ConfigSpecification.SpaceType.values();
|
ConfigSpecification.SpaceType[] spaceTypes = ConfigSpecification.SpaceType.values();
|
||||||
List<Character> allSpaceTypesAsChar = new ArrayList<>();
|
List<Character> allSpaceTypesAsChar = new ArrayList<>();
|
||||||
|
@ -109,26 +101,23 @@ public class Track implements TrackSpecification {
|
||||||
allSpaceTypesAsChar.add(spaceType.getValue());
|
allSpaceTypesAsChar.add(spaceType.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int yPosition = 0; yPosition < track.size(); yPosition++) {
|
|
||||||
String line = track.get(yPosition);
|
for (int j = 0; j < track.size(); j++) {
|
||||||
for (int xPosition = 0; xPosition < line.length(); xPosition++) {
|
String line = track.get(j);
|
||||||
char possibleCarChar = line.charAt(xPosition);
|
for (int i = 0; i < line.length(); i++) {
|
||||||
|
char possibleCarChar = line.charAt(i);
|
||||||
if (!allSpaceTypesAsChar.contains(possibleCarChar)) {
|
if (!allSpaceTypesAsChar.contains(possibleCarChar)) {
|
||||||
if (usedSymbolForCar.contains(possibleCarChar)) {
|
if (usedSymbolForCar.contains(possibleCarChar)) {
|
||||||
throw new InvalidTrackFormatException("More than one car on track!");
|
throw new InvalidTrackFormatException();
|
||||||
}
|
}
|
||||||
usedSymbolForCar.add(possibleCarChar);
|
usedSymbolForCar.add(possibleCarChar);
|
||||||
cars.add(new Car(possibleCarChar, new PositionVector(xPosition, yPosition)));
|
cars.add(new Car(possibleCarChar, new PositionVector(i, j)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines the finish line and saves it in a list, throws an Exception if none is found.
|
|
||||||
*
|
|
||||||
* @throws InvalidTrackFormatException thrown if no finish line is found
|
|
||||||
*/
|
|
||||||
private void findFinish() throws InvalidTrackFormatException {
|
private void findFinish() throws InvalidTrackFormatException {
|
||||||
for (int i = 0; i < track.size(); i++) {
|
for (int i = 0; i < track.size(); i++) {
|
||||||
String line = track.get(i);
|
String line = track.get(i);
|
||||||
|
@ -142,22 +131,16 @@ public class Track implements TrackSpecification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (finishLine.size() == 0) {
|
if (finishLine.size() == 0) {
|
||||||
throw new InvalidTrackFormatException("No finish line found!");
|
throw new InvalidTrackFormatException();
|
||||||
}
|
}
|
||||||
finishTyp = getSpaceType(finishLine.get(0));
|
finishTyp = getSpaceType(finishLine.get(0));
|
||||||
for (PositionVector positionVector : finishLine) {
|
for (PositionVector positionVector : finishLine) {
|
||||||
if (getSpaceType(positionVector) != finishTyp) {
|
if (getSpaceType(positionVector) != finishTyp) {
|
||||||
throw new InvalidTrackFormatException("Inconsistent finish line found!");
|
throw new InvalidTrackFormatException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to find the PositionVector of a chosen character
|
|
||||||
*
|
|
||||||
* @param symbol char that we are looking for on the track
|
|
||||||
* @return the PositionVector of the desired char
|
|
||||||
*/
|
|
||||||
private PositionVector findChar(char symbol) {
|
private PositionVector findChar(char symbol) {
|
||||||
PositionVector vector = null;
|
PositionVector vector = null;
|
||||||
for (int i = 0; i < track.size(); i++) {
|
for (int i = 0; i < track.size(); i++) {
|
||||||
|
@ -171,12 +154,6 @@ public class Track implements TrackSpecification {
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method that places a character at a chosen position
|
|
||||||
*
|
|
||||||
* @param positionVector position where char will be placed
|
|
||||||
* @param symbol char that should be placed at desired position
|
|
||||||
*/
|
|
||||||
private void drawCharOnTrackIndicator(PositionVector positionVector, char symbol) {
|
private void drawCharOnTrackIndicator(PositionVector positionVector, char symbol) {
|
||||||
String line = track.get(positionVector.getY());
|
String line = track.get(positionVector.getY());
|
||||||
line = line.substring(0, positionVector.getX()) + symbol + line.substring(positionVector.getX() + 1);
|
line = line.substring(0, positionVector.getX()) + symbol + line.substring(positionVector.getX() + 1);
|
||||||
|
@ -184,19 +161,30 @@ public class Track implements TrackSpecification {
|
||||||
track.add(positionVector.getY(), line);
|
track.add(positionVector.getY(), line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void isPositionVectorOnTrack(PositionVector positionVector) throws PositionVectorNotValid {
|
||||||
|
try{
|
||||||
|
track.get(positionVector.getY()).charAt(positionVector.getX());
|
||||||
|
}catch (IndexOutOfBoundsException e) {
|
||||||
|
throw new PositionVectorNotValid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method that returns the finish line as a List
|
* @return all Cars
|
||||||
*
|
*/
|
||||||
* @return finishLine List
|
public List<Car> getCars() {
|
||||||
|
return cars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return finishLine
|
||||||
*/
|
*/
|
||||||
public List<PositionVector> getFinishLine() {
|
public List<PositionVector> getFinishLine() {
|
||||||
return finishLine;
|
return finishLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the whole Track as List of Strings
|
* @return the track
|
||||||
*
|
|
||||||
* @return track as List of Strings
|
|
||||||
*/
|
*/
|
||||||
public List<String> getTrack() {
|
public List<String> getTrack() {
|
||||||
return track;
|
return track;
|
||||||
|
@ -215,7 +203,7 @@ public class Track implements TrackSpecification {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This Method does change the Position of the car inside the track object.
|
* This class does change the Position of the car only in the track.
|
||||||
*
|
*
|
||||||
* @param carIndex of the current car
|
* @param carIndex of the current car
|
||||||
*/
|
*/
|
||||||
|
@ -224,9 +212,9 @@ public class Track implements TrackSpecification {
|
||||||
//Removes the Car at Current Pos
|
//Removes the Car at Current Pos
|
||||||
drawCharOnTrackIndicator(carPositionVector, ConfigSpecification.SpaceType.TRACK.getValue());
|
drawCharOnTrackIndicator(carPositionVector, ConfigSpecification.SpaceType.TRACK.getValue());
|
||||||
|
|
||||||
//Redraw finish line if Car was on finish-line Position
|
//Redraw finishline if Car was on finish-line Position
|
||||||
for (PositionVector finishLinePositionVector : finishLine) {
|
for(PositionVector finishLinePositionVector : finishLine){
|
||||||
if (finishLinePositionVector.equals(carPositionVector)) {
|
if(finishLinePositionVector.equals(carPositionVector)){
|
||||||
drawCharOnTrackIndicator(carPositionVector, finishTyp.getValue());
|
drawCharOnTrackIndicator(carPositionVector, finishTyp.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,12 +225,13 @@ public class Track implements TrackSpecification {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This Method will check if the Car would crash at the specific position
|
* This Method will check if the Car could crash at the specific position
|
||||||
*
|
*
|
||||||
* @param positionVector the position to check if the car would crash
|
* @param positionVector the position to check if the car could crash
|
||||||
* @return true if crash otherwise false
|
* @return true if car would crash. Else false.
|
||||||
*/
|
*/
|
||||||
public boolean willCrashAtPosition(int carIndex, PositionVector positionVector) {
|
public boolean willCrashAtPosition(int carIndex, PositionVector positionVector) throws PositionVectorNotValid {
|
||||||
|
isPositionVectorOnTrack(positionVector); //TODO: remove this line? Or Method?
|
||||||
char charAtPosition = track.get(positionVector.getY()).charAt(positionVector.getX());
|
char charAtPosition = track.get(positionVector.getY()).charAt(positionVector.getX());
|
||||||
if (getCarId(carIndex) == charAtPosition) return false;
|
if (getCarId(carIndex) == charAtPosition) return false;
|
||||||
return !(charAtPosition == ConfigSpecification.SpaceType.TRACK.value ||
|
return !(charAtPosition == ConfigSpecification.SpaceType.TRACK.value ||
|
||||||
|
@ -253,12 +242,13 @@ public class Track implements TrackSpecification {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This Method will mark the Car as crashed inside the track and the car Object.
|
* This Method will make the Car Crash. In Track and in the Car Object
|
||||||
*
|
*
|
||||||
* @param carIndex of car that will be marked as crashed
|
* @param carIndex representing current Car
|
||||||
* @param crashPositionVector of the location of the crash
|
* @param crashPositionVector where the Crash did happen
|
||||||
*/
|
*/
|
||||||
public void carDoesCrash(int carIndex, PositionVector crashPositionVector) {
|
public void carDoesCrash(int carIndex, PositionVector crashPositionVector) throws PositionVectorNotValid{
|
||||||
|
isPositionVectorOnTrack(crashPositionVector); //TODO: remove this line? and Method?
|
||||||
PositionVector currentCarPosition = getCarPos(carIndex);
|
PositionVector currentCarPosition = getCarPos(carIndex);
|
||||||
drawCharOnTrackIndicator(new PositionVector(currentCarPosition.getX(), currentCarPosition.getY()), ConfigSpecification.SpaceType.TRACK.getValue());
|
drawCharOnTrackIndicator(new PositionVector(currentCarPosition.getX(), currentCarPosition.getY()), ConfigSpecification.SpaceType.TRACK.getValue());
|
||||||
Car car = cars.get(carIndex);
|
Car car = cars.get(carIndex);
|
||||||
|
@ -272,10 +262,11 @@ public class Track implements TrackSpecification {
|
||||||
* If the location is outside the track bounds, it is considered a wall.
|
* If the location is outside the track bounds, it is considered a wall.
|
||||||
*
|
*
|
||||||
* @param position The coordinates of the position to examine
|
* @param position The coordinates of the position to examine
|
||||||
* @return The type of space at the desired position
|
* @return The type of track position at the given location
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Config.SpaceType getSpaceType(PositionVector position) {
|
public Config.SpaceType getSpaceType(PositionVector position) {
|
||||||
|
//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) {
|
||||||
|
@ -284,13 +275,13 @@ public class Track implements TrackSpecification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ConfigSpecification.SpaceType.WALL;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the number of cars that are located in a track
|
* Return the number of cars.
|
||||||
*
|
*
|
||||||
* @return number of cars as int
|
* @return Number of cars
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int getCarCount() {
|
public int getCarCount() {
|
||||||
|
@ -347,7 +338,7 @@ public class Track implements TrackSpecification {
|
||||||
* If there is a crashed car at the position, {@link #CRASH_INDICATOR} is returned.
|
* If there is a crashed car at the position, {@link #CRASH_INDICATOR} is returned.
|
||||||
*
|
*
|
||||||
* @param y position Y-value
|
* @param y position Y-value
|
||||||
* @param x position X-value
|
* @param x position X-vlaue
|
||||||
* @param currentSpace char to return if no car is at position (x,y)
|
* @param currentSpace char to return if no car is at position (x,y)
|
||||||
* @return character representing position (x,y) on the track
|
* @return character representing position (x,y) on the track
|
||||||
*/
|
*/
|
||||||
|
@ -364,118 +355,6 @@ public class Track implements TrackSpecification {
|
||||||
return currentSpace.getValue();
|
return currentSpace.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines all points that lie between the two position vectors including the endpoint VectorPosition using the Bresenham algorithm.
|
|
||||||
*
|
|
||||||
* @param startPosition PositionVector of the finish coordinate
|
|
||||||
* @param endPosition PositionVector of the start coordinate
|
|
||||||
* @return ArrayList containing PositionVectors of all position that are between the start and finish including the finish position.
|
|
||||||
*/
|
|
||||||
public ArrayList<PositionVector> calculatePointsOnPath(PositionVector startPosition, PositionVector endPosition) {
|
|
||||||
ArrayList<PositionVector> pathList = new ArrayList<>();
|
|
||||||
// Use Bresenham's algorithm to determine positions.
|
|
||||||
int x = startPosition.getX();
|
|
||||||
int y = startPosition.getY();
|
|
||||||
|
|
||||||
// Relative Distance (x & y-axis) between end- and starting position
|
|
||||||
int diffX = endPosition.getX() - startPosition.getX();
|
|
||||||
int diffY = endPosition.getY() - startPosition.getY();
|
|
||||||
|
|
||||||
// Absolute distance (x & y-axis) between end- and starting position
|
|
||||||
int distX = Math.abs(diffX);
|
|
||||||
int distY = Math.abs(diffY);
|
|
||||||
|
|
||||||
// Direction of vector on x & y axis (-1: to left/down, 0: none, +1 : to right/up)
|
|
||||||
int dirX = Integer.signum(diffX);
|
|
||||||
int dirY = Integer.signum(diffY);
|
|
||||||
|
|
||||||
// Determine which axis is the fast direction and set parallel/diagonal step values
|
|
||||||
int parallelStepX, parallelStepY;
|
|
||||||
int diagonalStepX, diagonalStepY;
|
|
||||||
int distanceSlowAxis, distanceFastAxis;
|
|
||||||
if (distX > distY) {
|
|
||||||
// x-axis is the 'fast' direction
|
|
||||||
parallelStepX = dirX;
|
|
||||||
parallelStepY = 0; // parallel step only moves in x direction
|
|
||||||
diagonalStepX = dirX;
|
|
||||||
diagonalStepY = dirY; // diagonal step moves in both directions
|
|
||||||
distanceSlowAxis = distY;
|
|
||||||
distanceFastAxis = distX;
|
|
||||||
} else {
|
|
||||||
// y-axis is the 'fast' direction
|
|
||||||
parallelStepX = 0;
|
|
||||||
parallelStepY = dirY; // parallel step only moves in y direction
|
|
||||||
diagonalStepX = dirX;
|
|
||||||
diagonalStepY = dirY; // diagonal step moves in both directions
|
|
||||||
distanceSlowAxis = distX;
|
|
||||||
distanceFastAxis = distY;
|
|
||||||
}
|
|
||||||
|
|
||||||
int error = distanceFastAxis / 2;
|
|
||||||
for (int step = 0; step < distanceFastAxis; step++) {
|
|
||||||
error -= distanceSlowAxis;
|
|
||||||
if (error < 0) {
|
|
||||||
error += distanceFastAxis; // correct error value to be positive again
|
|
||||||
// step into slow direction; diagonal step
|
|
||||||
x += diagonalStepX;
|
|
||||||
y += diagonalStepY;
|
|
||||||
} else {
|
|
||||||
// step into fast direction; parallel step
|
|
||||||
x += parallelStepX;
|
|
||||||
y += parallelStepY;
|
|
||||||
}
|
|
||||||
|
|
||||||
pathList.add(new PositionVector(x, y));
|
|
||||||
}
|
|
||||||
return pathList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method will check if a car is passing the finish line.
|
|
||||||
* If the car is passing the finish line in the wrong direction, the car will lose a winpoint.
|
|
||||||
* If the car is passing the finish line in the correct direction, the car will gain a winpoint.
|
|
||||||
*
|
|
||||||
* @param start the start position of the car
|
|
||||||
* @param finish the expected finish position 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.
|
||||||
*
|
*
|
||||||
|
|
|
@ -6,31 +6,24 @@ import org.beryx.textio.TextTerminal;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
|
||||||
* Class representing the Userinterface.
|
|
||||||
* Used to get inputs from users via text io.
|
|
||||||
*
|
|
||||||
* @author Roman Schenk
|
|
||||||
*/
|
|
||||||
public class UserInterface {
|
public class UserInterface {
|
||||||
|
|
||||||
private final TextIO textIO;
|
private final TextIO textIO;
|
||||||
private final TextTerminal<?> textTerminal;
|
private final TextTerminal<?> textTerminal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a new Terminal Window and prints the welcome Text.
|
* Opens a new Terminal Window and prints the welcome Text
|
||||||
*
|
|
||||||
* @param welcomeText The Text which will be printed after the windows is opened.
|
* @param welcomeText The Text which will be printed after the windows is opened.
|
||||||
*/
|
*/
|
||||||
public UserInterface(String welcomeText) {
|
public UserInterface(String welcomeText) {
|
||||||
textIO = TextIoFactory.getTextIO();
|
textIO = TextIoFactory.getTextIO();
|
||||||
textTerminal = textIO.getTextTerminal();
|
textTerminal = textIO.getTextTerminal();
|
||||||
|
|
||||||
textTerminal.println(welcomeText + "\n");
|
textTerminal.println(welcomeText + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints the given Text in textTerminal
|
* Prints the given Text in textTerminal
|
||||||
*
|
|
||||||
* @param text The Text which should be printed.
|
* @param text The Text which should be printed.
|
||||||
*/
|
*/
|
||||||
public void printInformation(String text) {
|
public void printInformation(String text) {
|
||||||
|
@ -38,25 +31,23 @@ public class UserInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method which asks the user to choose one of the options given.
|
* asks the user to choose one of the options given.
|
||||||
*
|
* @param text Text which is printed befor the options are printed. Example: "Select Track file:"
|
||||||
* @param text Text which is printed before the options are printed. Example: "Select Track file:"
|
|
||||||
* @param options List with the options which can be selected.
|
* @param options List with the options which can be selected.
|
||||||
* @return the list index of the selected option
|
* @return the list index of the selected option
|
||||||
*/
|
*/
|
||||||
public int selectOption(String text, List<String> options) {
|
public int selectOption(String text, List<String> options) {
|
||||||
textTerminal.println(text + ":");
|
textTerminal.println(text + ":");
|
||||||
for (int option = 0; option < options.size(); option++) {
|
for(int option = 0; option < options.size(); option ++) {
|
||||||
textTerminal.println(" " + (option + 1) + ": " + options.get(option));
|
textTerminal.println(" " + (option + 1) + ": " + options.get(option));
|
||||||
}
|
}
|
||||||
return textIO.newIntInputReader().withMinVal(1).withMaxVal(options.size()).read("Enter your choice: ") - 1;
|
return textIO.newIntInputReader().withMinVal(1).withMaxVal(options.size()).read("Enter your choice: ") - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gives information which player is at turn and asks for the direction to accelerate or quit the game.
|
* gives information which player's turn it is and asks for the direction to accelerate
|
||||||
*
|
|
||||||
* @param playingCarIndex the index of the player
|
* @param playingCarIndex the index of the player
|
||||||
* @param playingCarID the ID of the player
|
* @param playingCarID the ID of the player
|
||||||
* @return the direction which is selected by the player. If null -> quit game
|
* @return the direction which is selected by the player. If null -> quit game
|
||||||
*/
|
*/
|
||||||
public PositionVector.Direction selectDirection(int playingCarIndex, char playingCarID) {
|
public PositionVector.Direction selectDirection(int playingCarIndex, char playingCarID) {
|
||||||
|
@ -79,8 +70,7 @@ public class UserInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method which returns the associated direction Object.
|
* returns the the associated direction Object
|
||||||
*
|
|
||||||
* @param number the number which was typed by the user
|
* @param number the number which was typed by the user
|
||||||
* @return the associated direction. If null -> unknown number
|
* @return the associated direction. If null -> unknown number
|
||||||
*/
|
*/
|
||||||
|
@ -100,21 +90,22 @@ public class UserInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to print the given Track in the terminal
|
* prints the given Track in the terminal
|
||||||
*
|
|
||||||
* @param track the track which should be printed
|
* @param track the track which should be printed
|
||||||
*/
|
*/
|
||||||
public void printTrack(Track track) {
|
public void printTrack(Track track) {
|
||||||
textTerminal.println(track.toString());
|
textTerminal.println(track.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to dispose of the Textterminal
|
* Method to dispose the Textterminal
|
||||||
*
|
* @param text OUtput Text
|
||||||
* @param text Output Text
|
|
||||||
*/
|
*/
|
||||||
public void quit(String text) {
|
public void quit(String text){
|
||||||
textIO.newStringInputReader().withMinLength(0).read(text);
|
textIO.newStringInputReader().withMinLength(0).read(text);
|
||||||
textTerminal.dispose();
|
textTerminal.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package ch.zhaw.pm2.racetrack.given;
|
package ch.zhaw.pm2.racetrack.given;
|
||||||
|
|
||||||
import ch.zhaw.pm2.racetrack.PositionVector;
|
import ch.zhaw.pm2.racetrack.PositionVector;
|
||||||
|
import ch.zhaw.pm2.racetrack.PositionVectorNotValid;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -18,11 +19,11 @@ public interface GameSpecification {
|
||||||
|
|
||||||
int getWinner();
|
int getWinner();
|
||||||
|
|
||||||
void doCarTurn(PositionVector.Direction acceleration);
|
void doCarTurn(PositionVector.Direction acceleration) throws PositionVectorNotValid;
|
||||||
|
|
||||||
void switchToNextActiveCar();
|
void switchToNextActiveCar();
|
||||||
|
|
||||||
List<PositionVector> calculatePath(PositionVector startPosition, PositionVector endPosition);
|
List<PositionVector> calculatePath(PositionVector startPosition, PositionVector endPosition);
|
||||||
|
|
||||||
boolean willCarCrash(int carIndex, PositionVector position);
|
boolean willCarCrash(int carIndex, PositionVector position) throws PositionVectorNotValid;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,15 +5,10 @@ import ch.zhaw.pm2.racetrack.PositionVector;
|
||||||
import static ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
import static ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This Class represents the DoNotMoveStrategy.
|
* Do not accelerate in any direction.
|
||||||
*/
|
*/
|
||||||
public class DoNotMoveStrategy implements MoveStrategy {
|
public class DoNotMoveStrategy implements MoveStrategy {
|
||||||
|
|
||||||
/**
|
|
||||||
* This method will be used to return the next Direction for the car.
|
|
||||||
*
|
|
||||||
* @return a NONE Direction
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Direction nextMove() {
|
public Direction nextMove() {
|
||||||
return PositionVector.Direction.NONE;
|
return PositionVector.Direction.NONE;
|
||||||
|
|
|
@ -1,62 +1,39 @@
|
||||||
package ch.zhaw.pm2.racetrack.strategy;
|
package ch.zhaw.pm2.racetrack.strategy;
|
||||||
|
|
||||||
import ch.zhaw.pm2.racetrack.InvalidFileFormatException;
|
|
||||||
import ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
import ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
/**
|
|
||||||
* This Class represent the MoveListStrategy. The Directions returned by the
|
|
||||||
* nextMove() are written down in a List.
|
|
||||||
*/
|
|
||||||
public class MoveListStrategy implements MoveStrategy {
|
public class MoveListStrategy implements MoveStrategy {
|
||||||
|
|
||||||
private final List<Direction> moveList;
|
private List<Direction> moveList;
|
||||||
private int pointer;
|
private int pointer;
|
||||||
|
|
||||||
public MoveListStrategy(File moveListFile) throws FileNotFoundException, InvalidFileFormatException {
|
public MoveListStrategy(String path) throws FileNotFoundException{
|
||||||
moveList = new ArrayList<>();
|
moveList = new ArrayList<>();
|
||||||
pointer = -1;
|
pointer = -1;
|
||||||
readFile(moveListFile);
|
readFile(new File(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void readFile(File trackFile) throws FileNotFoundException {
|
||||||
* This Method will read in a File and checks line by line if the file contains a valid direction.
|
Scanner scanner = new Scanner(new FileInputStream(trackFile), "UTF-8");
|
||||||
* If so the direction will be added to the moveList.
|
|
||||||
*
|
|
||||||
* @param trackFile the file to read in the directions
|
|
||||||
* @throws FileNotFoundException if the file does not exist.
|
|
||||||
*/
|
|
||||||
private void readFile(File trackFile) throws FileNotFoundException, InvalidFileFormatException {
|
|
||||||
Scanner scanner = new Scanner(new FileInputStream(trackFile), StandardCharsets.UTF_8);
|
|
||||||
Direction[] directions = Direction.values();
|
Direction[] directions = Direction.values();
|
||||||
while (scanner.hasNextLine()) {
|
while (scanner.hasNextLine()) {
|
||||||
boolean validLine = false;
|
|
||||||
String line = scanner.nextLine();
|
String line = scanner.nextLine();
|
||||||
for (Direction direction : directions) {
|
for (Direction direction : directions) {
|
||||||
if (direction.toString().equals(line)) {
|
if (direction.toString().equals(line)) {
|
||||||
moveList.add(direction);
|
moveList.add(direction);
|
||||||
validLine = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!(validLine || line.equals(""))) {
|
|
||||||
throw new InvalidFileFormatException("The File contains invalid data!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method will be used to return the next Direction for the car.
|
|
||||||
*
|
|
||||||
* @return the next direction from the list. Returns null if the list is empty.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Direction nextMove() {
|
public Direction nextMove() {
|
||||||
pointer += 1;
|
pointer += 1;
|
||||||
|
|
|
@ -1,223 +0,0 @@
|
||||||
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.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Strategy which calculates the path automatically
|
|
||||||
*/
|
|
||||||
public class PathFinderMoveStrategy implements MoveStrategy {
|
|
||||||
private final Track track;
|
|
||||||
private final int carIndex;
|
|
||||||
private List<PositionVector.Direction> moveList;
|
|
||||||
// the index of the next move in moveList
|
|
||||||
private int pointer;
|
|
||||||
// all Directions which can be used for acceleration
|
|
||||||
private final PositionVector.Direction[] allDirections;
|
|
||||||
// List of all States (combination of Position and Velocity) which are already reached with a calculated move.
|
|
||||||
private List<State> calculatedStates;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor which initialises the needed variables and creates the MoveList
|
|
||||||
*
|
|
||||||
* @param track track instance of the game
|
|
||||||
* @param carIndex index of the car which owns this moveStrategy
|
|
||||||
*/
|
|
||||||
public PathFinderMoveStrategy(Track track, int carIndex) {
|
|
||||||
this.track = track;
|
|
||||||
this.carIndex = carIndex;
|
|
||||||
allDirections = PositionVector.Direction.values();
|
|
||||||
createMoveList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to create a working moveList
|
|
||||||
*/
|
|
||||||
private void createMoveList() {
|
|
||||||
// if Movelist is recreated next move will be the first move in moveList
|
|
||||||
pointer = 0;
|
|
||||||
calculatedStates = new ArrayList<>();
|
|
||||||
PossibleMove finishedMove = null;
|
|
||||||
List<PossibleMove> possibleMoves = new ArrayList<>();
|
|
||||||
|
|
||||||
// create a PossibleMove object for each direction which doesn't end with a crash.
|
|
||||||
for (PositionVector.Direction direction : allDirections) {
|
|
||||||
PossibleMove newMove = new PossibleMove(null, direction);
|
|
||||||
if (!newMove.crashed()) {
|
|
||||||
possibleMoves.add(newMove);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// while no PossibleMove crosses the finish line
|
|
||||||
// every PossibleMove will be accelerated in each direction to find a Move which finishes.
|
|
||||||
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);
|
|
||||||
//only use the new created Possible Move if it doesn't crash, end State isn't in List of calculatedStates
|
|
||||||
// and if there is no move found yet which is finished.
|
|
||||||
if (!(newMove.crashed() || alreadyCalculated(newState) || finishedMove != null)) {
|
|
||||||
if (newMove.finished()) {
|
|
||||||
finishedMove = newMove;
|
|
||||||
} else {
|
|
||||||
calculatedStates.add(newState);
|
|
||||||
newMoves.add(newMove);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
possibleMoves = newMoves;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// if a finished Move is found save its directions as moveList
|
|
||||||
moveList = finishedMove.directions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to check if a State is already in List calculatedStates
|
|
||||||
*
|
|
||||||
* @param state the State which should be checked
|
|
||||||
* @return true if it is in List, false if it isn't in List
|
|
||||||
*/
|
|
||||||
private boolean alreadyCalculated(State state) {
|
|
||||||
for (State calculatedState : calculatedStates) {
|
|
||||||
if (state.equals(calculatedState)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Combination of position and velocity
|
|
||||||
*/
|
|
||||||
public static class State {
|
|
||||||
final PositionVector position;
|
|
||||||
final PositionVector velocity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor of State
|
|
||||||
*
|
|
||||||
* @param position the PositionVector object with coordinates of the Position
|
|
||||||
* @param velocity the PositionVector object with coordinates of the Velocity
|
|
||||||
*/
|
|
||||||
public State(PositionVector position, PositionVector velocity) {
|
|
||||||
this.position = position;
|
|
||||||
this.velocity = velocity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a state has the same Position and the same Velocity
|
|
||||||
*
|
|
||||||
* @param compareState the State object to compare
|
|
||||||
* @return true if it is equal, false if it is not equal
|
|
||||||
*/
|
|
||||||
public boolean equals(State compareState) {
|
|
||||||
return compareState.position.equals(position) && compareState.velocity.equals(velocity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PossibleMove represents a move which can be done by the player.
|
|
||||||
*/
|
|
||||||
public class PossibleMove {
|
|
||||||
// List of all directions used for the previous moves and the direction of the current move (the highest Index).
|
|
||||||
final List<PositionVector.Direction> directions;
|
|
||||||
// Position of the car bevor the move is executed
|
|
||||||
final PositionVector startPosition;
|
|
||||||
// Position of the car after the move is executed
|
|
||||||
final PositionVector endPosition;
|
|
||||||
// Velocity of the car after the move is executed
|
|
||||||
final PositionVector endVelocity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor of PossibleMove
|
|
||||||
*
|
|
||||||
* @param previousMove The move which must be executed bevor this move can be executed
|
|
||||||
* @param nextDirection The direction of the move
|
|
||||||
*/
|
|
||||||
public PossibleMove(PossibleMove previousMove, PositionVector.Direction nextDirection) {
|
|
||||||
// Velocity of the car bevor the move is executed
|
|
||||||
PositionVector startVelocity;
|
|
||||||
|
|
||||||
directions = new ArrayList<>();
|
|
||||||
// check if there was a previousMove.
|
|
||||||
if (previousMove != null) {
|
|
||||||
directions.addAll(previousMove.directions); //copy the LIst of Directions from the previousMove
|
|
||||||
startPosition = previousMove.endPosition; //use the endPosition from previousMove as startPosition
|
|
||||||
startVelocity = previousMove.endVelocity; //use the endVelocity from previousMove as startVelocity
|
|
||||||
} else { //if there was no previousMove
|
|
||||||
startPosition = track.getCarPos(carIndex); //use the current Position of the car from track as startPosition
|
|
||||||
startVelocity = track.getCar(carIndex).getVelocity(); //use the current Velocity of the car from track as startVelocity
|
|
||||||
}
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* check if the finish line is crossed (in correct direction) if this move is executed
|
|
||||||
*
|
|
||||||
* @return true if finish line will be crossed
|
|
||||||
*/
|
|
||||||
public boolean finished() {
|
|
||||||
return track.calculateNewWinPoints(startPosition, endPosition) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* checks if the car will crash or finishline will be crossed in wrong direction if this move is executed
|
|
||||||
*
|
|
||||||
* @return true if car will crash
|
|
||||||
*/
|
|
||||||
public boolean crashed() {
|
|
||||||
List<PositionVector> points = track.calculatePointsOnPath(startPosition, endPosition);
|
|
||||||
for (PositionVector point : points) {
|
|
||||||
if (track.willCrashAtPosition(carIndex, point)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return track.calculateNewWinPoints(startPosition, endPosition) == -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the next Move in moveList will crash. If no crash next move in moveList will be executed.
|
|
||||||
* If crash the moveList will be recreated.
|
|
||||||
*
|
|
||||||
* @return the direction of acceleration which should be executed.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public PositionVector.Direction nextMove() {
|
|
||||||
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());
|
|
||||||
for (PositionVector point : track.calculatePointsOnPath(currentPosition, newPosition)) {
|
|
||||||
if (track.willCrashAtPosition(carIndex, point)) {
|
|
||||||
createMoveList();
|
|
||||||
pointer = 0;
|
|
||||||
direction = moveList.get(pointer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pointer += 1;
|
|
||||||
return direction;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,13 +1,11 @@
|
||||||
package ch.zhaw.pm2.racetrack.strategy;
|
package ch.zhaw.pm2.racetrack.strategy;
|
||||||
|
|
||||||
import ch.zhaw.pm2.racetrack.InvalidFileFormatException;
|
|
||||||
import ch.zhaw.pm2.racetrack.PositionVector;
|
import ch.zhaw.pm2.racetrack.PositionVector;
|
||||||
import ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
import ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
@ -27,7 +25,7 @@ public class PathFollowerMoveStrategy implements MoveStrategy {
|
||||||
/**
|
/**
|
||||||
* List of all points on the path.
|
* List of all points on the path.
|
||||||
*/
|
*/
|
||||||
private final ArrayList<PositionVector> pointList;
|
private ArrayList<PositionVector> pointList;
|
||||||
/**
|
/**
|
||||||
* The index of the next point on the path.
|
* The index of the next point on the path.
|
||||||
*/
|
*/
|
||||||
|
@ -35,41 +33,34 @@ public class PathFollowerMoveStrategy implements MoveStrategy {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor to create a new PathFollowerMoveStrategy for a car.
|
* Constructor to create a new PathFollowerMoveStrategy for a car.
|
||||||
*
|
* @param path The location where the file is saved
|
||||||
* @param trackFile The location where the file is saved
|
|
||||||
* @param startPosition The start position of the car
|
* @param startPosition The start position of the car
|
||||||
* @throws FileNotFoundException If the file with the given path does not exist.
|
* @throws FileNotFoundException If the file with the given path does not exist.
|
||||||
*/
|
*/
|
||||||
public PathFollowerMoveStrategy(File trackFile, PositionVector startPosition) throws FileNotFoundException, InvalidFileFormatException {
|
public PathFollowerMoveStrategy(String path, PositionVector startPosition) throws FileNotFoundException {
|
||||||
pointList = new ArrayList<>();
|
pointList = new ArrayList<>();
|
||||||
pointer = 0;
|
pointer = 0;
|
||||||
readFile(trackFile);
|
readFile(new File(path));
|
||||||
currentPosition = startPosition;
|
currentPosition = startPosition;
|
||||||
currentVelocity = new PositionVector(0, 0);
|
currentVelocity = new PositionVector(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to read the given File and add the points to the pointList
|
* Method to read the given File and add the points to the pointList
|
||||||
*
|
|
||||||
* @param trackFile the File Object which should be read
|
* @param trackFile the File Object which should be read
|
||||||
* @throws FileNotFoundException If the file with the given path does not exist.
|
* @throws FileNotFoundException If the file with the given path does not exist.
|
||||||
*/
|
*/
|
||||||
public void readFile(File trackFile) throws FileNotFoundException, InvalidFileFormatException {
|
public void readFile(File trackFile) throws FileNotFoundException {
|
||||||
Scanner scanner = new Scanner(new FileInputStream(trackFile), StandardCharsets.UTF_8);
|
Scanner scanner = new Scanner(new FileInputStream(trackFile), "UTF-8");
|
||||||
while (scanner.hasNextLine()) {
|
while (scanner.hasNextLine()) {
|
||||||
String line = scanner.nextLine();
|
String line = scanner.nextLine();
|
||||||
String[] coordinates = line.split("(\\(X:|, Y:|\\))");
|
String[] coordinates = line.split("(\\(X:|, Y:|\\))");
|
||||||
try {
|
pointList.add(new PositionVector(Integer.parseInt(coordinates[1]), Integer.parseInt(coordinates[2])));
|
||||||
pointList.add(new PositionVector(Integer.parseInt(coordinates[1]), Integer.parseInt(coordinates[2])));
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
throw new InvalidFileFormatException("Invalid File Format");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to select the direction for the next move.
|
* Method to select the direction for the next move.
|
||||||
*
|
|
||||||
* @return The direction for the next move. null if there are no points left in the list.
|
* @return The direction for the next move. null if there are no points left in the list.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@ -81,7 +72,7 @@ public class PathFollowerMoveStrategy implements MoveStrategy {
|
||||||
|
|
||||||
// increase pointer variable if the next point is reached.
|
// increase pointer variable if the next point is reached.
|
||||||
if (pointList.get(pointer).equals(currentPosition)) {
|
if (pointList.get(pointer).equals(currentPosition)) {
|
||||||
pointer++;
|
pointer ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate Vector from current Position to next Point
|
// calculate Vector from current Position to next Point
|
||||||
|
@ -89,29 +80,31 @@ public class PathFollowerMoveStrategy implements MoveStrategy {
|
||||||
|
|
||||||
// select acceleration for X
|
// select acceleration for X
|
||||||
int accelerationX;
|
int accelerationX;
|
||||||
if ((movementVector.getX() == 0 && currentVelocity.getX() > 0) || //reduce velocity to 0 if the destination coordinate is reached
|
if((movementVector.getX() == 0 && currentVelocity.getX() > 0) || //reduce velocity to 0 if the destination coordinate is reached
|
||||||
(movementVector.getX() > 0 && movementVector.getX() / 2.0 <= currentVelocity.getX()) || //increase velocity
|
(movementVector.getX() > 0 && movementVector.getX()/2.0 <= currentVelocity.getX()) || //increase velocity
|
||||||
(movementVector.getX() < 0 && movementVector.getX() / 2.0 < currentVelocity.getX())) { //reduce velocity
|
(movementVector.getX() < 0 && movementVector.getX()/2.0 < currentVelocity.getX())){ //reduce velocity
|
||||||
accelerationX = -1;
|
accelerationX = -1;
|
||||||
} else if ((movementVector.getX() == 0 && currentVelocity.getX() < 0) || //reduce velocity to 0 if the destination coordinate is reached
|
} else if((movementVector.getX() == 0 && currentVelocity.getX() < 0) || //reduce velocity to 0 if the destination coordinate is reached
|
||||||
(movementVector.getX() > 0 && movementVector.getX() / 2.0 > currentVelocity.getX()) || //increase velocity
|
(movementVector.getX() > 0 && movementVector.getX()/2.0 > currentVelocity.getX()) || //increase velocity
|
||||||
(movementVector.getX() < 0 && movementVector.getX() / 2.0 >= currentVelocity.getX())) { //reduce velocity
|
(movementVector.getX() < 0 && movementVector.getX()/2.0 >= currentVelocity.getX())) { //reduce velocity
|
||||||
accelerationX = 1;
|
accelerationX = 1;
|
||||||
} else { //no acceleration
|
}
|
||||||
|
else { //no acceleration
|
||||||
accelerationX = 0;
|
accelerationX = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// select acceleration for Y
|
// select acceleration for Y
|
||||||
int accelerationY;
|
int accelerationY;
|
||||||
if ((movementVector.getY() == 0 && currentVelocity.getY() > 0) || //reduce velocity to 0 if the destination coordinate is reached
|
if((movementVector.getY() == 0 && currentVelocity.getY() > 0) || //reduce velocity to 0 if the destination coordinate is reached
|
||||||
(movementVector.getY() > 0 && movementVector.getY() / 2.0 <= currentVelocity.getY()) || //increase velocity
|
(movementVector.getY() > 0 && movementVector.getY()/2.0 <= currentVelocity.getY()) || //increase velocity
|
||||||
(movementVector.getY() < 0 && movementVector.getY() / 2.0 < currentVelocity.getY())) { //reduce velocity
|
(movementVector.getY() < 0 && movementVector.getY()/2.0 < currentVelocity.getY())){ //reduce velocity
|
||||||
accelerationY = -1;
|
accelerationY = -1;
|
||||||
} else if ((movementVector.getY() == 0 && currentVelocity.getY() < 0) || //reduce velocity to 0 if the destination coordinate is reached
|
} else if((movementVector.getY() == 0 && currentVelocity.getY() < 0) || //reduce velocity to 0 if the destination coordinate is reached
|
||||||
(movementVector.getY() > 0 && movementVector.getY() / 2.0 > currentVelocity.getY()) || //increase velocity
|
(movementVector.getY() > 0 && movementVector.getY()/2.0 > currentVelocity.getY()) || //increase velocity
|
||||||
(movementVector.getY() < 0 && movementVector.getY() / 2.0 >= currentVelocity.getY())) { //reduce velocity
|
(movementVector.getY() < 0 && movementVector.getY()/2.0 >= currentVelocity.getY())) { //reduce velocity
|
||||||
accelerationY = 1;
|
accelerationY = 1;
|
||||||
} else { //no acceleration
|
}
|
||||||
|
else { //no acceleration
|
||||||
accelerationY = 0;
|
accelerationY = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +120,7 @@ public class PathFollowerMoveStrategy implements MoveStrategy {
|
||||||
return direction;
|
return direction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,11 @@ import ch.zhaw.pm2.racetrack.UserInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Let the user decide the next move.
|
* Let the user decide the next move.
|
||||||
* Therefore, it uses the UserInterface class to ask for a direction.
|
|
||||||
*/
|
*/
|
||||||
public class UserMoveStrategy implements MoveStrategy {
|
public class UserMoveStrategy implements MoveStrategy {
|
||||||
private final UserInterface userInterface;
|
private UserInterface userInterface;
|
||||||
private final int carIndex;
|
private int carIndex;
|
||||||
private final char carID;
|
private char carID;
|
||||||
|
|
||||||
public UserMoveStrategy(UserInterface userInterface, int carIndex, char carID) {
|
public UserMoveStrategy(UserInterface userInterface, int carIndex, char carID) {
|
||||||
this.userInterface = userInterface;
|
this.userInterface = userInterface;
|
||||||
|
@ -18,11 +17,6 @@ public class UserMoveStrategy implements MoveStrategy {
|
||||||
this.carID = carID;
|
this.carID = carID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Uses the interface to determine which move the user takes.
|
|
||||||
*
|
|
||||||
* @return the next taken move as Direction
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Direction nextMove() {
|
public Direction nextMove() {
|
||||||
return userInterface.selectDirection(carIndex, carID);
|
return userInterface.selectDirection(carIndex, carID);
|
||||||
|
|
|
@ -1,233 +0,0 @@
|
||||||
|
|
||||||
package ch.zhaw.pm2.racetrack;
|
|
||||||
|
|
||||||
import ch.zhaw.pm2.racetrack.strategy.*;
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class that contains all test for the Class Car
|
|
||||||
*
|
|
||||||
* @author Roman Schenk
|
|
||||||
*/
|
|
||||||
class CarTest {
|
|
||||||
|
|
||||||
Car car;
|
|
||||||
|
|
||||||
// Default coordinates for tests
|
|
||||||
final int DEFAULT_X = 10;
|
|
||||||
final int DEFAULT_Y = 10;
|
|
||||||
final char DEFAULT_ID = 'f';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new Car Object and set Position to a defined Default Position
|
|
||||||
*/
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() {
|
|
||||||
car = new Car(DEFAULT_ID, new PositionVector(DEFAULT_X, DEFAULT_Y));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the method getID returns the correct value
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void getID() {
|
|
||||||
assertEquals(DEFAULT_ID, car.getID());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to check nextPosition with coordinates as int
|
|
||||||
*
|
|
||||||
* @param x the expected value for x coordinate
|
|
||||||
* @param y the expected value for y coordinate
|
|
||||||
*/
|
|
||||||
void checkNextPosition(int x, int y) {
|
|
||||||
assertEquals(new PositionVector(x, y), car.nextPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the position of the car can be set and saved correctly with valid positions.
|
|
||||||
* Checks if an exception is thrown and position kept unchanged if invalid coordinates are entered.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void setPosition() {
|
|
||||||
checkNextPosition(DEFAULT_X, DEFAULT_Y);
|
|
||||||
|
|
||||||
// List of valid Positions
|
|
||||||
List<PositionVector> validPositions = new ArrayList<>();
|
|
||||||
validPositions.add(new PositionVector(20, 20));
|
|
||||||
validPositions.add(new PositionVector(0, 0));
|
|
||||||
validPositions.add(new PositionVector(20, 0));
|
|
||||||
validPositions.add(new PositionVector(0, 20));
|
|
||||||
|
|
||||||
for (PositionVector positionVector : validPositions) {
|
|
||||||
car.setPosition(positionVector);
|
|
||||||
assertEquals(positionVector, car.nextPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
// List of invalid positions.
|
|
||||||
List<PositionVector> invalidPositions = new ArrayList<>();
|
|
||||||
invalidPositions.add(new PositionVector(0, -20));
|
|
||||||
invalidPositions.add(new PositionVector(-20, 0));
|
|
||||||
invalidPositions.add(new PositionVector(-20, -20));
|
|
||||||
|
|
||||||
for (PositionVector positionVector : invalidPositions) {
|
|
||||||
boolean exception = false;
|
|
||||||
setUp();
|
|
||||||
try {
|
|
||||||
car.setPosition(positionVector);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
exception = true;
|
|
||||||
}
|
|
||||||
assertTrue(exception);
|
|
||||||
|
|
||||||
// position should keep unchanged
|
|
||||||
checkNextPosition(DEFAULT_X, DEFAULT_Y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkVelocity(int x, int y) {
|
|
||||||
assertEquals(new PositionVector(x, y), car.getVelocity());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the methods accelerate, move and getVelocity are working correctly with acceleration in all directions.
|
|
||||||
* Checks also if velocity is calculated correctly if method accelerate is called a second time.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void movement() {
|
|
||||||
// add all possible directions in a List
|
|
||||||
PositionVector.Direction[] directions = PositionVector.Direction.values();
|
|
||||||
|
|
||||||
//position shouldn't be changed because velocity should be 0.
|
|
||||||
car.move();
|
|
||||||
checkNextPosition(DEFAULT_X, DEFAULT_Y);
|
|
||||||
|
|
||||||
|
|
||||||
for (PositionVector.Direction direction1 : directions) {
|
|
||||||
for (PositionVector.Direction direction2 : directions) {
|
|
||||||
|
|
||||||
//create a new instance of Car with default coordinates and velocity 0.
|
|
||||||
setUp();
|
|
||||||
|
|
||||||
//variables to save the actual expected result of method nextPosition
|
|
||||||
int expectedNextPosX = DEFAULT_X;
|
|
||||||
int expectedNextPosY = DEFAULT_Y;
|
|
||||||
|
|
||||||
//variables to save the actual expected result of method getVelocity
|
|
||||||
int expectedVelocityX = 0;
|
|
||||||
int expectedVelocityY = 0;
|
|
||||||
|
|
||||||
car.accelerate(direction1);
|
|
||||||
expectedVelocityX += direction1.vector.getX();
|
|
||||||
expectedVelocityY += direction1.vector.getY();
|
|
||||||
expectedNextPosX += direction1.vector.getX();
|
|
||||||
expectedNextPosY += direction1.vector.getY();
|
|
||||||
checkVelocity(expectedVelocityX, expectedVelocityY);
|
|
||||||
checkNextPosition(expectedNextPosX, expectedNextPosY);
|
|
||||||
|
|
||||||
car.move();
|
|
||||||
expectedNextPosX += direction1.vector.getX();
|
|
||||||
expectedNextPosY += direction1.vector.getY();
|
|
||||||
checkVelocity(expectedVelocityX, expectedVelocityY);
|
|
||||||
checkNextPosition(expectedNextPosX, expectedNextPosY);
|
|
||||||
|
|
||||||
|
|
||||||
car.accelerate(direction2);
|
|
||||||
expectedVelocityX += direction2.vector.getX();
|
|
||||||
expectedVelocityY += direction2.vector.getY();
|
|
||||||
expectedNextPosX += direction2.vector.getX();
|
|
||||||
expectedNextPosY += direction2.vector.getY();
|
|
||||||
checkVelocity(expectedVelocityX, expectedVelocityY);
|
|
||||||
checkNextPosition(expectedNextPosX, expectedNextPosY);
|
|
||||||
|
|
||||||
car.move();
|
|
||||||
checkVelocity(expectedVelocityX, expectedVelocityY);
|
|
||||||
expectedNextPosX += (direction1.vector.getX() + direction2.vector.getX());
|
|
||||||
expectedNextPosY += (direction1.vector.getY() + direction2.vector.getY());
|
|
||||||
checkNextPosition(expectedNextPosX, expectedNextPosY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for methods crash and isCrashed.
|
|
||||||
* Checks if state crashed is set and returned correctly.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void crash() {
|
|
||||||
assertFalse(car.isCrashed());
|
|
||||||
car.crash();
|
|
||||||
assertTrue(car.isCrashed());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for methods setMoveStrategy.
|
|
||||||
* Checks if the MoveStrategy Object is saved and returned correctly with all Types of MoveStrategy.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void MoveStrategy() {
|
|
||||||
MoveStrategy moveStrategy;
|
|
||||||
|
|
||||||
moveStrategy = new DoNotMoveStrategy();
|
|
||||||
car.setMoveStrategy(moveStrategy);
|
|
||||||
assertEquals(moveStrategy, car.getMoveStrategy());
|
|
||||||
|
|
||||||
try {
|
|
||||||
moveStrategy = new MoveListStrategy(new File(".\\moves\\challenge-car-a.txt"));
|
|
||||||
} catch (FileNotFoundException | InvalidFileFormatException e) {
|
|
||||||
Assertions.fail();
|
|
||||||
}
|
|
||||||
car.setMoveStrategy(moveStrategy);
|
|
||||||
assertEquals(moveStrategy, car.getMoveStrategy());
|
|
||||||
|
|
||||||
try {
|
|
||||||
moveStrategy = new PathFollowerMoveStrategy(new File(".\\follower\\challenge_points.txt"), new PositionVector(0, 0));
|
|
||||||
} catch (FileNotFoundException | InvalidFileFormatException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
car.setMoveStrategy(moveStrategy);
|
|
||||||
assertEquals(moveStrategy, car.getMoveStrategy());
|
|
||||||
|
|
||||||
moveStrategy = new UserMoveStrategy(new UserInterface("Hello"), 0, 'a');
|
|
||||||
car.setMoveStrategy(moveStrategy);
|
|
||||||
assertEquals(moveStrategy, car.getMoveStrategy());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if getWinPoints returns the correct value.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void getWinPoints() {
|
|
||||||
assertEquals(0, car.getWinPoints());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if winpoints increase functions properly.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void increaseWinPoints() {
|
|
||||||
car.increaseWinPoints();
|
|
||||||
assertEquals(1, car.getWinPoints());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if the deductions of winpoints functions properly.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void deductWinPoints() {
|
|
||||||
car.deductWinPoints();
|
|
||||||
assertEquals(-1, car.getWinPoints());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -4,314 +4,101 @@ import ch.zhaw.pm2.racetrack.strategy.UserMoveStrategy;
|
||||||
import org.junit.jupiter.api.*;
|
import org.junit.jupiter.api.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.util.List;
|
|
||||||
import static ch.zhaw.pm2.racetrack.Game.NO_WINNER;
|
import static ch.zhaw.pm2.racetrack.Game.NO_WINNER;
|
||||||
import static ch.zhaw.pm2.racetrack.PositionVector.Direction.*;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for Class Game. The Class is split up in nested classes.
|
|
||||||
*
|
|
||||||
* @author Andrin Fassbind
|
|
||||||
*/
|
|
||||||
class GameTest {
|
class GameTest {
|
||||||
private UserInterface userInterface;
|
private UserInterface userInterface;
|
||||||
private Game game;
|
private Game game;
|
||||||
private Track track;
|
private Track track;
|
||||||
|
|
||||||
private final String TRACK_FILE_PATH = ".\\tracks\\challenge.txt";
|
|
||||||
private final int CAR_INDEX_ONE = 0;
|
|
||||||
private final int CAR_INDEX_TWO = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This nested Class tests if the game gets initiated correctly.
|
|
||||||
*/
|
|
||||||
@Nested
|
@Nested
|
||||||
@DisplayName("Test correct Setup")
|
@DisplayName("Test correct Setup")
|
||||||
class Setup {
|
class Setup {
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up getting the Config, Game and Userinterface for the following tests.
|
|
||||||
*/
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setup() {
|
void setup() {
|
||||||
userInterface = new UserInterface("Test");
|
userInterface = new UserInterface("Test");
|
||||||
Config config = new Config();
|
game = new Game(userInterface);
|
||||||
game = new Game(userInterface, config);
|
track = game.selectTrack(new File(".\\tracks\\challenge.txt"));
|
||||||
try {
|
game.selectMoveStrategy(track.getCar(0),new UserMoveStrategy(new UserInterface("Testing"),0, track.getCarId(0)));
|
||||||
track = game.selectTrack(new File(TRACK_FILE_PATH));
|
game.selectMoveStrategy(track.getCar(1),new UserMoveStrategy(new UserInterface("Testing"),1, track.getCarId(1)));
|
||||||
} catch (InvalidTrackFormatException | FileNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
Assertions.fail();
|
|
||||||
}
|
|
||||||
game.selectMoveStrategy(track.getCar(CAR_INDEX_ONE), new UserMoveStrategy(new UserInterface("Testing"), CAR_INDEX_ONE, track.getCarId(CAR_INDEX_ONE)));
|
|
||||||
game.selectMoveStrategy(track.getCar(CAR_INDEX_TWO), new UserMoveStrategy(new UserInterface("Testing"), CAR_INDEX_TWO, track.getCarId(CAR_INDEX_TWO)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if car index is correct
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
void getCurrentCarIndex() {
|
void getCurrentCarIndex() {
|
||||||
Assertions.assertEquals(CAR_INDEX_ONE, game.getCurrentCarIndex());
|
Assertions.assertEquals(0,game.getCurrentCarIndex());
|
||||||
game.switchToNextActiveCar();
|
game.switchToNextActiveCar();
|
||||||
Assertions.assertEquals(CAR_INDEX_TWO, game.getCurrentCarIndex());
|
Assertions.assertEquals(1,game.getCurrentCarIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if CarId matches char given in track file
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
void getCarId() {
|
void getCarId() {
|
||||||
Assertions.assertEquals('a', game.getCarId(0));
|
Assertions.assertEquals('a',game.getCarId(0));
|
||||||
Assertions.assertEquals('b', game.getCarId(1));
|
Assertions.assertEquals('b',game.getCarId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks initial car position
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
void getCarPosition() {
|
void getCarPosition() {
|
||||||
Assertions.assertEquals(new PositionVector(24, 22), game.getCarPosition(0));
|
Assertions.assertEquals(new PositionVector(24,22),game.getCarPosition(0));
|
||||||
Assertions.assertEquals(new PositionVector(24, 24), game.getCarPosition(1));
|
Assertions.assertEquals(new PositionVector(24,24),game.getCarPosition(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if initial car velocity is 0,0
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
void getCarVelocity() {
|
void getCarVelocity() {
|
||||||
Assertions.assertEquals(new PositionVector(0, 0), game.getCarVelocity(0));
|
Assertions.assertEquals(new PositionVector(0,0),game.getCarVelocity(0));
|
||||||
Assertions.assertEquals(new PositionVector(0, 0), game.getCarVelocity(1));
|
Assertions.assertEquals(new PositionVector(0,0),game.getCarVelocity(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks initial winner
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
void getWinner() {
|
void getWinner() {
|
||||||
Assertions.assertEquals(NO_WINNER, game.getWinner());
|
Assertions.assertEquals(NO_WINNER,game.getWinner());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks correct initial state
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
void onlyOneCarLeft() {
|
void onlyOneCarLeft() {
|
||||||
Assertions.assertFalse(game.onlyOneCarLeft());
|
Assertions.assertFalse(game.onlyOneCarLeft());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if cars are able to move
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
void carsMoving() {
|
void carsMoving() {
|
||||||
Assertions.assertTrue(game.carsMoving());
|
Assertions.assertTrue(game.carsMoving());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This nested Class makes basic manipulation after Game init.
|
|
||||||
*/
|
|
||||||
@Nested
|
@Nested
|
||||||
@DisplayName("Basic manipulation")
|
@DisplayName("Basic manipulation")
|
||||||
class Manipulation {
|
class manipulation {
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setup() {
|
void setup() {
|
||||||
userInterface = new UserInterface("Test");
|
userInterface = new UserInterface("Test");
|
||||||
Config config = new Config();
|
game = new Game(userInterface);
|
||||||
game = new Game(userInterface, config);
|
track = game.selectTrack(new File(".\\tracks\\challenge.txt"));
|
||||||
try {
|
game.selectMoveStrategy(track.getCar(0),new UserMoveStrategy(new UserInterface("Testing"),0, track.getCarId(0)));
|
||||||
track = game.selectTrack(new File(TRACK_FILE_PATH));
|
game.selectMoveStrategy(track.getCar(1),new UserMoveStrategy(new UserInterface("Testing"),1, track.getCarId(1)));
|
||||||
} catch (InvalidTrackFormatException | FileNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
Assertions.fail();
|
|
||||||
}
|
|
||||||
game.selectMoveStrategy(track.getCar(CAR_INDEX_ONE), new UserMoveStrategy(new UserInterface("Testing"), CAR_INDEX_ONE, track.getCarId(CAR_INDEX_ONE)));
|
|
||||||
game.selectMoveStrategy(track.getCar(CAR_INDEX_TWO), new UserMoveStrategy(new UserInterface("Testing"), CAR_INDEX_TWO, track.getCarId(CAR_INDEX_TWO)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if car does change velocity specified by direction input
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
void carTurnCorrect() {
|
void carTurnCorrect() {
|
||||||
game.doCarTurn(RIGHT);
|
try {
|
||||||
Assertions.assertEquals(new PositionVector(1, 0), game.getCarVelocity(0));
|
game.doCarTurn(PositionVector.Direction.RIGHT);
|
||||||
|
Assertions.assertEquals(new PositionVector(1,0),game.getCarVelocity(0));
|
||||||
|
} catch (PositionVectorNotValid positionVectorNotValid) {
|
||||||
|
positionVectorNotValid.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if car crash is set if a car crashes.
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
void carCrash() {
|
void carCrash() {
|
||||||
game.doCarTurn(PositionVector.Direction.UP);
|
|
||||||
Assertions.assertTrue(game.onlyOneCarLeft());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This nested Class tests a play trough and implements a userInterface which pretends to be a real player.
|
|
||||||
* At the end of every Test the user interface stays open for 10 more sec to visualize the game.
|
|
||||||
*/
|
|
||||||
@Nested
|
|
||||||
@DisplayName("Playtrough")
|
|
||||||
class Play {
|
|
||||||
private Game game;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method will start a game instance on the challenge track. Car a uses MoveListStrategy. Car b uses DoNotMoveStrategy
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void winner() {
|
|
||||||
game = new Game(new Interface("Test",new Integer[]{0,2,0},new PositionVector.Direction[]{RIGHT,
|
|
||||||
RIGHT,
|
|
||||||
RIGHT,
|
|
||||||
NONE,
|
|
||||||
NONE,
|
|
||||||
NONE,
|
|
||||||
NONE,
|
|
||||||
UP,
|
|
||||||
LEFT,
|
|
||||||
LEFT,
|
|
||||||
LEFT,
|
|
||||||
LEFT,
|
|
||||||
UP_LEFT,
|
|
||||||
NONE,
|
|
||||||
RIGHT,
|
|
||||||
RIGHT,
|
|
||||||
RIGHT,
|
|
||||||
NONE,
|
|
||||||
LEFT,
|
|
||||||
DOWN_LEFT,
|
|
||||||
DOWN_LEFT,
|
|
||||||
LEFT,
|
|
||||||
LEFT,
|
|
||||||
NONE,
|
|
||||||
RIGHT,
|
|
||||||
NONE,
|
|
||||||
DOWN,
|
|
||||||
DOWN,
|
|
||||||
RIGHT,
|
|
||||||
NONE,
|
|
||||||
RIGHT,
|
|
||||||
DOWN,
|
|
||||||
NONE,
|
|
||||||
UP_RIGHT,
|
|
||||||
RIGHT,
|
|
||||||
UP_RIGHT,
|
|
||||||
UP_RIGHT,
|
|
||||||
RIGHT,
|
|
||||||
RIGHT}), new Config());
|
|
||||||
game.initPhase();
|
|
||||||
Assertions.assertEquals("a",game.gamePhase());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Will start a game instance where car a does crash.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void crashA() {
|
|
||||||
game = new Game(new Interface("Test",new Integer[]{0,1,0},new PositionVector.Direction[]{UP}), new Config());
|
|
||||||
game.initPhase();
|
|
||||||
Assertions.assertEquals("b",game.gamePhase());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks that a car cant win before finishing a complete round around the track.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void passFinishLineInWrongDirection() {
|
|
||||||
game = new Game(new Interface("Test",new Integer[]{1,0,1},new PositionVector.Direction[]{LEFT,NONE,NONE,RIGHT,RIGHT}), new Config());
|
|
||||||
game.initPhase();
|
|
||||||
Assertions.assertEquals("a",game.gamePhase());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does wait 10 seconds before closing the textio.
|
|
||||||
*/
|
|
||||||
@AfterEach
|
|
||||||
void cleanUp() {
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(10000);
|
game.doCarTurn(PositionVector.Direction.UP);
|
||||||
} catch (InterruptedException e) {
|
Assertions.assertTrue(game.onlyOneCarLeft());
|
||||||
e.printStackTrace();
|
} catch (PositionVectorNotValid positionVectorNotValid) {
|
||||||
|
positionVectorNotValid.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This Class is used to communicate with the UserInterface. It overrides crucial methods and returns an instruction based on the instructions' data field.
|
|
||||||
* To implement the right instructions the user has to be aware of the game sequence.
|
|
||||||
*/
|
|
||||||
private class Interface extends UserInterface {
|
|
||||||
|
|
||||||
private final PositionVector.Direction[] directions;
|
|
||||||
private final Integer[] instructions;
|
|
||||||
private int pointerDir,pointerInstruction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor to create a new Interface Object
|
|
||||||
* @param welcometext The first Text which will be printed in the UserInterface Window
|
|
||||||
* @param instructions list of instructions to simulate userinput
|
|
||||||
* @param directions list of Directions to simulate userinput
|
|
||||||
*/
|
|
||||||
public Interface(String welcometext, Integer[] instructions, PositionVector.Direction[] directions) {
|
|
||||||
super(welcometext);
|
|
||||||
pointerDir = -1;
|
|
||||||
pointerInstruction = -1;
|
|
||||||
this.instructions = instructions;
|
|
||||||
this.directions = directions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overwriting Method for testing without userinteraction
|
|
||||||
* @param text Text which is printed before the options are printed. Example: "Select Track file:"
|
|
||||||
* @param options List with the options which can be selected.
|
|
||||||
* @return the selected Option
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int selectOption(String text, List<String> options) {
|
|
||||||
pointerInstruction++;
|
|
||||||
return instructions[pointerInstruction];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overwriting Method for testing without userinteraction
|
|
||||||
* @param text The Text which should be printed.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void printInformation(String text) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overwriting Method for testing without userinteraction
|
|
||||||
* @param text Output Text
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void quit(String text) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overwriting Method for testing without userinteraction
|
|
||||||
* @param playingCarIndex the index of the player
|
|
||||||
* @param playingCarID the ID of the player
|
|
||||||
* @return the direction to accelerate
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public PositionVector.Direction selectDirection(int playingCarIndex, char playingCarID) {
|
|
||||||
pointerDir += 1;
|
|
||||||
if(pointerDir < directions.length) {
|
|
||||||
return directions[pointerDir];
|
|
||||||
}
|
|
||||||
return NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,38 +4,26 @@ import ch.zhaw.pm2.racetrack.strategy.MoveListStrategy;
|
||||||
import ch.zhaw.pm2.racetrack.strategy.MoveStrategy;
|
import ch.zhaw.pm2.racetrack.strategy.MoveStrategy;
|
||||||
import org.junit.jupiter.api.*;
|
import org.junit.jupiter.api.*;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
|
||||||
/**
|
public class MoveStrategyTest {
|
||||||
* This Class tests the MoveStrategy.
|
|
||||||
*
|
|
||||||
* @author Andrin Fassbind
|
|
||||||
*/
|
|
||||||
public class MoveListStrategyTest {
|
|
||||||
|
|
||||||
private MoveStrategy moveList;
|
private MoveStrategy moveList;
|
||||||
|
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@DisplayName("MoveListStrategy")
|
@DisplayName("MoveListStrategy")
|
||||||
class MoveList {
|
class MoveList {
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new MoveListStrategy
|
|
||||||
*/
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setup() {
|
void setup() {
|
||||||
try {
|
try {
|
||||||
moveList = new MoveListStrategy(new File(".\\moves\\challenge-car-a.txt"));
|
moveList = new MoveListStrategy(".\\moves\\challenge-car-a.txt");
|
||||||
}catch (FileNotFoundException | InvalidFileFormatException e) {
|
}catch (FileNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the directions are returned correct by method nextMove
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
void checkMove() {
|
void checkMove() {
|
||||||
Assertions.assertEquals(PositionVector.Direction.RIGHT,moveList.nextMove());
|
Assertions.assertEquals(PositionVector.Direction.RIGHT,moveList.nextMove());
|
|
@ -2,50 +2,37 @@ package ch.zhaw.pm2.racetrack;
|
||||||
|
|
||||||
import ch.zhaw.pm2.racetrack.given.ConfigSpecification;
|
import ch.zhaw.pm2.racetrack.given.ConfigSpecification;
|
||||||
import org.junit.jupiter.api.*;
|
import org.junit.jupiter.api.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
|
||||||
* This Class tests the track
|
|
||||||
*
|
|
||||||
* @author Andrin Fassbind
|
|
||||||
*/
|
|
||||||
public class TrackTest {
|
public class TrackTest {
|
||||||
Track trackObj;
|
Track trackObj;
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@DisplayName("Positive Test Cases")
|
@DisplayName("Positiv Test Cases")
|
||||||
class positiveClass {
|
class positivClass {
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up the Test cases by loading the file and setting a new track.
|
|
||||||
*/
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setup() {
|
void setup() {
|
||||||
File file = new File(".\\tracks\\challenge.txt");
|
File file = new File(".\\tracks\\challenge.txt");
|
||||||
try {
|
try {
|
||||||
trackObj = new Track(file);
|
trackObj = new Track(file);
|
||||||
} catch (FileNotFoundException | InvalidTrackFormatException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
Assertions.fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
} catch (Exception | PositionVectorNotValid e) {
|
||||||
|
System.err.println("Error in Test compareTrack" + e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if correct amount of cars has been instantiated
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Create correct amount of Car instance")
|
@DisplayName("Create correct amount of Car instance")
|
||||||
void checkCars() {
|
void checkCars() {
|
||||||
Assertions.assertEquals(2, trackObj.getCarCount());
|
Assertions.assertEquals(2, trackObj.getCarCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if car id matches track file symbol
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Create Car instance with correct Symbols / Id")
|
@DisplayName("Create Car instance with correct Symbols / Id")
|
||||||
void checkCarId() {
|
void checkCarId() {
|
||||||
|
@ -53,18 +40,13 @@ public class TrackTest {
|
||||||
Assertions.assertEquals('b', trackObj.getCarId(1));
|
Assertions.assertEquals('b', trackObj.getCarId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* checks if track reads space typ from track file correctly
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Check getSpaceTyp")
|
@DisplayName("Check getSpaceTyp")
|
||||||
void getSpaceTyp() {
|
void getSpaceTyp() {
|
||||||
Assertions.assertEquals(ConfigSpecification.SpaceType.FINISH_RIGHT, trackObj.getSpaceType(new PositionVector(22, 24)));
|
Assertions.assertEquals(ConfigSpecification.SpaceType.FINISH_RIGHT, trackObj.getSpaceType(new PositionVector(22, 24)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* checks if track finds the finish line at the correct positions
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Find FinishLine")
|
@DisplayName("Find FinishLine")
|
||||||
void findFinish() {
|
void findFinish() {
|
||||||
|
@ -75,11 +57,8 @@ public class TrackTest {
|
||||||
Assertions.assertEquals(expected, trackObj.getFinishLine());
|
Assertions.assertEquals(expected, trackObj.getFinishLine());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if track does read in track file correctly
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Converts track file correctly to List<String>")
|
@DisplayName("Converts Trackfile correctly to List<String>")
|
||||||
void checkTrack() {
|
void checkTrack() {
|
||||||
Track trackObj;
|
Track trackObj;
|
||||||
try {
|
try {
|
||||||
|
@ -100,14 +79,11 @@ public class TrackTest {
|
||||||
track.add("##################################################");
|
track.add("##################################################");
|
||||||
track.add("##################################################");
|
track.add("##################################################");
|
||||||
Assertions.assertLinesMatch(track, trackObj.getTrack());
|
Assertions.assertLinesMatch(track, trackObj.getTrack());
|
||||||
} catch (FileNotFoundException | InvalidTrackFormatException e) {
|
} catch (FileNotFoundException | InvalidTrackFormatException | PositionVectorNotValid e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* checks if track does process car move correctly
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Make Car move down on track")
|
@DisplayName("Make Car move down on track")
|
||||||
void makeCarMoveDown() {
|
void makeCarMoveDown() {
|
||||||
|
@ -119,9 +95,6 @@ public class TrackTest {
|
||||||
Assertions.assertEquals(beforeMove.getX(), afterMove.getX());
|
Assertions.assertEquals(beforeMove.getX(), afterMove.getX());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if car does not move if there is no acceleration
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Make Car move with (0,0) acceleration on track")
|
@DisplayName("Make Car move with (0,0) acceleration on track")
|
||||||
void makeCarStay() {
|
void makeCarStay() {
|
||||||
|
@ -132,58 +105,52 @@ public class TrackTest {
|
||||||
Assertions.assertEquals(beforeMove.getX(), afterMove.getX());
|
Assertions.assertEquals(beforeMove.getX(), afterMove.getX());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if car does crash
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Will Car Crash")
|
@DisplayName("Will Car Crash")
|
||||||
void willCarCrash() {
|
void willCarCrash() {
|
||||||
//Car will Crash
|
try {
|
||||||
Assertions.assertTrue(trackObj.willCrashAtPosition(0, new PositionVector(25, 21)));
|
//Car will Crash
|
||||||
//Car will not Crash and is on track
|
Assertions.assertTrue(trackObj.willCrashAtPosition(0, new PositionVector(25, 21)));
|
||||||
Assertions.assertFalse(trackObj.willCrashAtPosition(0, new PositionVector(7, 22)));
|
//Car will not Crash and is on track
|
||||||
//Car will not Crash and is on finishLine
|
Assertions.assertFalse(trackObj.willCrashAtPosition(0, new PositionVector(7, 22)));
|
||||||
Assertions.assertFalse(trackObj.willCrashAtPosition(0, trackObj.getFinishLine().get(0)));
|
//Car will not Crash and is on finishLine
|
||||||
|
Assertions.assertFalse(trackObj.willCrashAtPosition(0, trackObj.getFinishLine().get(0)));
|
||||||
|
} catch (PositionVectorNotValid positionVectorNotValid) {
|
||||||
|
positionVectorNotValid.printStackTrace();
|
||||||
|
Assertions.fail("Test should not throw error");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* checks if track is updated after car crash
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Make Car Crash")
|
@DisplayName("Make Car Crash")
|
||||||
void makeCarCrash() {
|
void makeCarCrash() {
|
||||||
trackObj.carDoesCrash(0, new PositionVector(6, 22));
|
try {
|
||||||
|
trackObj.carDoesCrash(0, new PositionVector(6, 22));
|
||||||
|
} catch (PositionVectorNotValid positionVectorNotValid) {
|
||||||
|
positionVectorNotValid.printStackTrace();
|
||||||
|
Assertions.fail("Test should not throw exception");
|
||||||
|
}
|
||||||
Assertions.assertEquals(Track.CRASH_INDICATOR, trackObj.getTrack().get(22).charAt(6));
|
Assertions.assertEquals(Track.CRASH_INDICATOR, trackObj.getTrack().get(22).charAt(6));
|
||||||
Assertions.assertTrue(trackObj.getCar(0).isCrashed());
|
Assertions.assertTrue(trackObj.getCar(0).isCrashed());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This testcase does check for negative test cases
|
|
||||||
*/
|
|
||||||
@Nested
|
@Nested
|
||||||
@DisplayName("Negative TestCase")
|
@DisplayName("Negative TestCase")
|
||||||
class negativeClass {
|
class negativeClass {
|
||||||
File file;
|
File file;
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up the negative Test cases by loading the file and setting a new track.
|
|
||||||
*/
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setup() {
|
void setup() {
|
||||||
file = new File(".\\tracks\\challenge.txt");
|
file = new File(".\\tracks\\challenge.txt");
|
||||||
try {
|
try {
|
||||||
trackObj = new Track(file);
|
trackObj = new Track(file);
|
||||||
|
|
||||||
} catch (InvalidTrackFormatException | FileNotFoundException e) {
|
} catch (Exception | PositionVectorNotValid e) {
|
||||||
System.err.println("Error in Test compareTrack" + e.getMessage());
|
System.err.println("Error in Test compareTrack" + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to read not valid file
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Throw error if File not found")
|
@DisplayName("Throw error if File not found")
|
||||||
void canReadFile() {
|
void canReadFile() {
|
||||||
|
@ -191,14 +158,20 @@ public class TrackTest {
|
||||||
Assertions.assertThrows(FileNotFoundException.class, () -> new Track(file));
|
Assertions.assertThrows(FileNotFoundException.class, () -> new Track(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to read not valid file with 2 cars with same symbol
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Throw error if File is invalid")
|
@DisplayName("Throw error if File is invalid")
|
||||||
void invalidTrackFile() {
|
void invalidTrackFile() {
|
||||||
File testFile = new File(".\\src\\test\\InvalidTracks\\sameCar.txt");
|
File testfile = new File(".\\src\\test\\InvalidTracks\\sameCar.txt");
|
||||||
Assertions.assertThrows(InvalidTrackFormatException.class, () -> new Track(testFile));
|
Assertions.assertThrows(InvalidTrackFormatException.class, () -> new Track(testfile));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Invalid Position Vector used")
|
||||||
|
void invalidPositionVector() {
|
||||||
|
Assertions.assertThrows(PositionVectorNotValid.class, () -> trackObj.willCrashAtPosition(0, new PositionVector(100, 200)));
|
||||||
|
Assertions.assertThrows(PositionVectorNotValid.class, () -> trackObj.carDoesCrash(1,new PositionVector(200,100)));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue