Compare commits
90
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa4842e440 | ||
|
|
dc704cce4c | ||
|
|
082d1414f5 | ||
|
|
7c87f4b2fd | ||
|
|
1c63c0cb21 | ||
|
|
787ddd7155 | ||
|
|
a14327a2a7 | ||
|
|
ded9023ff1 | ||
|
|
2de3993921 | ||
|
|
de91717a48 | ||
|
|
826f67d125 | ||
|
|
6ac4f64456 | ||
|
|
b1a4f3b3db | ||
|
|
45918124df | ||
|
|
b8dda0b96a | ||
|
|
dc34d984f8 | ||
|
|
8877f1476f | ||
|
|
c59e4a30d8 | ||
|
|
eddf9d3daa | ||
|
|
fe74d017b2 | ||
|
|
b467a79596 | ||
|
|
d7a593be30 | ||
|
|
8826561963 | ||
|
|
a80ea0fa1c | ||
|
|
fc78b10365 | ||
|
|
fec3aceaa6 | ||
|
|
833b122d2b | ||
|
|
67c5a79174 | ||
|
|
837297cd31 | ||
|
|
c30d7a2988 | ||
|
|
21da4feaf5 | ||
|
|
dad57ea8ac | ||
|
|
e6fc0fde39 | ||
|
|
9869e8e74d | ||
|
|
1c618ad09a | ||
|
|
3684b5589e | ||
|
|
fd4513e0d0 | ||
|
|
504d5c62ef | ||
|
|
848d62a5f9 | ||
|
|
8dad26006c | ||
|
|
268506a084 | ||
|
|
74a83e790a | ||
|
|
e1e03d4ad4 | ||
|
|
63204a4b29 | ||
|
|
e5f45b7bb1 | ||
|
|
a723ea16ec | ||
|
|
5ec7260b1e | ||
|
|
9b6908ef47 | ||
|
|
06ad28fbe8 | ||
|
|
b606f20d9f | ||
|
|
d02c04f91d | ||
|
|
e94053fee8 | ||
|
|
8929d295b9 | ||
|
|
884b349077 | ||
|
|
af6914f795 | ||
|
|
7e5d349f3f | ||
|
|
e159274085 | ||
|
|
dd987a5a14 | ||
|
|
bf08749f28 | ||
|
|
dd625907c9 | ||
|
|
3fe1bb1426 | ||
|
|
6285cfe215 | ||
|
|
156f6d0cab | ||
|
|
ddbf666cc8 | ||
|
|
57a5d199a6 | ||
|
|
dca575999e | ||
|
|
6080b48b82 | ||
|
|
4ebe8cb1ed | ||
|
|
0fafa3e0e7 | ||
|
|
c4ea4d1920 | ||
|
|
16e4460a47 | ||
|
|
a67a96d19d | ||
|
|
46e6b838c2 | ||
|
|
ee68bf9a1d | ||
|
|
befc67f4f0 | ||
|
|
19b227c59f | ||
|
|
cbc915bf50 | ||
|
|
d6a46f3cae | ||
|
|
b6f69d3c1c | ||
|
|
5afd0b0b61 | ||
|
|
15123b05bb | ||
|
|
31a24120eb | ||
|
|
007d8ee393 | ||
|
|
dea430e418 | ||
|
|
40cd4f7b72 | ||
|
|
8086111772 | ||
|
|
972f011a08 | ||
|
|
571728b6fd | ||
|
|
8ff70ab3ac | ||
|
|
381ea44a9a |
@@ -0,0 +1 @@
|
|||||||
|
<mxfile host="Electron" modified="2022-03-22T17:46:19.706Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/16.5.1 Chrome/96.0.4664.110 Electron/16.0.7 Safari/537.36" etag="blTsmpdlGFIXdx0F82xm" version="16.5.1" type="device"><diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">7Vtbd6I6GP01PraLi7c+qr3MzOn0OGNPe16jRMgxEE+Itc6vny8QQExVaGVorWt1rZKPkED2zpedDTbsgf98w9Hc+84cTBuW4Tw37MuGZZnwB/9kZBVHOu1mHHA5cVSlLDAiv7AKGiq6IA4OcxUFY1SQeT44YUGAJyIXQ5yzZb7alNF8r3PkYi0wmiCqRx+JI7w42rU6WfwLJq6X9Gy2L+IzPkoqqycJPeSw5VrIvmrYA86YiI/85wGmcvCScXn8unqkt7P2zbcf4f/on/5f93cPZ3Fj12UuSR+B40C8uulfs+n1l4fmf//Oh9c/lsZNb/ztTF1iPCG6UOM1xDxkgXpisUqGMVwSn6IASv0pC8RInYFB6CNK3ACOJ3B3mEPgCXNBAIGeOiHYHKITj1DnFq3YQj5DKNBklpT6HuPkFzSLKJwyIQCnuVBkstq5GiN5JYQNiHIcQp1hMjBmGrpFoVB1JoxSNA/JOLphWcVH3CVBnwnB/KQhtggc7KhSinRUEJzNUu7I6wvCoWCTo4Gf18io4LnBzMeCr6CKOttVaKiZ1lLFZUZbs61i3jpl7a6aLmqquGnLaWc/YWqhwIUhSHuz7Hx3ZrNgf4BHrjtEAfYACdyXgxiukxAO1h40C0XULEFTU6PpHfKxRlIYZ7FGSIqnYisdwzmakMC9jepcNrPIT/WkMsTg2imNqOARx8FBRBWBBIrZJPkxZyQQ0VC0+vAHAzYwzluNFtzQAMpmVoY/WZ2LAQuAVYhE9MFA1SWWdH2BWDsn7X5irfKIlUV2nUg5SMviZ+lpxmOBJOPdwh9D0jg2JHfkE0/4VB1WhXfLqhlvW8P7ykdEXtZzHMjQ4QnwgwLe6dYMeFMDXEOYkkg9qNEwX1xZ98DvA5CyuQTve0mHyzNT44Stc8J+AX+KxpgOWUgEYbJ9Htfd4EVdWds0msVQ3bH8vwnUlp61F3zioVAmbhBdMxje6OgI53NloJp15+a2hupILBz5mAU1v3HS/JVpfrtbreg37Vf2V4Po72wn6rHKxoJZp12YZe9lA9DVsOzB3UvrxjK+w0pydEgeVA+Wxrv2DcDFSQ8eHNSiIr8qOWjqZuFXSPzGFaARrbSWcc9kOeBMtnZkM3pdAjWrwrhbd6I2davtBssVd4R9EiAuAb9HM6w7xB8d36ogrV/xJzewKxvjwOnJty1QGlMmxXYfQkqNm0ZcvCY0Wbn2yOX88ocdFydTB9MxW15lgX4UgBMJU0qL7ZDBrhTvhwy2Fy4usJmTd7sT2JeA5JgiQZ7yL512aPOhJG6myy0jr8stw843ET+kumr9LU/ZhuJR0Bo6mFOvW39DzqY4DJku108bzOo3mLb5yh1fx9hL4hc2mHazQHed97HBNHXXcoQoUhn3E65t6eT9OBtLUzcpNfQ++06jPKxF94+VbTV0k/JTKZYEsXctWTYXls4rJcvmCmV1Nu6lasmiG43b3lKeBEv1gqW1oSAKf5Zi7lhjtguWVivf3bv+DEa3UUeCY6y/uvksgqVTmF3vRrDo1uiAiOOTnAc1wMvjXLsDnnw1mpurkB1OQB8W6No/fbF0xxSEvVzELWPAnBPgBwa88Gcx1SGu+6kDGBNxhMZB3VjbrxRjh8Na9zM1kD+9v1Ae11ZBGVaVwWDp1t8DQOQc4wJdHYrt2jOx7v79vRDzhXQXevJV5a2cBydECyN6UXu+Lef8sXk01uW8vdQWNOt3+tTY7jX6Eiz3On0KZ0mlnIuibuiNpp+98b2ieWHlmyhq+m26PFpDW0w/raGzzRdOG+2w6TTElfiGlu4bGufnCfAZXSMvbi0R7Ek7Y+XIxWt4H01mbsTfAaOMw/mAZf6jMrut4jkhmV/q55bqthrpjxyL+3Rnb2RUQsw/BpdunhXHKtFPHxWsw8z+5JPcPw6d7plReAq5wKOt3ueaHN9EVVfBRQz8VKPvxrqUif5GYmgE2MaV4uvExWGYknyevmHiv4UrUMx+bB1Xz36ybl/9Bg==</diagram></mxfile>
|
||||||
@@ -1,2 +1,39 @@
|
|||||||
# team02-AngryNerds-projekt1-racetrack
|
# 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.
|
||||||
|
|
||||||
|
# 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 startpoint 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
|
||||||
|
+ Path Follow Move Strategy
|
||||||
|
> A list of point has to be given to the follow move strategy, the strategy will then calculate the route to cross each point in the given order.
|
||||||
|
+ 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>
|
||||||
|
'#' is a Wall<br>
|
||||||
|
'>,<,^,v' are finish line components<br>
|
||||||
|
And every other character represents a car.
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
|
## Class Diagramm
|
||||||
|
|||||||
+2
-1
@@ -29,6 +29,7 @@ dependencies {
|
|||||||
|
|
||||||
// beryx uses SLF4J. To remove warning, we add the implementation "no operation"
|
// beryx uses SLF4J. To remove warning, we add the implementation "no operation"
|
||||||
implementation 'org.slf4j:slf4j-nop:2.+'
|
implementation 'org.slf4j:slf4j-nop:2.+'
|
||||||
|
implementation 'junit:junit:4.13.1'
|
||||||
|
|
||||||
// Use JUnit Jupiter API for testing.
|
// Use JUnit Jupiter API for testing.
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
|
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
|
||||||
@@ -43,7 +44,7 @@ version = '2022.1'
|
|||||||
|
|
||||||
application {
|
application {
|
||||||
// Define the main class for the application.
|
// Define the main class for the application.
|
||||||
mainClass = 'ch.zhaw.pm2.racetrack.ConsoleApp'
|
mainClass = 'ch.zhaw.pm2.racetrack.Main'
|
||||||
}
|
}
|
||||||
|
|
||||||
run {
|
run {
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
(X:40, Y:22)
|
||||||
|
(X:43, Y:22)
|
||||||
|
(X:46, Y:21)
|
||||||
|
(X:48, Y:19)
|
||||||
|
(X:48, Y:17)
|
||||||
|
(X:46, Y:15)
|
||||||
|
(X:41, Y:13)
|
||||||
|
(X:41, Y:10)
|
||||||
|
(X:46, Y:9)
|
||||||
|
(X:49, Y:4)
|
||||||
|
(X:40, Y:2)
|
||||||
|
(X:30, Y:2)
|
||||||
|
(X:21, Y:3)
|
||||||
|
(X:16, Y:7)
|
||||||
|
(X:13, Y:10)
|
||||||
|
(X:14, Y:14)
|
||||||
|
(X:11, Y:19)
|
||||||
|
(X:13, Y:22)
|
||||||
|
(X:24, Y:22)
|
||||||
@@ -3,6 +3,8 @@ 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.
|
||||||
@@ -22,6 +24,10 @@ public class Car implements CarSpecification {
|
|||||||
* Current position of the car on the track grid using a {@link PositionVector}
|
* Current position of the car on the track grid using a {@link PositionVector}
|
||||||
*/
|
*/
|
||||||
private PositionVector position;
|
private PositionVector position;
|
||||||
|
/**
|
||||||
|
* Points that car is holding for determining winner.
|
||||||
|
*/
|
||||||
|
private int winPoints;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current velocity of the car using a {@link PositionVector}
|
* Current velocity of the car using a {@link PositionVector}
|
||||||
@@ -48,17 +54,51 @@ public class Car implements CarSpecification {
|
|||||||
setPosition(position);
|
setPosition(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the id of the car.
|
||||||
|
*
|
||||||
|
* @return id of the car.
|
||||||
|
*/
|
||||||
|
public char getID(){
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void increaseWinPoints() {
|
||||||
|
winPoints ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deductWinPoints() {
|
||||||
|
winPoints --;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWinPoints() {
|
||||||
|
return winPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current velocity of the car as a PositionVector.
|
||||||
|
*
|
||||||
|
* @return velocity current velocity of the car.
|
||||||
|
*/
|
||||||
|
public PositionVector getVelocity(){
|
||||||
|
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 normaly 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.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setPosition(final PositionVector position) {
|
public void setPosition(final PositionVector position) {
|
||||||
// TODO: implementation
|
if (position.getX() < 0 || position.getY() < 0) {
|
||||||
throw new UnsupportedOperationException();
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,8 +109,7 @@ public class Car implements CarSpecification {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public PositionVector nextPosition() {
|
public PositionVector nextPosition() {
|
||||||
// TODO: implementation
|
return new PositionVector(position.getX() + velocity.getX(),position.getY() + velocity.getY());
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,11 +119,18 @@ public class Car implements CarSpecification {
|
|||||||
* Changes only velocity, not position.
|
* Changes only velocity, not position.
|
||||||
*
|
*
|
||||||
* @param acceleration A Direction vector containing the amounts to add to the velocity in x and y dimension
|
* @param acceleration A Direction vector containing the amounts to add to the velocity in x and y dimension
|
||||||
|
* @throws IllegalArgumentException if PositionVector is not in allowed area.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void accelerate(PositionVector.Direction acceleration) {
|
public void accelerate(PositionVector.Direction acceleration) {
|
||||||
// TODO: implementation
|
if(acceleration.vector.getX() < -1 || acceleration.vector.getX() > 1||
|
||||||
throw new UnsupportedOperationException();
|
acceleration.vector.getY() < -1 || acceleration.vector.getY() > 1) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
velocity = new PositionVector(velocity.getX() + acceleration.vector.getX(),
|
||||||
|
velocity.getY() + acceleration.vector.getY());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,8 +138,7 @@ public class Car implements CarSpecification {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void move() {
|
public void move() {
|
||||||
// TODO: implementation
|
position = new PositionVector(position.getX() + velocity.getX(), position.getY() + velocity.getY());
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,8 +146,7 @@ public class Car implements CarSpecification {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void crash() {
|
public void crash() {
|
||||||
// TODO: implementation
|
crashed = true;
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,13 +156,12 @@ public class Car implements CarSpecification {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isCrashed() {
|
public boolean isCrashed() {
|
||||||
// TODO: implementation
|
return crashed;
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set move strategy
|
* Set move strategy
|
||||||
* @param moveStrategy
|
* @param moveStrategy Strategy to be implemented
|
||||||
*/
|
*/
|
||||||
public void setMoveStrategy(MoveStrategy moveStrategy) {
|
public void setMoveStrategy(MoveStrategy moveStrategy) {
|
||||||
this.moveStrategy = moveStrategy;
|
this.moveStrategy = moveStrategy;
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package ch.zhaw.pm2.racetrack;
|
package ch.zhaw.pm2.racetrack;
|
||||||
|
|
||||||
import ch.zhaw.pm2.racetrack.given.GameSpecification;
|
import ch.zhaw.pm2.racetrack.given.GameSpecification;
|
||||||
|
import ch.zhaw.pm2.racetrack.strategy.*;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
import static ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
||||||
@@ -13,59 +17,158 @@ import static ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
|||||||
*/
|
*/
|
||||||
public class Game implements GameSpecification {
|
public class Game implements GameSpecification {
|
||||||
public static final int NO_WINNER = -1;
|
public static final int NO_WINNER = -1;
|
||||||
|
private Track track;
|
||||||
|
private int currentCarIndex;
|
||||||
|
|
||||||
|
UserInterface userInterface;
|
||||||
|
|
||||||
|
public Game(UserInterface userInterface) {
|
||||||
|
this.userInterface = userInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean initPhase() throws InvalidTrackFormatException {
|
||||||
|
File folder = new File("tracks");
|
||||||
|
File[] listOfFiles = folder.listFiles();
|
||||||
|
if (listOfFiles.length > 0) {
|
||||||
|
List<String> tracks = new ArrayList<>();
|
||||||
|
for (File file : listOfFiles) {
|
||||||
|
tracks.add(file.getName());
|
||||||
|
}
|
||||||
|
File selectedTrack = listOfFiles[userInterface.selectOption("Select Track file", tracks)];
|
||||||
|
selectTrack(selectedTrack);
|
||||||
|
List<String> moveStrategies = new ArrayList<>();
|
||||||
|
moveStrategies.add("Do not move Strategy");
|
||||||
|
moveStrategies.add("User Move Strategy");
|
||||||
|
moveStrategies.add("Move List Strategy");
|
||||||
|
moveStrategies.add("Path Follow Move Strategy");
|
||||||
|
for (int i = 0; i < track.getCarCount(); i++) {
|
||||||
|
Car car = track.getCar(i);
|
||||||
|
MoveStrategy moveStrategy = null;
|
||||||
|
while (moveStrategy == null) {
|
||||||
|
String filePath;
|
||||||
|
int moveStrategie = userInterface.selectOption(
|
||||||
|
"Select Strategy for Car " + i + " (" + track.getCarId(i) + ")", moveStrategies);
|
||||||
|
switch (moveStrategie + 1) {
|
||||||
|
case 1:
|
||||||
|
moveStrategy = new DoNotMoveStrategy();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
userInterface.printInformation("No Trackfile found!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The functionality was taken out of init to automate testing
|
||||||
|
*
|
||||||
|
* @param selectedTrack
|
||||||
|
*/
|
||||||
|
Track selectTrack(File selectedTrack) {
|
||||||
|
try {
|
||||||
|
track = new Track(selectedTrack);
|
||||||
|
return track;
|
||||||
|
} catch (FileNotFoundException | PositionVectorNotValid | InvalidTrackFormatException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The functionality was taken out of init to automate testing
|
||||||
|
*
|
||||||
|
* @param car to set the MoveStrategy
|
||||||
|
* @param strategy The movestrategy to set
|
||||||
|
*/
|
||||||
|
void selectMoveStrategy(Car car, MoveStrategy strategy) {
|
||||||
|
car.setMoveStrategy(strategy);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the index of the current active car.
|
* Return the index of the current active car.
|
||||||
* Car indexes are zero-based, so the first car is 0, and the last car is getCarCount() - 1.
|
* Car indexes are zero-based, so the first car is 0, and the last car is getCarCount() - 1.
|
||||||
|
*
|
||||||
* @return The zero-based number of the current car
|
* @return The zero-based number of the current car
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int getCurrentCarIndex() {
|
public int getCurrentCarIndex() {
|
||||||
// TODO: implementation
|
return currentCarIndex;
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get 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
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public char getCarId(int carIndex) {
|
public char getCarId(int carIndex) {
|
||||||
// TODO: implementation
|
return track.getCarId(carIndex);
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the position of the specified car.
|
* Get the position of the specified car.
|
||||||
|
*
|
||||||
* @param carIndex The zero-based carIndex number
|
* @param carIndex The zero-based carIndex number
|
||||||
* @return A PositionVector containing the car's current position
|
* @return A PositionVector containing the car's current position
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public PositionVector getCarPosition(int carIndex) {
|
public PositionVector getCarPosition(int carIndex) {
|
||||||
// TODO: implementation
|
return track.getCarPos(carIndex);
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the velocity of the specified car.
|
* Get the velocity of the specified car.
|
||||||
|
*
|
||||||
* @param carIndex The zero-based carIndex number
|
* @param carIndex The zero-based carIndex number
|
||||||
* @return A PositionVector containing the car's current velocity
|
* @return A PositionVector containing the car's current velocity
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public PositionVector getCarVelocity(int carIndex) {
|
public PositionVector getCarVelocity(int carIndex) {
|
||||||
// TODO: implementation
|
return track.getCarVelocity(carIndex);
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the winner of the game. If the game is still in progress, returns NO_WINNER.
|
* Return the winner of the game. If the game is still in progress, returns NO_WINNER.
|
||||||
|
*
|
||||||
* @return The winning car's index (zero-based, see getCurrentCar()), or NO_WINNER if the game is still in progress
|
* @return The winning car's index (zero-based, see getCurrentCar()), or NO_WINNER if the game is still in progress
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int getWinner() {
|
public int getWinner() {
|
||||||
// TODO: implementation
|
if (onlyOneCarLeft()) {
|
||||||
throw new UnsupportedOperationException();
|
return currentCarIndex;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < track.getCarCount(); i++) {
|
||||||
|
if (track.getCar(i).getWinPoints() == 1) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NO_WINNER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,9 +198,47 @@ public class Game implements GameSpecification {
|
|||||||
* for this turn
|
* for this turn
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void doCarTurn(Direction acceleration) {
|
public void doCarTurn(Direction acceleration) throws PositionVectorNotValid {
|
||||||
// TODO: implementation
|
track.getCar(currentCarIndex).accelerate(acceleration);
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
|
PositionVector crashPosition = null;
|
||||||
|
List<PositionVector> positionList = calculatePath(track.getCarPos(currentCarIndex), track.getCar(currentCarIndex).nextPosition());
|
||||||
|
for (int i = 0; i < positionList.size(); i++) {
|
||||||
|
if (willCarCrash(currentCarIndex, positionList.get(i))) {
|
||||||
|
if (i == 0) {
|
||||||
|
crashPosition = track.getCarPos(currentCarIndex);
|
||||||
|
} else {
|
||||||
|
crashPosition = positionList.get(i - 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (crashPosition != null) {
|
||||||
|
track.carDoesCrash(currentCarIndex, crashPosition);
|
||||||
|
} else {
|
||||||
|
calculateWinner(track.getCarPos(currentCarIndex), track.getCar(currentCarIndex).nextPosition(), currentCarIndex);
|
||||||
|
track.moveCar(currentCarIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String gamePhase() throws PositionVectorNotValid {
|
||||||
|
while (carsMoving() && getWinner() == NO_WINNER) {
|
||||||
|
userInterface.printTrack(track);
|
||||||
|
Direction direction;
|
||||||
|
direction = track.getCar(currentCarIndex).getMoveStrategy().nextMove();
|
||||||
|
if (direction == null) {
|
||||||
|
track.getCar(currentCarIndex).setMoveStrategy(new DoNotMoveStrategy());
|
||||||
|
direction = track.getCar(currentCarIndex).getMoveStrategy().nextMove();
|
||||||
|
}
|
||||||
|
doCarTurn(direction);
|
||||||
|
switchToNextActiveCar();
|
||||||
|
}
|
||||||
|
userInterface.printTrack(track);
|
||||||
|
int indexWinner = getWinner();
|
||||||
|
if (indexWinner == NO_WINNER) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return String.valueOf(track.getCar(indexWinner).getID());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,8 +246,14 @@ public class Game implements GameSpecification {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void switchToNextActiveCar() {
|
public void switchToNextActiveCar() {
|
||||||
// TODO: implementation
|
do {
|
||||||
throw new UnsupportedOperationException();
|
if ((currentCarIndex + 1) == track.getCarCount()) {
|
||||||
|
currentCarIndex = 0;
|
||||||
|
} else {
|
||||||
|
currentCarIndex++;
|
||||||
|
}
|
||||||
|
} while (track.getCar(currentCarIndex).isCrashed());
|
||||||
|
// TODO: evtl andere Kapselung
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -117,25 +264,86 @@ public class Game implements GameSpecification {
|
|||||||
* - Detect which axis of the distance vector is longer (faster movement)
|
* - Detect which axis of the distance vector is longer (faster movement)
|
||||||
* - for each pixel on the 'faster' axis calculate the position on the 'slower' axis.
|
* - for each pixel on the 'faster' axis calculate the position on the 'slower' axis.
|
||||||
* Direction of the movement has to correctly considered
|
* Direction of the movement has to correctly considered
|
||||||
|
*
|
||||||
* @param startPosition Starting position as a PositionVector
|
* @param startPosition Starting position as a PositionVector
|
||||||
* @param endPosition Ending position as a PositionVector
|
* @param endPosition Ending position as a PositionVector
|
||||||
* @return Intervening grid positions as a List of PositionVector's, including the starting and ending positions.
|
* @return Intervening grid positions as a List of PositionVector's, including the starting and ending positions.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<PositionVector> calculatePath(PositionVector startPosition, PositionVector endPosition) {
|
public List<PositionVector> calculatePath(PositionVector startPosition, PositionVector endPosition) {
|
||||||
// TODO: implementation
|
return track.calculatePointsOnPath(startPosition, endPosition);
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
*
|
||||||
* @param carIndex The zero-based carIndex number
|
* @param carIndex The zero-based carIndex number
|
||||||
* @param position A PositionVector of the possible crash position
|
* @param position A PositionVector of the possible crash position
|
||||||
* @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 {
|
||||||
// TODO: implementation
|
return track.willCrashAtPosition(carIndex, position);
|
||||||
throw new UnsupportedOperationException();
|
}
|
||||||
|
|
||||||
|
public boolean onlyOneCarLeft() {
|
||||||
|
int carsLeft = 0;
|
||||||
|
for (int carIndex = 0; carIndex < track.getCarCount(); carIndex++) {
|
||||||
|
if (!track.getCar(carIndex).isCrashed()) {
|
||||||
|
carsLeft++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !(carsLeft > 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean carsMoving() {
|
||||||
|
for (int carIndex = 0; carIndex < track.getCarCount(); carIndex++) {
|
||||||
|
if (!(track.getCar(carIndex).isCrashed() || track.getCar(carIndex).getMoveStrategy().getClass() == DoNotMoveStrategy.class)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
package ch.zhaw.pm2.racetrack;
|
package ch.zhaw.pm2.racetrack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for Exception when invalid Fileformat is used.
|
||||||
|
*/
|
||||||
public class InvalidFileFormatException extends Exception {
|
public class InvalidFileFormatException extends Exception {
|
||||||
// TODO: implementation
|
public InvalidFileFormatException(String errorMessage) {
|
||||||
|
super(errorMessage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
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 {
|
||||||
// TODO: implementation
|
public InvalidTrackFormatException(String errorMessage) {
|
||||||
|
super(errorMessage);
|
||||||
|
}
|
||||||
|
public InvalidTrackFormatException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package ch.zhaw.pm2.racetrack;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws InvalidTrackFormatException, PositionVectorNotValid {
|
||||||
|
UserInterface userInterface = new UserInterface("Hello and Welcome to Racetrack by Team02-\"AngryNerds\"");
|
||||||
|
while (true) {
|
||||||
|
Game game = new Game(userInterface);
|
||||||
|
String winner;
|
||||||
|
if (game.initPhase()) {
|
||||||
|
winner = game.gamePhase();
|
||||||
|
List<String> optionsNewGame = new ArrayList<>();
|
||||||
|
optionsNewGame.add("exit");
|
||||||
|
optionsNewGame.add("new game");
|
||||||
|
String winnerText;
|
||||||
|
if(winner == null){
|
||||||
|
winnerText = "There was no winner.";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
winnerText = "The Winner was Car " + winner;
|
||||||
|
}
|
||||||
|
int selectedOption = userInterface.selectOption(winnerText + "\nStart new Game?", optionsNewGame);
|
||||||
|
if(selectedOption == 0) {
|
||||||
|
userInterface.quit("Thank you and goodbye\npress enter to close the application.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
userInterface.quit("The initialisation of the game failed. Press enter to close the application.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package ch.zhaw.pm2.racetrack;
|
||||||
|
|
||||||
|
public class PositionVectorNotValid extends Throwable {
|
||||||
|
public PositionVectorNotValid(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PositionVectorNotValid() {}
|
||||||
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
package ch.zhaw.pm2.racetrack;
|
package ch.zhaw.pm2.racetrack;
|
||||||
|
|
||||||
|
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.FileNotFoundException;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents the racetrack board.
|
* This class represents the racetrack board.
|
||||||
@@ -54,8 +57,10 @@ import java.io.FileNotFoundException;
|
|||||||
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;
|
||||||
// TODO: Add necessary variables
|
private List<Car> cars;
|
||||||
|
private final List<PositionVector> finishLine;
|
||||||
|
private ConfigSpecification.SpaceType finishTyp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a Track from the given track file.
|
* Initialize a Track from the given track file.
|
||||||
@@ -64,9 +69,192 @@ public class Track implements TrackSpecification {
|
|||||||
* @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 tracklines, ...)
|
* @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 {
|
||||||
// TODO: implementation
|
track = new ArrayList<>();
|
||||||
throw new UnsupportedOperationException();
|
cars = new ArrayList<>();
|
||||||
|
finishLine = new ArrayList<>();
|
||||||
|
readFile(trackFile);
|
||||||
|
findFinish();
|
||||||
|
addCars();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method reads the File and saves it to the track ArrayList Line by Line
|
||||||
|
*
|
||||||
|
* @param trackFile the File where the track has been documented
|
||||||
|
* @throws FileNotFoundException if the FilePath is invalid.
|
||||||
|
*/
|
||||||
|
private void readFile(File trackFile) throws FileNotFoundException {
|
||||||
|
Scanner scanner = new Scanner(new FileInputStream(trackFile),"UTF-8");
|
||||||
|
while (scanner.hasNextLine()) {
|
||||||
|
track.add(scanner.nextLine());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void addCars() throws InvalidTrackFormatException {
|
||||||
|
ConfigSpecification.SpaceType[] spaceTypes = ConfigSpecification.SpaceType.values();
|
||||||
|
List<Character> allSpaceTypesAsChar = new ArrayList<>();
|
||||||
|
List<Character> usedSymbolForCar = new ArrayList<>();
|
||||||
|
|
||||||
|
for (ConfigSpecification.SpaceType spaceType : spaceTypes) {
|
||||||
|
allSpaceTypesAsChar.add(spaceType.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int j = 0; j < track.size(); j++) {
|
||||||
|
String line = track.get(j);
|
||||||
|
for (int i = 0; i < line.length(); i++) {
|
||||||
|
char possibleCarChar = line.charAt(i);
|
||||||
|
if (!allSpaceTypesAsChar.contains(possibleCarChar)) {
|
||||||
|
if (usedSymbolForCar.contains(possibleCarChar)) {
|
||||||
|
throw new InvalidTrackFormatException();
|
||||||
|
}
|
||||||
|
usedSymbolForCar.add(possibleCarChar);
|
||||||
|
cars.add(new Car(possibleCarChar, new PositionVector(i, j)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findFinish() throws InvalidTrackFormatException {
|
||||||
|
for (int i = 0; i < track.size(); i++) {
|
||||||
|
String line = track.get(i);
|
||||||
|
for (int j = 0; j < line.length(); j++) {
|
||||||
|
if (line.charAt(j) == ConfigSpecification.SpaceType.FINISH_LEFT.getValue() ||
|
||||||
|
line.charAt(j) == ConfigSpecification.SpaceType.FINISH_RIGHT.getValue() ||
|
||||||
|
line.charAt(j) == ConfigSpecification.SpaceType.FINISH_DOWN.getValue() ||
|
||||||
|
line.charAt(j) == ConfigSpecification.SpaceType.FINISH_UP.getValue()) {
|
||||||
|
finishLine.add(new PositionVector(j, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (finishLine.size() == 0) {
|
||||||
|
throw new InvalidTrackFormatException();
|
||||||
|
}
|
||||||
|
finishTyp = getSpaceType(finishLine.get(0));
|
||||||
|
for (PositionVector positionVector : finishLine) {
|
||||||
|
if (getSpaceType(positionVector) != finishTyp) {
|
||||||
|
throw new InvalidTrackFormatException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PositionVector findChar(char symbol) {
|
||||||
|
PositionVector vector = null;
|
||||||
|
for (int i = 0; i < track.size(); i++) {
|
||||||
|
String line = track.get(i);
|
||||||
|
for (int j = 0; j < line.length(); j++) {
|
||||||
|
if (line.charAt(j) == symbol) {
|
||||||
|
vector = new PositionVector(j, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawCharOnTrackIndicator(PositionVector positionVector, char symbol) {
|
||||||
|
String line = track.get(positionVector.getY());
|
||||||
|
line = line.substring(0, positionVector.getX()) + symbol + line.substring(positionVector.getX() + 1);
|
||||||
|
track.remove(positionVector.getY());
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return all Cars
|
||||||
|
*/
|
||||||
|
public List<Car> getCars() {
|
||||||
|
return cars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return finishLine
|
||||||
|
*/
|
||||||
|
public List<PositionVector> getFinishLine() {
|
||||||
|
return finishLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the track
|
||||||
|
*/
|
||||||
|
public List<String> getTrack() {
|
||||||
|
return track;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Method will update the Car on the track
|
||||||
|
* and will make the Car move to the next position
|
||||||
|
*
|
||||||
|
* @param carIndex representing the current Car
|
||||||
|
*/
|
||||||
|
public void moveCar(int carIndex) {
|
||||||
|
makeCarMoveInTrack(carIndex);
|
||||||
|
//Change position of car
|
||||||
|
getCar(carIndex).move();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class does change the Position of the car only in the track.
|
||||||
|
*
|
||||||
|
* @param carIndex of the current car
|
||||||
|
*/
|
||||||
|
private void makeCarMoveInTrack(int carIndex) {
|
||||||
|
PositionVector carPositionVector = findChar(getCarId(carIndex));
|
||||||
|
//Removes the Car at Current Pos
|
||||||
|
drawCharOnTrackIndicator(carPositionVector, ConfigSpecification.SpaceType.TRACK.getValue());
|
||||||
|
|
||||||
|
//Redraw finishline if Car was on finish-line Position
|
||||||
|
for(PositionVector finishLinePositionVector : finishLine){
|
||||||
|
if(finishLinePositionVector.equals(carPositionVector)){
|
||||||
|
drawCharOnTrackIndicator(carPositionVector, finishTyp.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Adds Car at new Position
|
||||||
|
carPositionVector = cars.get(carIndex).nextPosition();
|
||||||
|
drawCharOnTrackIndicator(carPositionVector, cars.get(carIndex).getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Method will check if the Car could crash at the specific position
|
||||||
|
*
|
||||||
|
* @param positionVector the position to check if the car could crash
|
||||||
|
* @return true if car would crash. Else false.
|
||||||
|
*/
|
||||||
|
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());
|
||||||
|
if (getCarId(carIndex) == charAtPosition) return false;
|
||||||
|
return !(charAtPosition == ConfigSpecification.SpaceType.TRACK.value ||
|
||||||
|
charAtPosition == ConfigSpecification.SpaceType.FINISH_RIGHT.value ||
|
||||||
|
charAtPosition == ConfigSpecification.SpaceType.FINISH_LEFT.value ||
|
||||||
|
charAtPosition == ConfigSpecification.SpaceType.FINISH_UP.value ||
|
||||||
|
charAtPosition == ConfigSpecification.SpaceType.FINISH_DOWN.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Method will make the Car Crash. In Track and in the Car Object
|
||||||
|
*
|
||||||
|
* @param carIndex representing current Car
|
||||||
|
* @param crashPositionVector where the Crash did happen
|
||||||
|
*/
|
||||||
|
public void carDoesCrash(int carIndex, PositionVector crashPositionVector) throws PositionVectorNotValid{
|
||||||
|
isPositionVectorOnTrack(crashPositionVector); //TODO: remove this line? and Method?
|
||||||
|
PositionVector currentCarPosition = getCarPos(carIndex);
|
||||||
|
drawCharOnTrackIndicator(new PositionVector(currentCarPosition.getX(), currentCarPosition.getY()), ConfigSpecification.SpaceType.TRACK.getValue());
|
||||||
|
Car car = cars.get(carIndex);
|
||||||
|
car.crash();
|
||||||
|
car.setPosition(crashPositionVector);
|
||||||
|
drawCharOnTrackIndicator(new PositionVector(crashPositionVector.getX(), crashPositionVector.getY()), CRASH_INDICATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,8 +266,16 @@ public class Track implements TrackSpecification {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Config.SpaceType getSpaceType(PositionVector position) {
|
public Config.SpaceType getSpaceType(PositionVector position) {
|
||||||
// TODO: implementation
|
//isPositionVectorOnTrack(position); Should be used but we are not allowed to change method head. We don't use function anyway
|
||||||
throw new UnsupportedOperationException();
|
char charAtPosition = track.get(position.getY()).charAt(position.getX());
|
||||||
|
ConfigSpecification.SpaceType[] spaceTypes = ConfigSpecification.SpaceType.values();
|
||||||
|
for (ConfigSpecification.SpaceType spaceType : spaceTypes) {
|
||||||
|
if (spaceType.getValue() == charAtPosition) {
|
||||||
|
return spaceType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,8 +285,7 @@ public class Track implements TrackSpecification {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int getCarCount() {
|
public int getCarCount() {
|
||||||
// TODO: implementation
|
return cars.size();
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,8 +296,7 @@ public class Track implements TrackSpecification {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Car getCar(int carIndex) {
|
public Car getCar(int carIndex) {
|
||||||
// TODO: implementation
|
return cars.get(carIndex);
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,20 +307,19 @@ public class Track implements TrackSpecification {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public char getCarId(int carIndex) {
|
public char getCarId(int carIndex) {
|
||||||
// TODO: implementation
|
return cars.get(carIndex).getID();
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the position of the specified car.
|
* Get the position of the specified car.
|
||||||
|
* Returns Null if carIndex not valid
|
||||||
*
|
*
|
||||||
* @param carIndex The zero-based carIndex number
|
* @param carIndex The zero-based carIndex number
|
||||||
* @return A PositionVector containing the car's current position
|
* @return A PositionVector containing the car's current position
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public PositionVector getCarPos(int carIndex) {
|
public PositionVector getCarPos(int carIndex) {
|
||||||
// TODO: implementation
|
return findChar(cars.get(carIndex).getID());
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,8 +330,7 @@ public class Track implements TrackSpecification {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public PositionVector getCarVelocity(int carIndex) {
|
public PositionVector getCarVelocity(int carIndex) {
|
||||||
// TODO: implementation
|
return cars.get(carIndex).getVelocity();
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -152,8 +344,74 @@ public class Track implements TrackSpecification {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public char getCharAtPosition(int y, int x, Config.SpaceType currentSpace) {
|
public char getCharAtPosition(int y, int x, Config.SpaceType currentSpace) {
|
||||||
// TODO: implementation
|
char charAtPos = track.get(y).charAt(x);
|
||||||
throw new UnsupportedOperationException();
|
PositionVector positionVector = new PositionVector(x, y);
|
||||||
|
for (Car car : cars) {
|
||||||
|
if (charAtPos == car.getID()) {
|
||||||
|
return charAtPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (positionVector.equals(findChar(CRASH_INDICATOR))) return CRASH_INDICATOR;
|
||||||
|
return currentSpace.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -163,7 +421,8 @@ public class Track implements TrackSpecification {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
// TODO: implementation
|
StringBuilder str = new StringBuilder();
|
||||||
throw new UnsupportedOperationException();
|
for (String line : track) str.append(line).append("\n");
|
||||||
|
return str.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,14 @@ public class UserInterface {
|
|||||||
textTerminal.println(welcomeText + "\n");
|
textTerminal.println(welcomeText + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the given Text in textTerminal
|
||||||
|
* @param text The Text which should be printed.
|
||||||
|
*/
|
||||||
|
public void printInformation(String text) {
|
||||||
|
textTerminal.println(text);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 befor the options are printed. Example: "Select Track file:"
|
||||||
@@ -29,7 +37,7 @@ public class UserInterface {
|
|||||||
* @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 + ":\n");
|
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));
|
||||||
}
|
}
|
||||||
@@ -44,7 +52,7 @@ public class UserInterface {
|
|||||||
*/
|
*/
|
||||||
public PositionVector.Direction selectDirection(int playingCarIndex, char playingCarID) {
|
public PositionVector.Direction selectDirection(int playingCarIndex, char playingCarID) {
|
||||||
PositionVector.Direction direction = null;
|
PositionVector.Direction direction = null;
|
||||||
textTerminal.println("Playing Car " + playingCarIndex + ": " + playingCarIndex);
|
textTerminal.println("Playing Car " + playingCarIndex + ": " + playingCarID);
|
||||||
textTerminal.println("Directions are based on the number pad:");
|
textTerminal.println("Directions are based on the number pad:");
|
||||||
textTerminal.println("7 8 9 7=up-left, 8=up, 9=up-right");
|
textTerminal.println("7 8 9 7=up-left, 8=up, 9=up-right");
|
||||||
textTerminal.println("4 5 6 4=left, 5=no acceleration, 6=right");
|
textTerminal.println("4 5 6 4=left, 5=no acceleration, 6=right");
|
||||||
@@ -89,6 +97,15 @@ public class UserInterface {
|
|||||||
textTerminal.println(track.toString());
|
textTerminal.println(track.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to dispose the Textterminal
|
||||||
|
* @param text OUtput Text
|
||||||
|
*/
|
||||||
|
public void quit(String text){
|
||||||
|
textIO.newStringInputReader().withMinLength(0).read(text);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package ch.zhaw.pm2.racetrack.strategy;
|
package ch.zhaw.pm2.racetrack.strategy;
|
||||||
|
|
||||||
|
import ch.zhaw.pm2.racetrack.PositionVector;
|
||||||
|
|
||||||
import static ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
import static ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,7 +11,6 @@ public class DoNotMoveStrategy implements MoveStrategy {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Direction nextMove() {
|
public Direction nextMove() {
|
||||||
// TODO: implementation
|
return PositionVector.Direction.NONE;
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,44 @@ package ch.zhaw.pm2.racetrack.strategy;
|
|||||||
|
|
||||||
import ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
import ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
public class MoveListStrategy implements MoveStrategy {
|
public class MoveListStrategy implements MoveStrategy {
|
||||||
|
|
||||||
|
private List<Direction> moveList;
|
||||||
|
private int pointer;
|
||||||
|
|
||||||
|
public MoveListStrategy(String path) throws FileNotFoundException{
|
||||||
|
moveList = new ArrayList<>();
|
||||||
|
pointer = -1;
|
||||||
|
readFile(new File(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readFile(File trackFile) throws FileNotFoundException {
|
||||||
|
Scanner scanner = new Scanner(new FileInputStream(trackFile), "UTF-8");
|
||||||
|
Direction[] directions = Direction.values();
|
||||||
|
while (scanner.hasNextLine()) {
|
||||||
|
String line = scanner.nextLine();
|
||||||
|
for (Direction direction : directions) {
|
||||||
|
if (direction.toString().equals(line)) {
|
||||||
|
moveList.add(direction);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Direction nextMove() {
|
public Direction nextMove() {
|
||||||
// TODO: implementation
|
pointer += 1;
|
||||||
throw new UnsupportedOperationException();
|
if (pointer < moveList.size()) {
|
||||||
|
return moveList.get(pointer);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,126 @@
|
|||||||
package ch.zhaw.pm2.racetrack.strategy;
|
package ch.zhaw.pm2.racetrack.strategy;
|
||||||
|
|
||||||
|
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.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The PathFollowerMoveStrategy class determines the next move based on a file containing points on a path.
|
* The PathFollowerMoveStrategy class determines the next move based on a file containing points on a path.
|
||||||
*/
|
*/
|
||||||
public class PathFollowerMoveStrategy implements MoveStrategy {
|
public class PathFollowerMoveStrategy implements MoveStrategy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current Position of the car.
|
||||||
|
*/
|
||||||
|
private PositionVector currentPosition;
|
||||||
|
/**
|
||||||
|
* The current Velocity of the car.
|
||||||
|
*/
|
||||||
|
private PositionVector currentVelocity;
|
||||||
|
/**
|
||||||
|
* List of all points on the path.
|
||||||
|
*/
|
||||||
|
private ArrayList<PositionVector> pointList;
|
||||||
|
/**
|
||||||
|
* The index of the next point on the path.
|
||||||
|
*/
|
||||||
|
private int pointer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor to create a new PathFollowerMoveStrategy for a car.
|
||||||
|
* @param path The location where the file is saved
|
||||||
|
* @param startPosition The start position of the car
|
||||||
|
* @throws FileNotFoundException If the file with the given path does not exist.
|
||||||
|
*/
|
||||||
|
public PathFollowerMoveStrategy(String path, PositionVector startPosition) throws FileNotFoundException {
|
||||||
|
pointList = new ArrayList<>();
|
||||||
|
pointer = 0;
|
||||||
|
readFile(new File(path));
|
||||||
|
currentPosition = startPosition;
|
||||||
|
currentVelocity = new PositionVector(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to read the given File and add the points to the pointList
|
||||||
|
* @param trackFile the File Object which should be read
|
||||||
|
* @throws FileNotFoundException If the file with the given path does not exist.
|
||||||
|
*/
|
||||||
|
public void readFile(File trackFile) throws FileNotFoundException {
|
||||||
|
Scanner scanner = new Scanner(new FileInputStream(trackFile), "UTF-8");
|
||||||
|
while (scanner.hasNextLine()) {
|
||||||
|
String line = scanner.nextLine();
|
||||||
|
String[] coordinates = line.split("(\\(X:|, Y:|\\))");
|
||||||
|
pointList.add(new PositionVector(Integer.parseInt(coordinates[1]), Integer.parseInt(coordinates[2])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Direction nextMove() {
|
public Direction nextMove() {
|
||||||
// TODO: implementation
|
// if no more points in the list --> return null
|
||||||
throw new UnsupportedOperationException();
|
if (pointer >= pointList.size()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// increase pointer variable if the next point is reached.
|
||||||
|
if (pointList.get(pointer).equals(currentPosition)) {
|
||||||
|
pointer ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate Vector from current Position to next Point
|
||||||
|
PositionVector movementVector = new PositionVector(pointList.get(pointer).getX() - currentPosition.getX(), pointList.get(pointer).getY() - currentPosition.getY());
|
||||||
|
|
||||||
|
// select acceleration for X
|
||||||
|
int accelerationX;
|
||||||
|
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())){ //reduce velocity
|
||||||
|
accelerationX = -1;
|
||||||
|
} 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())) { //reduce velocity
|
||||||
|
accelerationX = 1;
|
||||||
|
}
|
||||||
|
else { //no acceleration
|
||||||
|
accelerationX = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// select acceleration for Y
|
||||||
|
int accelerationY;
|
||||||
|
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())){ //reduce velocity
|
||||||
|
accelerationY = -1;
|
||||||
|
} 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())) { //reduce velocity
|
||||||
|
accelerationY = 1;
|
||||||
|
}
|
||||||
|
else { //no acceleration
|
||||||
|
accelerationY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//update current Velocity and current Position with the selected acceleration
|
||||||
|
currentVelocity = new PositionVector(currentVelocity.getX() + accelerationX, currentVelocity.getY() + accelerationY);
|
||||||
|
currentPosition = new PositionVector(currentPosition.getX() + currentVelocity.getX(), currentPosition.getY() + currentVelocity.getY());
|
||||||
|
|
||||||
|
//Find Direction for acceleration
|
||||||
|
PositionVector acceleration = new PositionVector(accelerationX, accelerationY);
|
||||||
|
Direction[] directions = Direction.values();
|
||||||
|
for (Direction direction : directions) {
|
||||||
|
if (direction.vector.equals(acceleration)) {
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,24 @@
|
|||||||
package ch.zhaw.pm2.racetrack.strategy;
|
package ch.zhaw.pm2.racetrack.strategy;
|
||||||
|
|
||||||
import ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
import ch.zhaw.pm2.racetrack.PositionVector.Direction;
|
||||||
|
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 int carIndex;
|
||||||
|
private char carID;
|
||||||
|
|
||||||
|
public UserMoveStrategy(UserInterface userInterface, int carIndex, char carID) {
|
||||||
|
this.userInterface = userInterface;
|
||||||
|
this.carIndex = carIndex;
|
||||||
|
this.carID = carID;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Direction nextMove() {
|
public Direction nextMove() {
|
||||||
// TODO: implementation
|
return userInterface.selectDirection(carIndex, carID);
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
###############################################################
|
||||||
|
################# #############
|
||||||
|
############### ###########
|
||||||
|
############### #########
|
||||||
|
############### ################## #########
|
||||||
|
############### #################### #########
|
||||||
|
############## ##################### #########
|
||||||
|
############ ###################### ##########
|
||||||
|
######### ###################### ############
|
||||||
|
######### ###################### ##############
|
||||||
|
######### ##################### ################
|
||||||
|
######### ################# ##################
|
||||||
|
######### ################ ##################
|
||||||
|
########## ################## ###############
|
||||||
|
########### #################### #############
|
||||||
|
########### ####################### ##########
|
||||||
|
########## ########################## #########
|
||||||
|
######### ############################ ########
|
||||||
|
######## ############################# ########
|
||||||
|
####### ############################## ########
|
||||||
|
###### ############################# ########
|
||||||
|
###### ############################ #########
|
||||||
|
###### > a ###########
|
||||||
|
###### > a ##############
|
||||||
|
######## > b #################
|
||||||
|
###############################################################
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
|
||||||
|
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.FileNotFoundException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for Class Car
|
||||||
|
*/
|
||||||
|
class CarTest {
|
||||||
|
|
||||||
|
Car car;
|
||||||
|
|
||||||
|
// Default coordinates for tests
|
||||||
|
int DEFAULT_X = 10;
|
||||||
|
int DEFAULT_Y = 10;
|
||||||
|
char DEFAULT_ID = 'f';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 throwed and position keeps 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
|
||||||
|
List<PositionVector.Direction> directions = Arrays.asList(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 acutal 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(".\\moves\\challenge-car-a.txt");
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
Assertions.fail();
|
||||||
|
}
|
||||||
|
car.setMoveStrategy(moveStrategy);
|
||||||
|
assertEquals(moveStrategy, car.getMoveStrategy());
|
||||||
|
|
||||||
|
try {
|
||||||
|
moveStrategy = new PathFollowerMoveStrategy(".\\follower\\challenge_points.txt", new PositionVector(0, 0));
|
||||||
|
} catch (FileNotFoundException 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for get WinPoints
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void getWinPoints() {
|
||||||
|
assertEquals(0,car.getWinPoints());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for increase WinPoints
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void increaseWinPoints() {
|
||||||
|
car.increaseWinPoints();
|
||||||
|
assertEquals(1,car.getWinPoints());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for deduct WinPoints
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void deductWinPoints() {
|
||||||
|
car.deductWinPoints();
|
||||||
|
assertEquals(-1,car.getWinPoints());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,233 @@
|
|||||||
|
package ch.zhaw.pm2.racetrack;
|
||||||
|
|
||||||
|
import ch.zhaw.pm2.racetrack.strategy.UserMoveStrategy;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
import static ch.zhaw.pm2.racetrack.Game.NO_WINNER;
|
||||||
|
import static ch.zhaw.pm2.racetrack.PositionVector.Direction.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for Class Game
|
||||||
|
*/
|
||||||
|
class GameTest {
|
||||||
|
private UserInterface userInterface;
|
||||||
|
private Game game;
|
||||||
|
private Track track;
|
||||||
|
|
||||||
|
private String TRACK_FILE_PATH = ".\\tracks\\challenge.txt";
|
||||||
|
private int CAR_INDEX_ONE = 0;
|
||||||
|
private int CAR_INDEX_TWO = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This nested Class tests if the game gets initiatet correctly
|
||||||
|
*/
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Test correct Setup")
|
||||||
|
class Setup {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
userInterface = new UserInterface("Test");
|
||||||
|
game = new Game(userInterface);
|
||||||
|
track = game.selectTrack(new File(TRACK_FILE_PATH));
|
||||||
|
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)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getCurrentCarIndex() {
|
||||||
|
Assertions.assertEquals(CAR_INDEX_ONE, game.getCurrentCarIndex());
|
||||||
|
game.switchToNextActiveCar();
|
||||||
|
Assertions.assertEquals(CAR_INDEX_TWO, game.getCurrentCarIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getCarId() {
|
||||||
|
Assertions.assertEquals('a', game.getCarId(0));
|
||||||
|
Assertions.assertEquals('b', game.getCarId(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getCarPosition() {
|
||||||
|
Assertions.assertEquals(new PositionVector(24, 22), game.getCarPosition(0));
|
||||||
|
Assertions.assertEquals(new PositionVector(24, 24), game.getCarPosition(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getCarVelocity() {
|
||||||
|
Assertions.assertEquals(new PositionVector(0, 0), game.getCarVelocity(0));
|
||||||
|
Assertions.assertEquals(new PositionVector(0, 0), game.getCarVelocity(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getWinner() {
|
||||||
|
Assertions.assertEquals(NO_WINNER, game.getWinner());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void onlyOneCarLeft() {
|
||||||
|
Assertions.assertFalse(game.onlyOneCarLeft());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void carsMoving() {
|
||||||
|
Assertions.assertTrue(game.carsMoving());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This nested Class makes basic manipulation after Game init.
|
||||||
|
*/
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Basic manipulation")
|
||||||
|
class Manipulation {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
userInterface = new UserInterface("Test");
|
||||||
|
game = new Game(userInterface);
|
||||||
|
track = game.selectTrack(new File(TRACK_FILE_PATH));
|
||||||
|
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)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void carTurnCorrect() {
|
||||||
|
try {
|
||||||
|
game.doCarTurn(RIGHT);
|
||||||
|
Assertions.assertEquals(new PositionVector(1, 0), game.getCarVelocity(0));
|
||||||
|
} catch (PositionVectorNotValid positionVectorNotValid) {
|
||||||
|
positionVectorNotValid.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void carCrash() {
|
||||||
|
try {
|
||||||
|
game.doCarTurn(PositionVector.Direction.UP);
|
||||||
|
Assertions.assertTrue(game.onlyOneCarLeft());
|
||||||
|
} catch (PositionVectorNotValid positionVectorNotValid) {
|
||||||
|
positionVectorNotValid.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This nested Class tests a Playtrough. And implements a UserInterface interagtion to pretend a real player
|
||||||
|
*/
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Playtrough")
|
||||||
|
class Play {
|
||||||
|
private Game game;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void winner() {
|
||||||
|
game = new Game(new interFace("Test",new Integer[]{0,2,1},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}));
|
||||||
|
try {
|
||||||
|
game.initPhase();
|
||||||
|
Assertions.assertEquals("a",game.gamePhase());
|
||||||
|
} catch (InvalidTrackFormatException | PositionVectorNotValid e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void crashA() {
|
||||||
|
game = new Game(new interFace("Test",new Integer[]{0,2,2},new PositionVector.Direction[]{UP}));
|
||||||
|
try {
|
||||||
|
game.initPhase();
|
||||||
|
Assertions.assertEquals("b",game.gamePhase());
|
||||||
|
} catch (InvalidTrackFormatException | PositionVectorNotValid e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class interFace extends UserInterface {
|
||||||
|
|
||||||
|
private final PositionVector.Direction[] directions;
|
||||||
|
private final Integer[] instructions;
|
||||||
|
private int pointerDir,pointerInstruction;
|
||||||
|
|
||||||
|
|
||||||
|
public interFace(String welcometxt, Integer[] instructions, PositionVector.Direction[] directions) {
|
||||||
|
super(welcometxt);
|
||||||
|
pointerDir = -1;
|
||||||
|
pointerInstruction = -1;
|
||||||
|
this.instructions = instructions;
|
||||||
|
this.directions = directions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int selectOption(String text, List<String> options) {
|
||||||
|
pointerInstruction++;
|
||||||
|
return instructions[pointerInstruction];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printInformation(String text) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printTrack(Track track) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void quit(String text) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public PositionVector.Direction selectDirection(int playingCarIndex, char playingCarID) {
|
||||||
|
pointerDir += 1;
|
||||||
|
if(pointerDir < directions.length) {
|
||||||
|
return directions[pointerDir];
|
||||||
|
}
|
||||||
|
return NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package ch.zhaw.pm2.racetrack;
|
||||||
|
|
||||||
|
import ch.zhaw.pm2.racetrack.strategy.MoveListStrategy;
|
||||||
|
import ch.zhaw.pm2.racetrack.strategy.MoveStrategy;
|
||||||
|
import org.junit.jupiter.api.*;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
|
||||||
|
public class MoveStrategyTest {
|
||||||
|
|
||||||
|
private MoveStrategy moveList;
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("MoveListStrategy")
|
||||||
|
class MoveList {
|
||||||
|
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
try {
|
||||||
|
moveList = new MoveListStrategy(".\\moves\\challenge-car-a.txt");
|
||||||
|
}catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void checkMove() {
|
||||||
|
Assertions.assertEquals(PositionVector.Direction.RIGHT,moveList.nextMove());
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
moveList.nextMove();
|
||||||
|
}
|
||||||
|
Assertions.assertEquals(PositionVector.Direction.NONE,moveList.nextMove());
|
||||||
|
for (int i = 0; i < 40; i++) {
|
||||||
|
moveList.nextMove();
|
||||||
|
}
|
||||||
|
Assertions.assertNull(moveList.nextMove());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
package ch.zhaw.pm2.racetrack;
|
||||||
|
|
||||||
|
import ch.zhaw.pm2.racetrack.given.ConfigSpecification;
|
||||||
|
import org.junit.jupiter.api.*;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
public class TrackTest {
|
||||||
|
Track trackObj;
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Positiv Test Cases")
|
||||||
|
class positivClass {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
File file = new File(".\\tracks\\challenge.txt");
|
||||||
|
try {
|
||||||
|
trackObj = new Track(file);
|
||||||
|
|
||||||
|
} catch (Exception | PositionVectorNotValid e) {
|
||||||
|
System.err.println("Error in Test compareTrack" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Create correct amount of Car instance")
|
||||||
|
void checkCars() {
|
||||||
|
Assertions.assertEquals(2, trackObj.getCarCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Create Car instance with correct Symbols / Id")
|
||||||
|
void checkCarId() {
|
||||||
|
Assertions.assertEquals('a', trackObj.getCarId(0));
|
||||||
|
Assertions.assertEquals('b', trackObj.getCarId(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Check getSpaceTyp")
|
||||||
|
void getSpaceTyp() {
|
||||||
|
Assertions.assertEquals(ConfigSpecification.SpaceType.FINISH_RIGHT, trackObj.getSpaceType(new PositionVector(22, 24)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Find FinishLine")
|
||||||
|
void findFinish() {
|
||||||
|
List<PositionVector> expected = new ArrayList<>();
|
||||||
|
expected.add(new PositionVector(22, 22));
|
||||||
|
expected.add(new PositionVector(22, 23));
|
||||||
|
expected.add(new PositionVector(22, 24));
|
||||||
|
Assertions.assertEquals(expected, trackObj.getFinishLine());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Converts Trackfile correctly to List<String>")
|
||||||
|
void checkTrack() {
|
||||||
|
Track trackObj;
|
||||||
|
try {
|
||||||
|
trackObj = new Track(new File(".\\tracks\\oval-anticlock-right.txt"));
|
||||||
|
List<String> track = new ArrayList<>();
|
||||||
|
track.add("##################################################");
|
||||||
|
track.add("##################################################");
|
||||||
|
track.add("############## #############");
|
||||||
|
track.add("########## ##########");
|
||||||
|
track.add("####### #######");
|
||||||
|
track.add("###### ################# ######");
|
||||||
|
track.add("##### ################### #####");
|
||||||
|
track.add("##### ################### #####");
|
||||||
|
track.add("###### ################# ######");
|
||||||
|
track.add("####### > a #######");
|
||||||
|
track.add("########## > ##########");
|
||||||
|
track.add("############## > b ##############");
|
||||||
|
track.add("##################################################");
|
||||||
|
track.add("##################################################");
|
||||||
|
Assertions.assertLinesMatch(track, trackObj.getTrack());
|
||||||
|
} catch (FileNotFoundException | InvalidTrackFormatException | PositionVectorNotValid e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Make Car move down on track")
|
||||||
|
void makeCarMoveDown() {
|
||||||
|
PositionVector beforeMove = trackObj.getCarPos(0);
|
||||||
|
trackObj.getCar(0).accelerate(PositionVector.Direction.DOWN);
|
||||||
|
trackObj.moveCar(0);
|
||||||
|
PositionVector afterMove = trackObj.getCarPos(0);
|
||||||
|
Assertions.assertEquals(beforeMove.getY() + 1, afterMove.getY());
|
||||||
|
Assertions.assertEquals(beforeMove.getX(), afterMove.getX());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Make Car move with (0,0) acceleration on track")
|
||||||
|
void makeCarStay() {
|
||||||
|
PositionVector beforeMove = trackObj.getCarPos(0);
|
||||||
|
trackObj.moveCar(0);
|
||||||
|
PositionVector afterMove = trackObj.getCarPos(0);
|
||||||
|
Assertions.assertEquals(beforeMove.getY(), afterMove.getY());
|
||||||
|
Assertions.assertEquals(beforeMove.getX(), afterMove.getX());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Will Car Crash")
|
||||||
|
void willCarCrash() {
|
||||||
|
try {
|
||||||
|
//Car will Crash
|
||||||
|
Assertions.assertTrue(trackObj.willCrashAtPosition(0, new PositionVector(25, 21)));
|
||||||
|
//Car will not Crash and is on track
|
||||||
|
Assertions.assertFalse(trackObj.willCrashAtPosition(0, new PositionVector(7, 22)));
|
||||||
|
//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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Make Car Crash")
|
||||||
|
void makeCarCrash() {
|
||||||
|
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.assertTrue(trackObj.getCar(0).isCrashed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Negative TestCase")
|
||||||
|
class negativeClass {
|
||||||
|
File file;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
file = new File(".\\tracks\\challenge.txt");
|
||||||
|
try {
|
||||||
|
trackObj = new Track(file);
|
||||||
|
|
||||||
|
} catch (Exception | PositionVectorNotValid e) {
|
||||||
|
System.err.println("Error in Test compareTrack" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Throw error if File not found")
|
||||||
|
void canReadFile() {
|
||||||
|
file = new File(".\\tracks\\NotExisting.txt");
|
||||||
|
Assertions.assertThrows(FileNotFoundException.class, () -> new Track(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Throw error if File is invalid")
|
||||||
|
void invalidTrackFile() {
|
||||||
|
File testfile = new File(".\\src\\test\\InvalidTracks\\sameCar.txt");
|
||||||
|
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)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1 +0,0 @@
|
|||||||
challenge_points.txt
|
|
||||||
Reference in New Issue
Block a user