LAB 6 - TUESDAY

This week, you are expected to implement a game named as “Crazy Race”. In order to simplify the process, the question is divided into 3 parts.

Part 1 – Car class

In this game, what races crazily is a car. So let’s define the Car class. It has some properties which are not accessible directly such as:

  • modelName: Model of the car.(1 pt)
  • enginePower: Power of the engine. It must be between 1 and 1000 inclusively.(1 pt)
  • fuelLevel: Shows the level of your fuel tank. It must be between 0 and 1 inclusively.(1 pt)
  • color: Color of the car. It must be WHITE, BLACK or RED.(1 pt)
  • velocity: Current speed of the car. It must be between 0 and maxVelocity inclusively.(1 pt)
  • maxVelocity: Maximum speed of the car. It must be between 10 and 120 inclusively.(1 pt)

Your Car class must have a constructor which initializes all of the above properties. However only modelName, enginePower, color, maxVelocity will be taken as the parameters of constructor. Initial velocity should be 0 and the fuel tank should be full.(3 pt)

Also your class must implement the following methods:

getModelName()(1 pt)

getEnginePower()(1 pt)

getFuelLevel()(1 pt)

getColor()(1 pt)

getVelocity()(1 pt)

getMaxVelocity()(1 pt)

setModelName(modelName)(1 pt)

setEnginePower(enginePower)(2 pt)

For values of enginePower smaller than 1, enginePower must be set to default value 1. Similarly for values of enginePower greater than 1000, enginePower must be set to default value 1000. Otherwise use the value of enginePower.

setFuelLevel(fuelLevel)(2 pt)

For values of fuelLevel smaller than 0, fuelLevel must be set to default value 0. Similarly for values of fuelLevel greater than 1, fuelLevel must be set to default value 1. Otherwise use the value of fuelLevel.

setColor(color)(2 pt)

For values of color other than WHITE, BLACK or RED, color must be set to default value WHITE. Otherwise use the value of color.

setVelocity(velocity)(2 pt)

For values of velocity smaller than 0 or greater than maxVelocity, velocity must be set to default value (maxVelocity / 2). Otherwise use the value of velocity.

setMaxVelocity(maxVelocity)(2 pt)

For values of maxVelocity smaller than 10 or greater than 120, maxVelocity must be set to default value 50. Otherwise use the value of maxVelocity.

fillFuelTank()(1 pt)

Fills the tank to the maximum level.

isFuelTankEmpty()(1 pt)

Checks if fuel in the tank is depleted.

toString(): For example(2 pt)

RED BMW

------

Engine Power: 700, Max Velocity: 50

compareTo(otherCar)(2 pt)

Returns a comparison code according to enginePower of the cars.

moveForward(otherCar, currentPosition, otherCarsCurrentPosition)(16 pt)

If the opponent car is in front of our car, then we must speed up. If we know that opponent has a stronger engine, then increase in our speed will be a random value between 0 and (maxVelocity / 5). If we know that our car is stronger, then increase will be between 0 and (maxVelocity / 10). Then update velocity with this increase.

Of course moving forward has some cost. You must update the fuel level. Use the following formula:

new_fuel_level = current_fuel_level x (1-(velocity / maxVelocity))

This method must return the new position of our car. Moving forward takes unit time and distance = velocity x time. Here time = 1.

Part 2 – Race Class

In this game, two cars are in a race. This class represents a particular race. Properties of the class are:

  • car1: First car of the race(1 pt)
  • car2: Second car of the race(1 pt)
  • length: Length of the road. It must be between 500 and 10000 inclusively.(1 pt)
  • car1Position: Current position of car1 on the road. It must be between 0 and length inclusively.(1 pt)
  • car2Position: Current position of car2 on the road. It must be between 0 and length inclusively.(1 pt)

Your Race class must have a constructor which initializes all of the above properties (3 pt).

Parameters of the constructor are car1, car2 and length. car1Position and car2Position must be set to 0 initially.

Also your class must implement the following methods:

getCar1Position()(1 pt)

getCar2Position()(1 pt)

setCar1Position(car1Position)(2 pt)

For values of car1Position smaller than 0 or greater than length, car1Position must be set to default value 0. Otherwise use the value of car1Position.

setCar2Position(car2Position)(2 pt)

