Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
976b153edb
|
@ -1,10 +1,10 @@
|
|||
# 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 players car to get to the finish line safely.
|
||||
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.
|
||||
|
||||
# Initialization:
|
||||
#### The game can be initialized by the terminal command:
|
||||
|
|
|
@ -2,7 +2,6 @@ package ch.zhaw.pm2.racetrack;
|
|||
|
||||
import ch.zhaw.pm2.racetrack.given.GameSpecification;
|
||||
import ch.zhaw.pm2.racetrack.strategy.*;
|
||||
import org.hamcrest.core.IsInstanceOf;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
@ -29,7 +28,7 @@ public class Game implements GameSpecification {
|
|||
}
|
||||
|
||||
/**
|
||||
* This method will initialize the game. Therefore it interacts with the user via UserInterface
|
||||
* This method will initialize the game. Therefore, it interacts with the user via UserInterface
|
||||
*
|
||||
* @return true if the initialization is completed. Returns false if there is an error.
|
||||
*/
|
||||
|
@ -85,7 +84,7 @@ public class Game implements GameSpecification {
|
|||
}
|
||||
return true;
|
||||
} else {
|
||||
userInterface.printInformation("No Trackfile found!");
|
||||
userInterface.printInformation("No track file found!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -137,7 +136,8 @@ public class Game implements GameSpecification {
|
|||
}
|
||||
|
||||
/**
|
||||
* The functionality was taken out of init to automate testing
|
||||
* 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
|
||||
*/
|
||||
|
@ -147,6 +147,7 @@ public class Game implements GameSpecification {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets a desired move strategy for a desired car.
|
||||
* The functionality was taken out of init to automate testing
|
||||
*
|
||||
* @param car to set the MoveStrategy
|
||||
|
@ -168,7 +169,7 @@ public class Game implements GameSpecification {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the id of the specified car.
|
||||
* Gets the id of the specified car.
|
||||
*
|
||||
* @param carIndex The zero-based carIndex number
|
||||
* @return A char containing the id of the car
|
||||
|
@ -241,7 +242,7 @@ 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
|
||||
* 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 cars acceleration vector (-1,0,1) in x and y direction
|
||||
* @param acceleration A Direction containing the current car's acceleration vector (-1,0,1) in x and y direction
|
||||
* for this turn
|
||||
*/
|
||||
@Override
|
||||
|
@ -273,7 +274,8 @@ public class Game implements GameSpecification {
|
|||
}
|
||||
|
||||
/**
|
||||
* This method implements the gameflow in a while loop. If there is a winner. The method will return its carid.
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
@ -337,52 +339,6 @@ public class Game implements GameSpecification {
|
|||
return track.calculatePointsOnPath(startPosition, endPosition);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method will check if a car is passing the finishline.
|
||||
* If the car is passing the finishline in the wrong direction, the car will lose a winpoint.
|
||||
* If the car is passing the finishline in the correct direction, the car will gain a winpoint.
|
||||
*
|
||||
* @param start the startposition of the car
|
||||
* @param finish the expected finishpositon of the car after the move
|
||||
*/
|
||||
private void calculateWinner(PositionVector start, PositionVector finish, int carIndex) {
|
||||
List<PositionVector> path = calculatePath(start, finish);
|
||||
for (PositionVector point : path) {
|
||||
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.
|
||||
*
|
||||
|
@ -395,6 +351,11 @@ public class Game implements GameSpecification {
|
|||
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() {
|
||||
int carsLeft = 0;
|
||||
for (int carIndex = 0; carIndex < track.getCarCount(); carIndex++) {
|
||||
|
@ -405,6 +366,11 @@ public class Game implements GameSpecification {
|
|||
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() {
|
||||
for (int carIndex = 0; carIndex < track.getCarCount(); carIndex++) {
|
||||
if (!(track.getCar(carIndex).isCrashed() || track.getCar(carIndex).getMoveStrategy().getClass() == DoNotMoveStrategy.class)) {
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
package ch.zhaw.pm2.racetrack;
|
||||
|
||||
/**
|
||||
* Class for Exception when invalid Fileformat is used.
|
||||
* Class for Exception when invalid file format is used.
|
||||
*/
|
||||
public class InvalidFileFormatException extends Exception {
|
||||
public InvalidFileFormatException() {
|
||||
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);
|
||||
}
|
||||
public InvalidFileFormatException(){super();}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ public class InvalidTrackFormatException extends Exception {
|
|||
public InvalidTrackFormatException(String errorMessage) {
|
||||
super(errorMessage);
|
||||
}
|
||||
|
||||
public InvalidTrackFormatException() {
|
||||
super();
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ public final class PositionVector {
|
|||
|
||||
/**
|
||||
* Adds two PositionVectors (e.g. car position and velocity vector or two velocity vectors).
|
||||
*
|
||||
* @param vectorA A position or velocity vector
|
||||
* @param vectorB A position or velocity vector
|
||||
* @return A new PositionVector holding the result of the addition. If both
|
||||
|
@ -45,6 +46,7 @@ public final class PositionVector {
|
|||
|
||||
/**
|
||||
* Subtracts two PositionVectors (e.g. car position and velocity vector or two velocity vectors).
|
||||
*
|
||||
* @param vectorA A position or velocity vector
|
||||
* @param vectorB A position or velocity vector
|
||||
* @return A new PositionVector holding the result of the addition. If both
|
||||
|
@ -58,6 +60,7 @@ public final class PositionVector {
|
|||
/**
|
||||
* Calculates the scalar product (Skalarprodukt) of two 2D vectors. The scalar product
|
||||
* multiplies the lengths of the parallel components of the vectors.
|
||||
*
|
||||
* @param vectorA A position or velocity vector
|
||||
* @param vectorB A position or velocity vector
|
||||
* @return The scalar product (vectorA * vectorB). Since vectorA and
|
||||
|
@ -75,6 +78,7 @@ public final class PositionVector {
|
|||
|
||||
/**
|
||||
* Copy constructor
|
||||
*
|
||||
* @param other
|
||||
*/
|
||||
public PositionVector(final PositionVector other) {
|
||||
|
|
|
@ -11,6 +11,7 @@ public class DoNotMoveStrategy implements MoveStrategy {
|
|||
|
||||
/**
|
||||
* This method will be used to return the next Direction for the car.
|
||||
*
|
||||
* @return a NONE Direction
|
||||
*/
|
||||
@Override
|
||||
|
|
|
@ -9,7 +9,7 @@ import java.util.List;
|
|||
/**
|
||||
* Strategy which calculates the path automatically
|
||||
*/
|
||||
public class PathFinderMoveStrategy implements MoveStrategy{
|
||||
public class PathFinderMoveStrategy implements MoveStrategy {
|
||||
private final Track track;
|
||||
private final int carIndex;
|
||||
private List<PositionVector.Direction> moveList;
|
||||
|
@ -23,6 +23,7 @@ public class PathFinderMoveStrategy implements MoveStrategy{
|
|||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
@ -36,17 +37,17 @@ public class PathFinderMoveStrategy implements MoveStrategy{
|
|||
/**
|
||||
* Method to create a working moveList
|
||||
*/
|
||||
private void createMoveList(){
|
||||
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<>();
|
||||
List<PossibleMove> possibleMoves = new ArrayList<>();
|
||||
|
||||
// create a PossibleMove object for each direction which doesn't end with a crash.
|
||||
for(PositionVector.Direction direction : allDirections){
|
||||
for (PositionVector.Direction direction : allDirections) {
|
||||
PossibleMove newMove = new PossibleMove(null, direction);
|
||||
if(! newMove.crashed()){
|
||||
if (!newMove.crashed()) {
|
||||
possibleMoves.add(newMove);
|
||||
}
|
||||
|
||||
|
@ -54,16 +55,16 @@ public class PathFinderMoveStrategy implements MoveStrategy{
|
|||
|
||||
// while no PossibleMove crosses the finishline
|
||||
// every PossibleMove will be accelerated in each direction to find a Move which finishes.
|
||||
while(finishedMove == null){
|
||||
while (finishedMove == null) {
|
||||
List<PossibleMove> newMoves = new ArrayList<>();
|
||||
for(PossibleMove previousMove : possibleMoves){
|
||||
for(PositionVector.Direction direction : allDirections){
|
||||
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()){
|
||||
if (!(newMove.crashed() || alreadyCalculated(newState) || finishedMove != null)) {
|
||||
if (newMove.finished()) {
|
||||
finishedMove = newMove;
|
||||
} else {
|
||||
calculatedStates.add(newState);
|
||||
|
@ -82,12 +83,13 @@ public class PathFinderMoveStrategy implements MoveStrategy{
|
|||
|
||||
/**
|
||||
* 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)){
|
||||
private boolean alreadyCalculated(State state) {
|
||||
for (State calculatedState : calculatedStates) {
|
||||
if (state.equals(calculatedState)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -97,26 +99,28 @@ public class PathFinderMoveStrategy implements MoveStrategy{
|
|||
/**
|
||||
* Combination of position and velocity
|
||||
*/
|
||||
public static class State{
|
||||
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){
|
||||
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){
|
||||
public boolean equals(State compareState) {
|
||||
return compareState.position.equals(position) && compareState.velocity.equals(velocity);
|
||||
}
|
||||
}
|
||||
|
@ -136,21 +140,21 @@ public class PathFinderMoveStrategy implements MoveStrategy{
|
|||
|
||||
/**
|
||||
* 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){
|
||||
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){
|
||||
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
|
||||
} 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
|
||||
}
|
||||
|
@ -161,20 +165,22 @@ public class PathFinderMoveStrategy implements MoveStrategy{
|
|||
|
||||
/**
|
||||
* check if the finishline is crossed (in correct direction) if this move is executed
|
||||
*
|
||||
* @return true if finishline will be crossed
|
||||
*/
|
||||
public boolean finished(){
|
||||
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)){
|
||||
for (PositionVector point : points) {
|
||||
if (track.willCrashAtPosition(carIndex, point)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -187,6 +193,7 @@ public class PathFinderMoveStrategy implements MoveStrategy{
|
|||
/**
|
||||
* 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
|
||||
|
@ -197,8 +204,8 @@ public class PathFinderMoveStrategy implements MoveStrategy{
|
|||
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)){
|
||||
for (PositionVector point : track.calculatePointsOnPath(currentPosition, newPosition)) {
|
||||
if (track.willCrashAtPosition(carIndex, point)) {
|
||||
createMoveList();
|
||||
pointer = 0;
|
||||
direction = moveList.get(pointer);
|
||||
|
|
Loading…
Reference in New Issue