Merge remote-tracking branch 'origin/main'

# Conflicts:
#	src/main/java/ch/zhaw/pm2/racetrack/Game.java
#	src/main/java/ch/zhaw/pm2/racetrack/Track.java
This commit is contained in:
Andrin Fassbind 2022-03-24 16:57:00 +01:00
commit 80b07111de
10 changed files with 129 additions and 82 deletions

View File

@ -3,14 +3,12 @@ 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 racetrack 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 acelleration vector. * The velocity is changed by providing an acceleration 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 {
@ -46,6 +44,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
*/ */
@ -83,6 +82,7 @@ public class Car implements CarSpecification {
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.
@ -95,8 +95,7 @@ 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;
} }
} }
@ -126,8 +125,7 @@ public class Car implements CarSpecification {
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());
} }
@ -161,6 +159,7 @@ public class Car implements CarSpecification {
/** /**
* Set move strategy * Set move strategy
*
* @param moveStrategy Strategy to be implemented * @param moveStrategy Strategy to be implemented
*/ */
public void setMoveStrategy(MoveStrategy moveStrategy) { public void setMoveStrategy(MoveStrategy moveStrategy) {
@ -169,6 +168,7 @@ public class Car implements CarSpecification {
/** /**
* Get current move strategy * Get current move strategy
*
* @return MoveStrategy * @return MoveStrategy
*/ */
public MoveStrategy getMoveStrategy() { public MoveStrategy getMoveStrategy() {

View File

@ -18,8 +18,7 @@ public class Main {
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);
@ -27,8 +26,7 @@ public class Main {
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;
} }

View File

@ -7,8 +7,8 @@ package ch.zhaw.pm2.racetrack;
* Created by mach 21.01.2020 * Created by mach 21.01.2020
*/ */
public final class PositionVector { public final class PositionVector {
private int x; // horizontal component (position / velocity) private final int x; // horizontal component (position / velocity)
private int y; // vertical component (position / velocity) private final int y; // vertical component (position / velocity)
/** /**
* Enum representing a direction on the track grid. * Enum representing a direction on the track grid.

View File

@ -3,7 +3,10 @@ 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.*; import java.io.File;
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;
@ -57,8 +60,8 @@ import java.util.Scanner;
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 List<String> track; private final List<String> track;
private List<Car> cars; private final List<Car> cars;
private final List<PositionVector> finishLine; private final List<PositionVector> finishLine;
private ConfigSpecification.SpaceType finishTyp; private ConfigSpecification.SpaceType finishTyp;
@ -85,13 +88,17 @@ 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),"UTF-8"); Scanner scanner = new Scanner(new FileInputStream(trackFile), StandardCharsets.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 cars 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<>();
@ -101,23 +108,26 @@ public class Track implements TrackSpecification {
allSpaceTypesAsChar.add(spaceType.getValue()); allSpaceTypesAsChar.add(spaceType.getValue());
} }
for (int yPosition = 0; yPosition < track.size(); yPosition++) {
for (int j = 0; j < track.size(); j++) { String line = track.get(yPosition);
String line = track.get(j); for (int xPosition = 0; xPosition < line.length(); xPosition++) {
for (int i = 0; i < line.length(); i++) { char possibleCarChar = line.charAt(xPosition);
char possibleCarChar = line.charAt(i);
if (!allSpaceTypesAsChar.contains(possibleCarChar)) { if (!allSpaceTypesAsChar.contains(possibleCarChar)) {
if (usedSymbolForCar.contains(possibleCarChar)) { if (usedSymbolForCar.contains(possibleCarChar)) {
throw new InvalidTrackFormatException(); throw new InvalidTrackFormatException();
} }
usedSymbolForCar.add(possibleCarChar); usedSymbolForCar.add(possibleCarChar);
cars.add(new Car(possibleCarChar, new PositionVector(i, j))); cars.add(new Car(possibleCarChar, new PositionVector(xPosition, yPosition)));
} }
} }
} }
} }
//TODO: THIS
/**
*
* @throws InvalidTrackFormatException
*/
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);
@ -141,6 +151,12 @@ public class Track implements TrackSpecification {
} }
} }
/**
* 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++) {
@ -154,12 +170,27 @@ 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);
track.remove(positionVector.getY()); track.remove(positionVector.getY());
track.add(positionVector.getY(), line); track.add(positionVector.getY(), line);
} }
//TODO: check if this method is okay and needed
/**
* Determines if a location is valid PositionVector inside the track
*
* @param positionVector of location that has to be checked
* @throws PositionVectorNotValid if the PositionVector does not lie on the track.
*/
private void isPositionVectorOnTrack(PositionVector positionVector) throws PositionVectorNotValid {
try {
private void isPositionVectorOnTrack(PositionVector positionVector) throws PositionVectorNotValidException { private void isPositionVectorOnTrack(PositionVector positionVector) throws PositionVectorNotValidException {
try{ try{
@ -169,22 +200,20 @@ public class Track implements TrackSpecification {
} }
} }
/**
* @return all Cars
*/
public List<Car> getCars() {
return cars;
}
/** /**
* @return finishLine * Method that returns the finishline as a List
*
* @return finishLine List
*/ */
public List<PositionVector> getFinishLine() { public List<PositionVector> getFinishLine() {
return finishLine; return finishLine;
} }
/** /**
* @return the track * Returns the whole Track as List of Strings
*
* @return track as List of Strings
*/ */
public List<String> getTrack() { public List<String> getTrack() {
return track; return track;
@ -203,7 +232,7 @@ public class Track implements TrackSpecification {
} }
/** /**
* This class does change the Position of the car only in the track. * This Method does change the Position of the car inside the track object.
* *
* @param carIndex of the current car * @param carIndex of the current car
*/ */
@ -225,10 +254,10 @@ public class Track implements TrackSpecification {
} }
/** /**
* This Method will check if the Car could crash at the specific position * This Method will check if the Car would crash at the specific position
* *
* @param positionVector the position to check if the car could crash * @param positionVector the position to check if the car would crash
* @return true if car would crash. Else false. * @return true if crash otherwise false
*/ */
public boolean willCrashAtPosition(int carIndex, PositionVector positionVector) throws PositionVectorNotValidException { public boolean willCrashAtPosition(int carIndex, PositionVector positionVector) throws PositionVectorNotValidException {
isPositionVectorOnTrack(positionVector); //TODO: remove this line? Or Method? isPositionVectorOnTrack(positionVector); //TODO: remove this line? Or Method?
@ -242,10 +271,10 @@ public class Track implements TrackSpecification {
} }
/** /**
* This Method will make the Car Crash. In Track and in the Car Object * This Method will mark the Car as crashed inside the track and the car Object.
* *
* @param carIndex representing current Car * @param carIndex of car that will be marked as crashed
* @param crashPositionVector where the Crash did happen * @param crashPositionVector of the location of the crash
*/ */
public void carDoesCrash(int carIndex, PositionVector crashPositionVector) throws PositionVectorNotValidException { public void carDoesCrash(int carIndex, PositionVector crashPositionVector) throws PositionVectorNotValidException {
isPositionVectorOnTrack(crashPositionVector); //TODO: remove this line? and Method? isPositionVectorOnTrack(crashPositionVector); //TODO: remove this line? and Method?
@ -262,10 +291,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 track position at the given location * @return The type of space at the desired position
*/ */
@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) {
@ -277,9 +307,9 @@ public class Track implements TrackSpecification {
} }
/** /**
* Return the number of cars. * Return the number of cars that are located in a track
* *
* @return Number of cars * @return number of cars as int
*/ */
@Override @Override
public int getCarCount() { public int getCarCount() {
@ -353,6 +383,13 @@ 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) { public ArrayList<PositionVector> calculatePointsOnPath(PositionVector startPosition, PositionVector endPosition) {
ArrayList<PositionVector> pathList = new ArrayList<>(); ArrayList<PositionVector> pathList = new ArrayList<>();
// Use Bresenham's algorithm to determine positions. // Use Bresenham's algorithm to determine positions.

View File

@ -6,13 +6,20 @@ import org.beryx.textio.TextTerminal;
import java.util.List; import java.util.List;
/**
* Class representing the Userinterface.
* Used to get inputs from users via textio.
*
* @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) {
@ -24,6 +31,7 @@ public class UserInterface {
/** /**
* 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) {
@ -31,8 +39,9 @@ public class UserInterface {
} }
/** /**
* asks the user to choose one of the options given. * Method which 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
*/ */
@ -45,7 +54,8 @@ public class UserInterface {
} }
/** /**
* gives information which player's turn it is and asks for the direction to accelerate * Gives information which player is at turn and asks for the direction to accelerate or quit the game.
*
* @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
@ -70,7 +80,8 @@ public class UserInterface {
} }
/** /**
* returns the the associated direction Object * Method which returns 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
*/ */
@ -90,7 +101,8 @@ public class UserInterface {
} }
/** /**
* prints the given Track in the terminal * Method to print 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) {
@ -98,14 +110,12 @@ public class UserInterface {
} }
/** /**
* Method to dispose the Textterminal * Method to dispose of 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();
} }
} }

View File

@ -5,13 +5,14 @@ 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;
public class MoveListStrategy implements MoveStrategy { public class MoveListStrategy implements MoveStrategy {
private List<Direction> moveList; private final List<Direction> moveList;
private int pointer; private int pointer;
public MoveListStrategy(String path) throws FileNotFoundException{ public MoveListStrategy(String path) throws FileNotFoundException{
@ -21,7 +22,7 @@ public class MoveListStrategy implements MoveStrategy {
} }
private void readFile(File trackFile) throws FileNotFoundException { private void readFile(File trackFile) throws FileNotFoundException {
Scanner scanner = new Scanner(new FileInputStream(trackFile), "UTF-8"); Scanner scanner = new Scanner(new FileInputStream(trackFile), StandardCharsets.UTF_8);
Direction[] directions = Direction.values(); Direction[] directions = Direction.values();
while (scanner.hasNextLine()) { while (scanner.hasNextLine()) {
String line = scanner.nextLine(); String line = scanner.nextLine();

View File

@ -6,6 +6,7 @@ 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;
@ -25,7 +26,7 @@ public class PathFollowerMoveStrategy implements MoveStrategy {
/** /**
* List of all points on the path. * List of all points on the path.
*/ */
private ArrayList<PositionVector> pointList; private final ArrayList<PositionVector> pointList;
/** /**
* The index of the next point on the path. * The index of the next point on the path.
*/ */
@ -51,7 +52,7 @@ public class PathFollowerMoveStrategy implements MoveStrategy {
* @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 { public void readFile(File trackFile) throws FileNotFoundException {
Scanner scanner = new Scanner(new FileInputStream(trackFile), "UTF-8"); Scanner scanner = new Scanner(new FileInputStream(trackFile), StandardCharsets.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:|\\))");

View File

@ -7,9 +7,9 @@ import ch.zhaw.pm2.racetrack.UserInterface;
* Let the user decide the next move. * Let the user decide the next move.
*/ */
public class UserMoveStrategy implements MoveStrategy { public class UserMoveStrategy implements MoveStrategy {
private UserInterface userInterface; private final UserInterface userInterface;
private int carIndex; private final int carIndex;
private char carID; private final char carID;
public UserMoveStrategy(UserInterface userInterface, int carIndex, char carID) { public UserMoveStrategy(UserInterface userInterface, int carIndex, char carID) {
this.userInterface = userInterface; this.userInterface = userInterface;

View File

@ -101,7 +101,7 @@ class CarTest {
@Test @Test
void movement() { void movement() {
// add all possible directions in a List // add all possible directions in a List
List<PositionVector.Direction> directions = Arrays.asList(PositionVector.Direction.values()); PositionVector.Direction[] directions = PositionVector.Direction.values();
//position shouldn't be changed because velocity should be 0. //position shouldn't be changed because velocity should be 0.
car.move(); car.move();

View File

@ -21,9 +21,9 @@ class GameTest {
private Game game; private Game game;
private Track track; private Track track;
private String TRACK_FILE_PATH = ".\\tracks\\challenge.txt"; private final String TRACK_FILE_PATH = ".\\tracks\\challenge.txt";
private int CAR_INDEX_ONE = 0; private final int CAR_INDEX_ONE = 0;
private int CAR_INDEX_TWO = 1; private final int CAR_INDEX_TWO = 1;
/** /**
* This nested Class tests if the game gets initiatet correctly * This nested Class tests if the game gets initiatet correctly