For values of car2Position smaller than 0 or greater than length, car2Position must be set to default value 0. Otherwise use the value of car2Position.

setLength(length)(2 pt)

For values of length smaller than 500 or greater than 10000, length must be set to default value 5000. Otherwise use the value of length.

race()(16 pt)

Race lasts until one of the cars reaches the end of the road. During the race before moving forward, the fuel tank should be checked. If it is empty, the corresponding car should wait for one turn and fill the tank to maximum. If there is some fuel, then car can go forward and the corresponding car position should be updated. These must be repeated for each car consecutively until race finishes. The one who reaches the end first must be returned by this method.

Part 3 – TestRace Class

This is the driver class of the game. You will have 2 cars. You should read all instances of the cars from keyboard.(3 pt)

<Model_Name>,<Engine_Power>,<Color>,<MAX_VELOCITY>

Sample input will be:

BMW,1000,RED,110

You can assume that input is error free and there is no whitespace character in the inputs. Use StringTokenizer to parse the inputs and use the appropriate tokens as the Car properties.

After creating the cars successfully(1 pt), you will perform 10 races. First race length is 1000, second is 2000, third is 3000 etc. Each race will start at position 0 and both cars will have full fuel tanks. Prepare a simple scoreboard showing the race results (which one wins how many times).(16 pt)

SAMPLE RUN

Car 1 specification: BMW,700,WHITE,100

Car 2 specification: Renault,550,RED,102

WHITE BMW

------

Engine Power: 700, Max Velocity: 100

RED Renault

------

Engine Power: 550, Max Velocity: 102

Score: 7-3

APPENDIX

To produce random numbers between [a,b] you can do the following:

  • Add “import java.util.Random;” on the top of your class which requires randomness.
  • Add “private static Random rnd = new Random();” statement to the list of class properties.
  • int number = rnd.nextInt(b – a + 1) + a;
  • number is a integer value from the range [a,b] (a and b are included.)

import java.util.Random;

/**

*

*/

/**

* @author Solution for Car.java

*

*/

public class Car

{

/**

* rnd will be used when randomness is required.

*/

private static Random rnd = new Random();

private String modelName;

private int enginePower;

private double fuelLevel;

private String color;

private int velocity;

private int maxVelocity;

public Car(String modelName, int enginePower, String color, int maxVelocity)

{

setModelName(modelName);

setEnginePower(enginePower);

setColor(color);

setMaxVelocity(maxVelocity);

setVelocity(0);

fillFuelTank();

}

public String getModelName() {

return modelName;

}

public void setModelName(String modelName) {

this.modelName = modelName;

}

public int getEnginePower() {

return enginePower;

}

public void setEnginePower(int enginePower) {

if(enginePower > 1000)

this.enginePower = 1000;

else if(enginePower < 1)

this.enginePower = 1;

else

this.enginePower = enginePower;

}

public double getFuelLevel() {

return fuelLevel;

}

public void setFuelLevel(double fuelLevel) {

if(fuelLevel > 1.0)

this.fuelLevel = 1.0;

else if(fuelLevel < 0.0)

this.fuelLevel = 0.0;

else

this.fuelLevel = fuelLevel;

}

public String getColor() {

return color;

}

public void setColor(String color) {

if(!(color.equalsIgnoreCase("WHITE") || color.equalsIgnoreCase("BLACK") || color.equalsIgnoreCase("RED")))

this.color = "WHITE";

else

this.color = color;

}

public int getVelocity() {

return velocity;

}

public void setVelocity(int velocity)

{

if(velocity < 0 || velocity > getMaxVelocity())

this.velocity = getMaxVelocity() / 2;

else

this.velocity = velocity;

}

public int getMaxVelocity() {

return maxVelocity;

}

public void setMaxVelocity(int maxVelocity) {

if(maxVelocity < 10 || maxVelocity > 120 )

this.maxVelocity = 50;

else

this.maxVelocity = maxVelocity;

}

public void fillFuelTank()

{

setFuelLevel(1.0);

}

public boolean isFuelTankEmpty()

{

return this.fuelLevel == 0;

}

public int moveForward(Car otherCar, int currentPosition, int otherCarsCurrentPosition)

{

int increaseInVelocity = 0;

if(otherCarsCurrentPosition >= currentPosition) //If Opponent is in front of us.

{

if(this.compareTo(otherCar) == -1) // If Our car has a weaker engine

{

increaseInVelocity = rnd.nextInt(getMaxVelocity() / 5);

}

else //If Our car has a stronger engine

{

increaseInVelocity = rnd.nextInt(getMaxVelocity() / 10);

}

}

setVelocity(getVelocity() + increaseInVelocity); // increase velocity

setFuelLevel(this.fuelLevel * (1-((double)this.velocity / this.maxVelocity))); // update fuel level

return currentPosition + getVelocity(); // compute and return the new position

}

public String toString()

{

return color+" "+modelName+"\n------\nEngine Power: "+enginePower+", Max Velocity: "+maxVelocity;

}

public int compareTo(Car otherCar)

{

if(enginePower == otherCar.enginePower)

{

return 0;

}

else if(enginePower > otherCar.enginePower)

{

return 1;

}

else

{

return -1;

}

}

}

