Can you Implement a Singleton Pattern with a State Pattern - java

I have an application that I have been working on for a little while, I understand a little of Java.
The scope of the application is combine multiple design patterns in a way that allows reusability, which code can be edited without having to scroll through hundreds of lines of code.
I have implemented a true Singleton Player class.
I have also implemented a decorator weapon class.
I am not looking to add a state pattern for the player class, an example of this would be AliveState and DeadState. Something simple so I understand the workings of it all.
For the sake of this I will post the full PlayerSingleton class:
public class PlayerSingleton{
private static PlayerSingleton player;
Scanner scanner = new Scanner(System.in);
private String playerName;
private Integer playerHealth;
private Weapon weapon;
private PlayerSingleton(Weapon weapon, String pName, int pHealth) {
this.weapon = weapon;
playerName = pName;
playerHealth = pHealth;
}
public static Weapon chooseWeapon(String choice) {
switch (choice) {
case "MP5":
System.out.println("You have chosen MP5!");
return new MP5Weapon();
case "SNIPER":
System.out.println("You have chosen Sniper!");
return new SniperRifleWeapon();
case "SHOTGUN":
System.out.println("You have chosen Shotgun!");
return new ShotgunWeapon();
default:
System.out.println("No gun by that name found!");
return null;
}
}
public static PlayerSingleton getInstance(String choice, String name, int health) {
System.out.println("Choose Weapon to play the with: ");
Weapon weapon = PlayerSingleton.chooseWeapon(choice);
weapon.getDescription();
if (player == null) {
player = new PlayerSingleton(weapon, name, health);
}
return player;
}
public void getWeaponDamage(Weapon damage) {
System.out.println("Damage of weapon: " + weapon.damage());
}
public void attackState(double damage) {
damage = player.weapon.damage();
}
// #Override
// public void aliveState() {
// if(playerHealth >= 1){
//
// }
// }
// #Override
// public void deadState() {
// if(playerHealth ==0){
// System.out.println("You are dead");
// System.out.println("GameOver");
// }
// }
public void chosenWeapon() {
System.out.println("Player Info: " + playerName + " " + "Has: " + playerHealth + " health");
System.out.println(weapon.getDescription() + ":" + " base damage: " + weapon.damage());
}
public void addBasicAttachment(String attachment) {
switch (attachment) {
case "SIGHT":
weapon = new BasicSight(weapon);
break;
case "SILENCER":
weapon = new BasicSilencer(weapon);
break;
case "STOCK":
weapon = new BasicStock(weapon);
break;
default:
System.out.println("No Attachment found!");
}
}
I've tried to implement this with help of Head first design patterns (State) but using the Singleton Pattern on the player class means that I cannot call the object from another class.
public class DeadState implements PlayerState{
PlayerSingleton player;
public DeadState(PlayerSingleton player){
this.player = player;
}
#Override
public void deadState() {
System.out.println("You are Dead!");
}
#Override
public void aliveState() {
System.out.println("You are Dead!");
}
}
Above is a test on making a DeadState implementing from a PlayerState interface.
Is there any way to do this with separate classes using the state pattern with PlayerSingleton?
Seriously any help would be amazing!
Also if you could explain the answer so I understand better.

First of all about this sentence that you said:
using the Singleton Pattern on the player class means that I cannot call the object from another class.
Actually you can call the object from other classes, as long as you have access to the instance, and that's how state pattern works.
I took your classes and remove some code just for the sake of simplicity and explain better the solution, you can add back the parts of the code I removed if you use this solution:
I used the two states you have in your code, first this is the PlayerState interface, it has two methods, one for taking damage and other for respawning:
public interface PlayerState {
void respawn();
void takeDamage(int damage);
}
Then the implementation of Alive state has only implementation for the takeDamage method, which receives the amount of damage taken:
public class AliveState implements PlayerState {
private PlayerSingleton player;
public AliveState(PlayerSingleton player) {
this.player = player;
this.player.setHealth(PlayerSingleton.MAX_PLAYER_HEALTH);
}
#Override
public void takeDamage(int damage) {
System.out.println(String.format("Suffering %d damage!", damage));
player.setHealth(player.getHealth() - damage);
if (player.getHealth() <= 0) {
player.setLives(player.getLives() - 1);
player.setState(new DeadState(player));
}
}
#Override
public void respawn() {
System.out.println("Nothing to do, player is alive!");
}
}
Same for the implementation of the DeadState, which has only implementation for the respawn method, as long as the player has lives left:
public class DeadState implements PlayerState {
private PlayerSingleton player;
public DeadState(PlayerSingleton player) {
this.player = player;
}
#Override
public void takeDamage(int damage) {
System.out.println("Nothing to do, player is dead!");
}
#Override
public void respawn() {
if (player.getLives() > 0) {
System.out.println("respawning to start location!");
player.setState(new AliveState(player));
} else {
System.out.println("Game Over!");
}
}
}
And finally the PlayerSingleton class, which is assigned the state AliveState when the player is created, the takeDamage and respawn methods call the implementations in the current player's state, and if you noticed, the State implementations have a reference to the player's instance, so they can change the object state.
public class PlayerSingleton {
public static Integer MAX_PLAYER_HEALTH = 500;
public static Integer DEFAULT_PLAYER_LIVES = 2;
private static PlayerSingleton player;
private Integer health = MAX_PLAYER_HEALTH;
private int lives = DEFAULT_PLAYER_LIVES;
private PlayerState playerState;
private PlayerSingleton() {
setState(new AliveState(this));
}
public static PlayerSingleton getInstance() {
if (player == null) {
player = new PlayerSingleton();
}
return player;
}
public void sufferDamage(int damage) {
playerState.takeDamage(damage);
}
public void respawn(String location) {
playerState.respawn();
}
// Getters and Setters
}
I used the following main method to test:
public static void main(String[] args) {
PlayerSingleton playerSingleton = PlayerSingleton.getInstance();
playerSingleton.takeDamage(300);
playerSingleton.respawn();
playerSingleton.takeDamage(300);
playerSingleton.respawn();
playerSingleton.takeDamage(600);
playerSingleton.respawn();
}
And this was the output:
Suffering 300 damage!
Nothing to do, player is alive!
Suffering 300 damage!
Player is dead!
respawning to start location!
Suffering 600 damage!
Player is dead!
Game Over!

Related

Selecting Random Method From Multiple Methods

I am trying to select a random method from the ones created inside the class. Is there a way to create an ArrayList and pass methods to it? I have attempted to do just that but I am getting an error when I try to add the method to the array.
public class Monkey{
private int energy;
String[] food = {"Meat", "Fish", "Bugs", "Grain"};
ArrayList<Activity> monkeyActivity = new ArrayList<>();
public Monkey(int energy) {
this.energy = energy;
}
public int getEnergy() {
System.out.println("Monkey energy level: " + energy);
return energy;
}
public void sound() {
System.out.println("Monkey: Oooo Oooo~!");
energy -= 3;
monkeyActivity.add(sound()); //I get an error message here when trying
//to add the method to the array
}
public void play(){
if (energy >= 8){
System.out.println("Monkey begins to play.");
energy -= 8;
}else {
System.out.println("Monkey does not have enough energy to play");
}
System.out.println("Energy remaining: " + energy);
}
public void eat(){
Random random = new Random();
int index = random.nextInt(food.length);
System.out.println("Monkey beings to eat " + food[index]);
energy += 5;
System.out.println("Energy remaining: " + energy);
}
public void sleep(){
System.out.println("Monkey is sleeping: Zzz...");
energy += 10;
System.out.println("Energy remaining: " + energy);
}
}
This is the separate class I have made for the generic Activity..
public class Activity {
private String sleep;
private String eat;
private String sound;
private String play;
public Activity(String sleep, String eat, String sound, String play) {
this.sleep = sleep;
this.eat = eat;
this.sound = sound;
this.play = play;
}
public String getSleep() {
return sleep;
}
public String getEat() {
return eat;
}
public String getSound() {
return sound;
}
public String getPlay() {
return play;
}
public void setSleep(String sleep) {
this.sleep = sleep;
}
public void setEat(String eat) {
this.eat = eat;
}
public void setSound(String sound) {
this.sound = sound;
}
public void setPlay(String play) {
this.play = play;
}
}
You are mixing up concepts.
technical issues:
return value clash
public void sound() {
// ...
monkeyActivity.add(sound());
The return value of your method sound() is void (which means no return value), but you try to add its (not existing) return value as element to the List. This is what your compiler complains about.
unintended recursion
public void sound() {
System.out.println("Monkey: Oooo Oooo~!");
energy -= 3;
monkeyActivity.add(sound());
In the last line you do a recursive call which means you call exactly the same method this code is in. If that happens unintended it almost ever results in a StackOverflowError.
writing classes without proper analysis
You have a class Activity.
But if you have a closer look this is not a single activity (as the classes name implies) but it is all possible activities.
As a result your collection monkeyActivity cannot hold single activities as elements.
Doing a wild guess I think what you wanted is more like this:
interface Activity{
void do();
}
public class Monkey{
private int energy;
String[] food = {"Meat", "Fish", "Bugs", "Grain"};
List<Activity> monkeyActivity = new ArrayList<>();
// ...
public void sound() {
monkeyActivity.add(new Activity(){
public void do(){
System.out.println("Monkey: Oooo Oooo~!");
energy -= 3;
}
});
}
You may store each method as Runnable, as any "action" is no-arg void method satisfying Runnable functional interface:
List<Runnable> actions = Arrays.asList(this::sound, this::play, this::eat, this::sleep);
to execute random method, just:
Random rnd = new Random();
actions.get(rnd.nextInt(actions.size())).run();

Object Interaction n Java

I'm making a pokemon game for fun and I want to be able to reduce the HP of the two pokemon fighting. What i'm doing is calling a method inside an 'if statement',which is inside of a loop, an have Java call a method from another class to reduce the HP.
Below is the Code as I have it...
import java.util.Scanner;
public class gameTester {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner inputSystem = new Scanner(System.in);
Scanner playerName = inputSystem;
System.out.println("Hello Player please type in the name of your pokemon.");
pokemon playerOne = new pokemon(playerName.nextLine());
pokemon playerTwo = new pokemon();
System.out.println(playerOne.toString());//shows player pokemon
System.out.println(playerTwo.toString());//shows enemy pokemon
System.out.println("Let's Battle! What do you do?");
while (playerOne.getHealthPoints() >= 0 || playerTwo.getHealthPoints() >= 0){
System.out.println("1. Bite 2. Slash 3. Flee");
int userChoice = inputSystem.nextInt();
if (userChoice == 3){
break;
}
else if (userChoice == 1 || userChoice == 2){
//playerTwo.getHealthPoints()
}
}
}
}
Also like I said above i'm calling a method from another class..
public class pokemon {
private String pokemonSpecies;
private String nameOfpokemon;
private int attackDamage;
private int healthPoints;
public pokemon (){
nameOfpokemon = "Enemy";
attackDamage = 1;
healthPoints = 3;
}
public pokemon (String desiredName){
nameOfpokemon = desiredName;
attackDamage = 1;
healthPoints = 3;
}
public String getPokemonSpecies() {
return pokemonSpecies;
}
public void setPokemonSpecies(String pokemonSpecies) {
this.pokemonSpecies = pokemonSpecies;
}
public String getNameOfpokemon() {
return nameOfpokemon;
}
public void setNameOfpokemon(String nameOfpokemon) {
this.nameOfpokemon = nameOfpokemon;
}
public int getAttackDamage() {
return attackDamage;
}
public void setAttackDamage(int attackDamage) {
this.attackDamage = attackDamage;
}
public int getHealthPoints() {
return healthPoints;
}
public void setHealthPoints() {
this.healthPoints = healthPoints;
}
#Override
public String toString(){
return "Name of Pokemon: " + nameOfpokemon + " Attack Damage: " + attackDamage + " Health Points: " + healthPoints;
}
public int enemyDamage(int damage){
setHealthPoints() = getAttackDamage() - getHealthPoints();
}
}
The last bit about public in enemyDamage(...) is where I'm stuck. I don't know if I should send an integer that can reduce the HP. Or is I should use this method to call other methods...
Any advice?
First use can change your setHealthPoints() method to
public void setHealthPoints(int healthPoints) {
this.healthPoints = healthPoints;
}
Here I assume
damage = attack/damage done by opponent's pokemon.
getHealthPoints() = my pokemon's health.
Then enemyDamage() goes in this way.
public void enemyDamage(int damage){
setHealthPoints(getHealthPoints() - damage);
}

How can one instance change some variable of the other instance of the same class

I am Java beginner and I have a question. Let's say we have a class:
class Foo {
public String test;
public void someMethod() { }
}
And we have two instances of this class: bar1 and bar2.
Now how can I make that bar1.someMethod() changes the value of the bar2.test without passing bar2 as parameter to the bar1 (no something like bar1.someMethod(bar2)). To clear out: I am making a game where you can move objects in turns, so I want that after the move object becomes inactive and makes other object active so only one of them can be moved at the time. Thanks.
you should solve this problem different
as you probably will have an other class playground (or whatever) put there a List for your Foos
and
add your Method someMethod() into this Class where you handle the state of the variable test of your class Foo
class playground{
List<Foo> foos = new List<Foo>();
void someMethod(Foo a,Foo b){
a.changeTest("");
b.changeTest("");
}
}
And in the class Foo you do of course the real change of the state
class Foo{
void changeTest(String a){
test = a;
}
}
Short answer: Can't do easily.
Longer:
How should bar1 know which other instance to manipulate? There may be many instances (or only two, I don't know you application).
You could have a (private) field in class Foo which knows the other instance.
Or you could have a class Foos which knows both instances.
Another (ugly) solution would be to have two static fields in Foo however this is discouraged as this will prevent you from every effectively using more than two instances.
I'm not clear on exactly what you mean but I've have a go. I'll explain it to you with two classes, one for your MainProgram and the other for Foo.
public class Foo {
public String test;
private Foo otherPlayer = null;
public void someMethod() {
}
public void setOtherPlayer(Foo otherPlayer) {
this.otherPlayer = otherPlayer;
}
}
I've added another method which does pass another Foo instance as a parameter, but this is the only method that will need it and it's for the purpose of setting a field (where it says private Foo otherPlayer) in your class instance which is accessible from all other methods in this instance.
Also, you'll notice the keyword this. this.variable means a field (a field is inside a class but outside a method) in the same instance as the calling method is in. otherPlayer refers to the parameter in the setOtherPlayer method.
public class MainProgram {
public static void main(String[] args) {
Foo player1 = new Foo();
Foo player2 = new Foo();
player1.setOtherPlayer(player2);
player2.setOtherPlayer(player1);
}
}
Then in your MainProgram create two instances of Foo and then for both players, set the player they are competing against. This should be done before doing anything else with the players.
This is another code for multiple players
import java.util.Random;
public class Dice {
public int roll() {
return new Random().nextInt(6) + 1;
}
}
import java.awt.event.ActionEvent;
public class Display extends JFrame {
public Display(final Game game) {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(null);
JButton btnNextMove = new JButton("Do next move");
btnNextMove.setBounds(12, 12, 129, 25);
getContentPane().add(btnNextMove);
setBounds(0, 0, 162, 77);
btnNextMove.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
game.doNextMove();
}
});
game.start();
}
}
import java.util.ArrayList;
public class Game {
private ArrayList<Player> players = new ArrayList<Player>();
private Player currentPlayer = null;
public void addPlayer(Player p) {
players.add(p);
}
public void start() {
int playerCount = players.size();
for (int i=0; i<playerCount; i++) {
int previousPlayerIndex = i-1;
int nextPlayerIndex = i+1;
// Makes the players loop round at the edges
if (previousPlayerIndex < 0) previousPlayerIndex += playerCount;
if (nextPlayerIndex >= playerCount) nextPlayerIndex -= playerCount;
Player p = players.get(i);
p.setPreviousPlayer(players.get(previousPlayerIndex));
p.setNextPlayer(players.get(nextPlayerIndex));
}
// Sets current player to the first player
setCurrentPlayer(players.get(0));
}
private void setCurrentPlayer(Player p) {
this.currentPlayer = p;
System.out.println();
System.out.println("It's " + p.playerName + "'s turn to make a move.");
}
public void doNextMove() {
Dice dice = new Dice();
int value = dice.roll();
System.out.println(currentPlayer.playerName + " rolled a " + value);
if (value <= 2) skipPlayer();
else if (value <= 4) reverse();
else if (value <= 6) doNormalMove();
}
public void reverse() {
int playerCount = players.size();
for (int i=0; i<playerCount; i++) {
players.get(i).reverseSiblingPlayers();
}
System.out.println("Play is reversed");
setCurrentPlayer(currentPlayer.getNextPlayer());
}
public void doNormalMove() {
System.out.println("Nothing special happens here");
setCurrentPlayer(currentPlayer.getNextPlayer());
}
public void skipPlayer() {
System.out.println(currentPlayer.getNextPlayer().playerName + " misses a turn");
setCurrentPlayer(currentPlayer.getNextPlayer().getNextPlayer());
}
}
public class MainProgram {
public static void main(String[] args) {
Game game = new Game();
game.addPlayer(new Player("Player 1"));
game.addPlayer(new Player("Player 2"));
game.addPlayer(new Player("Player 3"));
game.addPlayer(new Player("Player 4"));
game.addPlayer(new Player("Player 5"));
game.addPlayer(new Player("Player 6"));
Display display = new Display(game);
display.setVisible(true);
}
}
public class Player {
public final String playerName;
private Player previousPlayer = null;
private Player nextPlayer = null;
public Player(String playerName) {
this.playerName = playerName;
}
public void setPreviousPlayer(Player previousPlayer) {
this.previousPlayer = previousPlayer;
}
public void setNextPlayer(Player nextPlayer) {
this.nextPlayer = nextPlayer;
}
public Player getPreviousPlayer() {
return previousPlayer;
}
public Player getNextPlayer() {
return nextPlayer;
}
public void reverseSiblingPlayers() {
Player previousPlayer = this.previousPlayer;
Player nextPlayer = this.nextPlayer;
this.nextPlayer = previousPlayer;
this.previousPlayer = nextPlayer;
}
}
Probably you can have a Chain of your performers.
So the Chain should look like this:
public class Performer {
private Performer next;
private boolean active;
public perform() {
if(isActive()) {
switchStates();
// do something meaningul
} else if(next.isActive()) {
next.perform();
}
}
public void setActive(boolean active) {
this.active = active.
}
private boolean isActive() {
return active;
}
private void switchStates() {
boolean currentState = this.active;
next.setActive(currentState );
this.active = !currentState;
}
}
IMPL2: when performers should do different things
public void perform(Action action) {
if(isActive()) {
// update states and do other basic actions
action.execute(); // executes action on current performer
} else if(next.isActive()) {
next.perform(action);
}
}
IF all performers can do the same JOB, but you need to switch between
it - create current state holder and call it from perform() method
according to performer "active" state. So, when some event is
registered, you should call perform() method, inside it you can do
whatever you want.
IF your performers should do different things, you should consider
about an "Action" class with different implementations, and it
should be passed into perform() method (you can see this in IMPL2 snippet)

Add weapons to inventory

I am trying to add weapons to a player inventory. It's kind of hard to explain, so I'll try my best. What I have are a class for each weapon, a class for Combat, and a class for the Player. I am trying to get it to where when the Random number equals a certain number, it will add a weapon to the player inventory. I will put my code Below.
Combat Class:
public class Combat {
M4 m4 = new M4();
M16 m16 = new M16();
M9 m9 = new M9();
Glock glock = new Glock();
SCAR Scar = new SCAR();
Player player = new Player();
final int chanceOfDrop = 3;
static boolean[] hasWeapon = {false, true};
public static int ranNumberGen(int chanceOfDrop) {
return (int) (Math.random()*5);
}
private void enemyDead() {
boolean canDrop = false;
if(ranNumberGen(chanceOfDrop)==0){
canDrop = true;
}
if(canDrop == true){
if(ranNumberGen(0) == 1) {
Player.addInvetory(m4.weaponName(wepName), m4.weaponAmmo(wepAmmo)); //Issues here. wepName & wepAmmo cannot be resolved into variable
//Should I just delete the line?
//Trying to get it to add the weapon M4 to the player inventory.
//Maybe use an ArrayList? If so I need a couple pointers on how to implement this.
}
}
}
}
M4 Class:
public class M4 implements Armory {
//Weapon classes are practically identical except for differences in the name wepDamage and wepAmmo.
public Integer weaponAmmo(int wepAmmo) {
wepAmmo = 10;
return wepAmmo;
}
public Integer weaponDamage(int wepDamage) {
wepDamage = 5;
return wepDamage;
}
public String weaponName(String wepName) {
wepName = "M4";
return wepName;
}
Player Class:
public class Player {
public static int health = 100;
//Player Class.
public static void addInvetory(String wepName, int wepAmmo) {
Player.addInvetory(wepName, wepAmmo);
}
public static void removeInventory(String wepName, int wepAmmo) {
Player.addInvetory(wepName, wepAmmo);
}
public static void removeAll(String wepName, int wepAmmo) {
Player.removeAll(wepName, wepAmmo);
}
Interface:
public interface Armory {
//Interface implemented by all of the weapons classes.
public Integer weaponAmmo(int wepAmmo);
public Integer weaponDamage(int wepDamage);
public String weaponName(String wepName);
Hope you can help!
class Weapon {
private final String name;
private final int damage;
private final int ammo;
public Weapon(final String name,final int damage,final int ammo) {
this.name = name;
this.damage = damage;
this.ammo = ammo;
}
public Weapon clone() {
return new Weapon(this.name,this.damage,this.ammo);
}
public String getName() {
return this.name;
}
public int getAmmo() {
return this.ammo;
}
public int getDamage() {
return this.damage;
}
}
class WeaponFactory {
static WeaponFactory factory;
public static WeaponFactory getWeaponFactory() {
if(factory == null) {
factory = new WeaponFactory();
}
return factory;
}
private ArrayList<Weapon> weapons = new ArrayList<Weapon>();
private Random random;
private WeaponFactory() {
//TODO: Fix Ammo and Damage
weapons.add(new Weapon("M4",0,0));
weapons.add(new Weapon("M16",0,0));
weapons.add(new Weapon("M9",0,0));
weapons.add(new Weapon("Glock",0,0));
weapons.add(new Weapon("SCAR",0,0));
}
public Weapon getWeapon() {
int w = random.nextInt(weapons.length);
return weapons.get(w).clone();
}
}
class Combat {
...
private void enemyDead() {
if(ranNumberGen(chanceOfDrop)==0){
Player.addInventory(WeaponFactory.getWeaponFactory().getWeapon());
}
}
}
You can use an array of Armory and the generate a random number from 0 to the size of the array as an index to the array to decide which weapon to add.
Okay dude, since your question about creating a programming language was closed, I'm answering it through here:
I think that your idea is great! Don't give up on it, yet don't get too excited. I would try all the options that you have heard of(interpreted route AND the Compiled route). If you can get either of those to work, then you may proceed to go into further detail with the language creation. It's going to take a while though. Be patient!

Java newbie - car application

I'm a student and, yes, this is my homework. I've spent the last week reviewing notes, reading the book, and researching related topics on the net, but I just don't get what the problem is. Can you tell me what I'm doing wrong? Any help will be greatly appreciated. (I'm only using notepad and the command prompt.)
The guidelines I was given: Create a Java application consisting of two classes. Class one will be your application class. Class two will be a class called Car. Your application will create an instance of Car, called nova, and drive it.
Rules for the car:
You can’t drive a car if it is not started (send an error message to the console).
You can’t stop a car if it is not started (send an error message to the console).
You can’t start a car if it is already started (send an error message to the console).
Once you tell the car to drive, the only thing you can do is stop (Send a message to the console)
Once you call stop, the car will return to the initial state and the user must start the car before attempting to do any other functions. (Send a message to the console)
The purpose of the showState method is provide a way to inspect the state of the car. It should build a message, which can then be sent to the console.
My code:
public class MyAppAssignment3
{
public static void main (String[] args)
{
System.out.println("Scenario 1");
Car nova1 = new Car();
nova1.start();
nova1.showState();
nova1.drive();
nova1.stop();
nova1.showState();
System.out.println("");
System.out.println("Scenario 2");
Car nova2 = new Car();
nova2.showState();
nova2.drive(); //needs to send error message - can't drive a car that's not started
nova2.stop();
nova2.showState();
System.out.println("");
System.out.println("Scenario 3");
Car nova3 = new Car();
nova3.showState();
nova3.start();
nova3.showState();
nova3.stop(); //needs to send error message - can't stop a car that's not driving
nova3.showState();
nova3.drive();
nova3.stop();
}
}
class Car
{
private boolean isStarted;
private boolean isDriving;
private boolean isStopped;
private String showState;
public Car()
{
this.showState = showState;
}
public void start()
{
isStarted = true;
isDriving = false;
isStopped = false;
System.out.println("The car is " + this.showState);
}
public void drive()
{
isStarted = false;
isStopped = false;
isDriving = true;
System.out.println("The car is " + this.showState);
}
public void stop()
{
isStopped = true;
isStarted = false;
isDriving = false;
System.out.println("The car is " + this.showState);
}
public String showState()
{
if (isStarted)
{
showState = "started";
}
else if(isDriving)
{
showState = "driving";
}
else if(isStopped)
{
showState = "stopped";
}
System.out.println("The car is " + this.showState);
return showState;
}
}
My output (which is all wrong - the values are incorrect):
Scenario 1
The car is null
The car is started
The car is started
The car is started
The car is stopped
Scenario 2
The car is null
The car is null
The car is null
The car is stopped
Scenario 3
The car is null
The car is null
The car is started
The car is started
The car is stopped
The car is stopped
The car is stopped
Sorry if this posted all wonky. I typed it fine but the preview looks screwy.
This isn't actually doing anything...
public Car()
{
this.showState = showState;
}
Basically, it's simply reassign the same value back to itself. I'd change to an initial state, probably of stopped
I'd use enum for my car status, rather then relying on boolean states, which could become jumbled...
public enum CarState {
Stopped,
Started,
Driving
}
Then simply assign it to a single state variable...
class Car
{
private CarState state;
public Car()
{
this.state= CarState.Stopped;
}
public void start()
{
if (state.equals(State.Stopped)) {
state = CarState.Started;
showState();
} else {
System.error.println("Car is not in a valid state to be started");
}
}
public void drive()
{
if (state.equals(State.Started)) {
state = CarState.Driving;
showState();
} else {
System.error.println("Car is not in a valid state to be driven");
}
}
public void stop()
{
if (state.equals(State.Driving)) {
state = CarState.Stopped;
showState();
} else {
System.error.println("Car is not in a valid state to be stopped");
}
}
public String showState()
{
System.out.println("The car is " + state);
}
}
The other issue you're having is that the showStatus isn't been called when you change state, which isn't assigning the current state to the showState variable...which I've corrected for by using enum
For one you're just creating a new instance. You never actually set defaults for those instances.
Consider at least something like this:
public Car()
{
isStopped = true;
}
That way when you call your first nova1.start(); you can check if isStopped is true before allowing it to start again...
public void start()
{
if(isStopped)
{
isStarted = true;
isDriving = false;
isStopped = false;
showState = "started";
System.out.println("The car is " + this.showState);
}
}
Just one example. But you can easily use that to extrapolate the rest of your needs. My point is primarily that you create an instance but then expect the boolean values to have a value without being specified. You can do this in defaults, or in the constructor.
For example:
private boolean isStarted = false;
Using enum's is a nice idea.
Here is an Implementation using Enum's, Enum's with default Implementations and own implementations using the typesystem.
Also there aren't any Conditionals, like if or switch used.
Just pure and beautiful Java Code.
public class Car {
private enum State {
OFF {
void start(Car c) {
System.out.println("Starting the car");
c.state = State.STARTED;
}
},
STARTED {
void stop(Car c) {
System.out.println("Stopping the car");
c.state = State.OFF;
}
void drive(Car c) {
System.out.println("Driving the car");
c.state = State.DRIVING;
}
},
DRIVING {
void stop (Car c) {
System.out.println("Stopping the car");
c.state = State.OFF;
}
};
void start(Car c) {
System.err.println("Can't start");
}
void stop(Car c) {
System.err.println("Can't stop");
}
void drive(Car c) {
System.err.println("Can't drive");
}
}
private State state = State.OFF;
public void start(){
state.start(this);
}
public void stop(){
state.stop(this);
}
public void drive() {
state.drive(this);
}
public void showState(){
System.out.println("The car is "+state);
}
}
This worked! Thanks for all the help!
public class MyAppAssignment3
{
public static void main (String[] args)
{
System.out.println("Scenario 1");
Car nova1 = new Car();
nova1.start();
nova1.showState();
nova1.drive();
nova1.stop();
nova1.showState();
System.out.println("");
System.out.println("Scenario 2");
Car nova2 = new Car();
nova2.showState();
nova2.drive();
nova2.stop();
nova2.showState();
System.out.println("");
System.out.println("Scenario 3");
Car nova3 = new Car();
nova3.showState();
nova3.start();
nova3.showState();
nova3.stop();
nova3.showState();
nova3.drive();
nova3.stop();
}
}
class Car
{
private boolean isStarted;
private boolean isDriving;
private boolean isStopped;
private String showState;
public Car()
{
isStarted = false;
isDriving = false;
isStopped = true;
}
public void start()
{
if(isStarted == false)
{
isStopped = false;
isStarted = true;
showState();
}
else
{
System.out.println("You can't start a car which is already started.");
}
}
public void drive()
{
if(isStarted)
{
isDriving = true;
showState();
}
else
{
System.out.println("You can't drive a car which is not started.");
}
}
public void stop()
{
if(isStarted)
{
isStarted = false;
isDriving = false;
isStopped = true;
showState();
}
else
{
System.out.println("You can't stop a car which is not started.");
}
}
public String showState()
{
if(isStarted && (isDriving == false))
{
showState = "started";
}
else if(isStarted && isDriving)
{
showState = "driving";
}
else if(isStopped)
{
showState = "stopped";
}
System.out.println("The car is " + this.showState + ".");
return showState;
}
}
What I would suggest is this, each car has its own unique id:
class Car
{
private boolean isStarted;
private boolean isDriving;
private boolean isStopped;
private String showState;
private int id;
public Car(Integer id)
{
this.id = id;
}
...
}
then in all place where you say print out, also include id:
System.out.println("The car id "+id+" is "+ this.showState);
then create an object like that:
Car nova1 = new Car(1);
Car nova2 = new Car(2);
Car nova3 = new Car(3);
It is not solution, but it gives the way to solution. You will find solution and u will feel it's taste
You have to translate in code what you've been asked for, and as you can see it's even way close to actual requirement - e.g.:
You can’t drive a car if it is not started (send an error message to the console).
becomes:
public void drive()
{
if( this.isStarted == false ){
System.out.println("You should start the car first!");
}else{
System.out.println("Car is running!");
}
}
Notice that you can write !this.isStarted as a shorthand for isStarted == false.
Try outputting the value of variables in each step. There are a few issues in the logical flow. For example, check the constructor.
public Car()
{
System.out.println(showState);
this.showState = showState;
}
There is no showState value being passed to the constructor and its not initialized inside the function too.
Also, inside each function start, stop and drive, you need to write :
System.out.println("The car is " + this.showState());
instead of :
System.out.println("The car is " + this.showState);
Let's keep it simple, why use 3 variables when you need only two? Correct if I'm wrong, but if a car is not started and you are not driving it then it's stopped, right? Look at my class:
public class car
{
private boolean isStarted;
private boolean isDriving;
public car()
{
isStarted = false;
isDriving = false;
//Initial State
showState();
}
public void start()
{
if(!isStarted)
{
if(!isDriving)
isStarted = true;
}
else
System.err.println("You can\'t start a car which is already started"); //You can’t start a car if it is already started (send an error message to the console).
showState();
}
public void drive()
{
if(isStarted)
isDriving = true;
else
System.err.println("You can\'t drive a car which is not started");
showState();
}
public void stop()
{
if(isStarted)
{
isStarted = false;
isDriving = false;
// Once you call stop, the car will return to the initial state and the user must start the car before attempting to do any other functions. (Send a message to the console. (Below on ShowState)
}
else
System.err.println("You can\'t stop a car which is not started"); // You can’t stop a car if it is not started (send an error message to the console).
showState(); // Once you tell the car to drive, the only thing you can do is stop (Send a message to the console)
}
public void showState()
{
if(isStarted && isDriving)
System.out.println("It\'s Driving");
if(!isStarted && !isDriving)
System.out.println("It\'s Stopped");
if(isStarted && !isDriving)
System.out.println("It\'s Started");
}
}
I hoped it helped. Cheers

Categories