How to access the initial value of an initialized object? - java

I'm learning java at the moment and I've got a question about an object that got initialized and got a variable changed during the program execution.
public class Char {
private String name;
private int skill;
private int defense;
private int life;
private Weapon weapon = Weapon.FISTS;
private Potion potion = null;
So, I want this code to get the initial value of life that got initialized, but how would I access it?
public boolean isWeak() {
return life < this.life * 0.25;
}
So, this method is located in the Char class. I'm trying to get it to return a true value when it gets lower than 25%.
while (hero.isAlive() && monster.isAlive()) {
if (hero.isWeak() && hero.hasPotion()) {
hero.sip();
} else if (monster.isWeak() && monster.hasPotion()){
monster.sip();
} else {
System.out.println(monster.isWeak());
hero.attack(monster);
if (monster.isAlive()) {
monster.attack(hero);
}
System.out.println();
}
}
Here is the execution program. All the other methods work just fine, but as pointed out, it'll never return true because it can't be a quarter of itself. Don't mind the prints, I'm just testing it.

To do this, you need to create a second variable that stores the value passed into the constructor:
public class Char {
private String name;
private int skill;
private int defense;
private int initialLife;
private int life;
private Weapon weapon = Weapon.FISTS;
private Potion potion = null;
public Char(int initialLife //I am excluding all the other parameters you want to pass in
) {
this.life = initialLife;
this.initialLife = initialLife;
}
public boolean isWeak() {
return life < this.initialLife * 0.25;
}
}
As you can see, I store the initial life and I don't ever modify it. Since I modify the life variable, I can't use it to keep track of the initial value. Modifying a variable is a destructive process, and Java doesn't have a way to keep track of the history of variable values (unless you do it yourself as shown above).

Related

Referencing method from abstract class

START OF INSTRUCTIONS
If there is a game piece on the clicked square (clickedSquare.getPiece()!= null)
Make sure the game piece belongs to the current player. You can get the owning player by calling the getPlayerType() method on the AbstractGamePiece returned by getPiece(). You can then compare that to the currentPlayerTurn JailBreak class member.
If the piece on the clicked square belongs to the current player
Set the selected square equal to the clicked square
Call the select() method on the selected square to show the yellow border
END OF INSTRUCTIONS
I've figured out how to highlight the piece by implementing the select() method, butt
I've tried several different implementations, such as AbstractGamePiece.getPlayerType()==currentPlayerTurn, using nested if statements to set conditions on clickedSquare.getPiece(), and a couple others that I can't think of off the top. I can't seem to get a reference to getPlayerType() from the abstract class. There is pre-written code in the class that seems to work fine as far as accessing the AbstractGamePiece, such as
private void changePlayerTurn()
{
if (currentPlayerTurn == AbstractGamePiece.PLAYER_OUTLAWS)
currentPlayerTurn = AbstractGamePiece.PLAYER_POSSE;
else
currentPlayerTurn = AbstractGamePiece.PLAYER_OUTLAWS;
}
I feel like I'm going about this wrong, but I can't seem to get a reference to the getPlayerType(). The one time I did, I created a new object of the abstract class, but the constructor needs 3 parameters that aren't really appropriate here.
Supporting code:
abstract public class AbstractGamePiece
{
// All class members are provided as part of the activity starter!
// These two constants define the Outlaws and Posse teams
static public final int PLAYER_OUTLAWS = 0;
static public final int PLAYER_POSSE = 1;
// These variables hold the piece's column and row index
protected int myCol;
protected int myRow;
// This variable indicates which team the piece belongs to
protected int myPlayerType;
// These two strings contain the piece's full name and first letter abbreviation
private String myAbbreviation;
private String myName;
// All derived classes will need to implement this method
abstract public boolean hasEscaped();
// The student should complete this constructor by initializing the member
// variables with the provided data.
public AbstractGamePiece(String name, String abbreviation, int playerType)
{
myName = name;
myAbbreviation = abbreviation;
myPlayerType = playerType;
}
public int getPlayerType()
{
return myPlayerType;
}
public void setPosition (int row, int col)
{
myRow = row;
myCol = col;
}
public int getRow()
{
return myRow;
}
public int getCol()
{
return myCol;
}
public String getAbbreviation()
{
return myAbbreviation;
}
public String toString()
{
return (myName + " at " + "(" + myRow + "," + myCol + ")");
}
public boolean canMoveToLocation(List<GameSquare> path)
{
return false;
}
public boolean isCaptured(GameBoard gameBoard)
{
return false;
}
Code that highlights the pieces indiscriminately has been implemented successfully.
private void handleClickedSquare(GameSquare clickedSquare)
{
if (selectedSquare == null)
{
selectedSquare=clickedSquare;
selectedSquare.select();
}
else if (selectedSquare == clickedSquare)
{
selectedSquare.deselect();
selectedSquare = null;
}
else
{
}
Why is it that I'm unable to create a reference to the getPlayerType() method?
Just call getPlayerType on any expression of type X, where X is either AbstractGamePiece or any subclass thereof. For example, square.getPiece().getPlayerType().
Method references are a thing in java and are definitely not what you want, you're using words ('I'm unable to create a reference to getPlayerType') that mean something else. A method reference looks like AbstractGamePiece::getPlayerType, and let you ship the concept of invoking that method around to other code (for example, you could make a method that calls some code 10 times in a row - so this method takes, as argument, 'some code' - and method references are a way to that). It is not what you want here, you want to just invoke that method. Which is done with ref.getPlayerType() where ref is an expression whose type is compatible with AbstractGamePiece. From context, clickedSquare.getPiece() is that expression.

oop java method to increment number sequentially

Im having an issue where I have to create a method in java to get a ticket number which every time it is called it generates a number sequentially.
this is what I have so far regarding the ticket method
public class Ticket
{
public static final String PREFIX = "CAR";
public static int number = 1000;
//instance variables
private String ticketNumber;
public Ticket(){
ticketNumber = generateTicketNumber();
}
public String getTicketNumber(){
return ticketNumber;
}
private String generateTicketNumber(){
number = number++;
ticketNumber = PREFIX +number;
return ticketNumber;
}
I'm told to use a static variable (which i have) to create and hold a counter to generate part of the ticket number, increment the static variable and assign it combined with the string prefix to the field ticketNumber. When i create an object it does not increment to CAR1001, it just goes CAR1000, am I to try a while loop for this?
number = number++; is not evaluated how you think. What this actually does is that the right-hand side increments number, but number++ is also an expression whose value is the old value of number, before the increment is done. Then because of the number = ... assignment, that old value is assigned to number on the left-hand side, undoing the increment.
So you should just write number++; instead, which simply increments the variable.
Unless I'm missing something, I think you've over complicated this. All you need is PREFIX and number. Concatenate PREFIX with number and increment number. That can be done in one step like,
public class Ticket {
private static final String PREFIX = "CAR";
private static int number = 1000;
public String getTicketNumber() {
return PREFIX + number++;
}
}
Or, perhaps a little easier to read,
public String getTicketNumber() {
try {
return PREFIX + number;
} finally {
number++;
}
}

Setting a value to zero

Ok so in my cs class we have an assignment that requires us to return a value and then set it to zero. I can't figure out how to do this without using a secondary variable(which would break requirements) so I would appreciate some help. here are the exact requirements.
"Has a use() method that returns the value contained in the points field. It also resets the points field to zero. You’re going to have to think about the order of operations here to make this work correctly."
package Game;
import java.util.Random;
public class HealthPotion
{
private int points;
boolean Haspotion;
HealthPotion()
{
Random num1 = new Random();
int num = num1.nextInt(10)+1;
points=num*10;
}
public int Use()
{
return points;
}
public int getPoints()
{
return points;
}
}
That's not really possible without abusing a finally block, i.e.
try {
return points;
} finally {
points = 0;
}
However it's really hard to believe that would be what's wanted, since it's not a good idea to write code like that.
Include a setter method like this.
public void setValue(){
this.points=0;
}
Call this method after you get the value.
How about this?
public int Use()
{
int tmp = points;
points = 0;
return tmp;
}
It has limitations, especially if points can be changed by a different thread while this method executes. But if you are working in a single-threaded environment this should be ok.
This should work
int points = 5;
public void test(){
System.out.println(use() +" " + points);
}
private int use(){
return points - (points = 0);
}
returning 5 0

Creating a method that works like ArrayList .add()

I'm writing a program that acts as a 'pocket' where the user is able to enter a kind of coin, such as, a quarter and the amount of quarters it has. I was assigned to do 3 different class, the Coin Class in which the coins and their values can be instatiated from, a Pocket Class, where I have to write a method that can add the coins of the user (basically the method would act like ArrayList .add() ) and the PocketClass tester. I have already written most of the code, but I am stuck as to how I could write the following method:
public void addCoin(String s, int i)
{
// s is type of coin, you are using s to instantiate a Coin and get value
// i is number of coins, you are using i to keep adding value to the totalValue
}
My question is how should I approach this? I am not quite clear on how to create method. Would I use a for-loop in order to keep track of the number of coins? I understand that the addCoin method works a lot like .add() from ArrayList.
Here is the code from my other classes:
public class Coin
{
private final String DOLLAR = "DOLLAR";
private final String QUARTER = "QUARTER";
private final String DIME = "DIME";
private final String NICKEL = "NICKEL";
private final String PENNY = "PENNY";
private int value;
private String coinName;
public Coin(String s,int count)//name of the coin and also the number of the coins you have
{
//Use if or switch statement to identify incoming string and provide value
double value=0;
if(DOLLAR.equalsIgnoreCase(s))
{
value=100.0;
}
else if(QUARTER.equalsIgnoreCase(s))
{
value=25.0;
}
else if(DIME.equalsIgnoreCase(s))
{
value=10.0;
}
else if(NICKEL.equalsIgnoreCase(s))
{
value=5.0;
}
else if(PENNY.equalsIgnoreCase(s))
{
value=1.0;
}
}
public int getValue()
{
return value;
}
}
and how the Pocket class is structured:
public class Pocket
{
private int currentValue;
private int totalValue;
private Coin quarter;
private Coin dime;
private Coin nickle;
private Coin penny;
public Pocket()
{ //Set initial value to zero
totalValue = 0;
currentValue = 0;
}
public void addCoin(String s, int i)
{
// s is type of coin, you are using s to instantiate a Coin and get value
// i is number of coins, you are using i to keep adding value to the totalValue
}
public int getValue()
{
return totalValue;
}
public void printTotal()
{
//print out two different output
}
}
I'm assuming you're adding the addCoin method in the Pocket class.
If you intend to keep track of the number of coins of each type within a Pocket, the simplest way to do so would be to declare a Hashmap that is keyed by the coin type (say, a "quarter" or a "dollar") and valued by the number of coins of that type. An invocation of the addCoin(type, count) method, say addCoin("dollar", 5) can then check if the hashmap already contains a key named "dollar" and if present, increment it's value by count.
I would suggest storing coins in a list so that you can add unlimited number of them.
Example:
class Coin{
//Same as your code....
public Coin(String coinType){
//..Same as your code, but removed number of coins
}
}
public class Pocket
{
private int currentValue;
private int totalValue;
//Create a list of coins to store unlimited number of coins
// A pocket can half 5 dimes
List coins;
public Pocket(){
//Set initial value to zero
totalValue = 0;
currentValue = 0;
coins = new ArrayList<Coin>();
}
/**
* This method will take only one coin at a time
**/
public void addCoin(String s){
Coin c = new Coin(s);
coins.add(c);
totalValue+=c.getValue();
}
/**
* This method will take any number of coins of same type
**/
public void addCoin(String s, int c){
//Add each one to array
for(int i=0;i<c;i++)[
addCoin(s);
}
}
}
I am not in favor of keeping multiple coin values in one Coin object because of the fact it is not a true representation of an object. What does that mean is tomorrow if you want to store other Coin attributes like "Printed Year", "President Picture on the coin" etc, you will have hard time. In my opinion it is better to represent one real world object (one coin here) using one object instance in the program,

Mapping magic numbers to enum values, and vice-versa

In the database I'm using this with there are magic numbers which I want to map to the State enum, and vice-versa. I'm intrigued by the static declaration of undefined.code = 0. What does this declaration, if that's what it is, actually do?
package net.bounceme.dur.data;
public enum State {
undefined(0), x(1), o(2), c(3), a(4), l(5), d(6);
private int code = 0;
static {
undefined.code = 0;
x.code = 1;
o.code = 2;
c.code = 3;
a.code = 4;
l.code = 5;
d.code = 6;
}
State(int code) {
this.code = code;
}
public int getCode() {
return this.code;
}
public static State getState(int code) {
for (State state : State.values()) {
if (state.getCode() == code) {
return state;
}
}
return undefined;
}
}
Currently, the usage for this enum factory method is as so:
title.setState(State.getState(resultSet.getInt(5)));
but I would be interested in any and all alternatives.
I've removed the useless static block and improved the inverse function.
public enum State {
private static Map<Integer,State> int2state = new HashMap<>();
undefined(0), x(1), o(2), c(3), a(4), l(5), d(6);
private int code;
State(int code) { // executed for *each* enum constant
this.code = code;
int2state.put( code, this );
}
public int getCode() {
return this.code;
}
public static State getState(int code) {
return int2state.get(code);
}
}
If the "code" integers are definitely ordinals from 0 up, you can omit the Constructor parameter, private int code and map like so:
int2state.put( this.ordinal(), this );
In the code you posted, the static block line
undefined.code = 0;
It accesses the enumerated constant undefined, and blindly sets the value of the mutable field code from 0 to 0. Basically, the constant was defined here
undefined(0)
with a code of 0. Likewise with x and 1. And so on.
Well it really does the same thing as the constructor - sets the code associated each enum value.
In your example, the static { ... } block is superfluous (unnecessary) and should probably be removed since it duplicates the line starting with underfined(0).
The point where Enum usage gets tricky is with the lookup (in your case, getState(...) method). The case statement here really duplicates the code a third time, and you might be better to build a Map that takes a code (int) and returns the enum (State) - just google around, there are plenty of examples on how to do this.
Just a hint. It is much more readable to change your getState(int) method to
public static State getState(int code) {
for (State state : State.values()) {
if (state.getCode() == code) {
return state;
}
}
return undefined;
}

Categories