/**

*

*/

/**

* @author Solution for Race.java

*

*/

public class Race

{

private Car car1;

private Car car2;

private int length;

private int car1Position;

private int car2Position;

public Race(Car car1, Car car2, int length) {

this.car1 = car1;

this.car2 = car2;

this.length = length;

this.car1Position = 0;

this.car2Position = 0;

}

public Car getCar1() {

return car1;

}

public void setCar1(Car car1) {

this.car1 = car1;

}

public Car getCar2() {

return car2;

}

public void setCar2(Car car2) {

this.car2 = car2;

}

public int getLength() {

return length;

}

public void setLength(int length)

{

if(length < 500 || length > 10000)

{

this.length = 5000;

}

else

this.length = length;

}

public int getCar1Position() {

return car1Position;

}

public void setCar1Position(int car1Position) {

if(car1Position < 0 || car1Position > length)

this.car1Position = 0;

else

this.car1Position = car1Position;

}

public int getCar2Position() {

return car2Position;

}

public void setCar2Position(int car2Position) {

if(car2Position < 0 || car2Position > length)

this.car2Position = 0;

else

this.car2Position = car2Position;

}

public Car race()

{

while(car1Position < length & car2Position < length) // While race continues

{

// Has car1 enough fuel?

if(car1.isFuelTankEmpty())

{

car1.fillFuelTank(); // No. Let's fill the tank.

}

else

{

// Yes, it has. So let's move forward and set new position as the return value.

setCar1Position(car1.moveForward(car2, car1Position, car2Position));

}

if(car2.isFuelTankEmpty())

{

car2.fillFuelTank();

}

else

{

setCar2Position(car2.moveForward(car1, car2Position, car1Position));

}

}

if(car1Position > car2Position) // If car1 is in front of car2

return car1;

else

return car2;

}

}

import java.util.Scanner;

import java.util.StringTokenizer;

/**

*

*/

/**

* @author Solution for TestRace.java

*

*/

public class TestRace {

public static void main(String[] args) {

Scanner keyboard = new Scanner(System.in);

String c1;

String c2;

System.out.print("Car 1 specification: ");

c1 = keyboard.nextLine();

System.out.print("Car 2 specification: ");

c2 = keyboard.nextLine();

StringTokenizer tokenizer = new StringTokenizer(c1, ",");

Car car1 = new Car(tokenizer.nextToken(),Integer.parseInt(tokenizer.nextToken()), tokenizer.nextToken(), Integer.parseInt(tokenizer.nextToken()));

System.out.println(car1);

tokenizer = new StringTokenizer(c2, ",");

Car car2 = new Car(tokenizer.nextToken(),Integer.parseInt(tokenizer.nextToken()), tokenizer.nextToken(), Integer.parseInt(tokenizer.nextToken()));

System.out.println(car2);

Race race = new Race(car1, car2, 0);

int count1 = 0, count2 = 0;

Car winner;

for(int i=0; i < 10; i++)

{

// Setup the race

race.setLength(1000*(i+1));

car1.fillFuelTank();

car2.fillFuelTank();

race.setCar1Position(0);

race.setCar2Position(0);

// Who is the winner?

winner = race.race();

if(winner == car1)

count1++;

else

count2++;

}

System.out.println("Score: "+count1+"-"+count2);

}

}