Simple if-clause not working, can't find the mistake - java

So I am working on an incremental game at the moment. In case you don't know what this is a short explanation. You click a button to get some kind of money (in my case gold). With enough money you can buy stuff that makes you money without even clicking. With more money you can get better upgrades which makes you even more money and so on.
Now to my problem; I created a class called Upgrade which you can see here:
public class Upgrade {
double baseCost;
double baseIncome;
int count =0;
double cost = baseCost*Math.pow(1.07,count);
double goldPerSecond = baseIncome; //TODO find usefull formula!
public Upgrade(double baseC, double baseIn){
baseCost = baseC;
baseIncome = baseIn;
}
}
The variables should explain themselves.
Now I created some Upgrades via the constructor:
Upgrade waitress = new Upgrade(50 ,2); //Constructor for Waitress
Upgrade seats = new Upgrade(100, 5); //Constructor for More-Seats
Upgrade decoration = new Upgrade(500, 20); //Constructor for Decoration
Upgrade bartender = new Upgrade (1000, 50); //Constructor for Bartender
To buy upgrades I have written the method buyUpgrade which is bound to buttons referring to the upgrades listed above.
public void buyUpgrade(Upgrade U) {
if (goldCount >= U.cost) {
goldCount = goldCount - U.cost;
clickGoldPerSecond++;
U.count++;
} else {
error.setText(getResources().getString(R.string.no_gold));
}
}
And here comes the problem. As the game starts you have 0 gold. That 0 is stored in the variable goldCount. But even though goldCount is I can buy every Upgrade in unlimited amounts. I just cant figure out the problem. Probably it is really simple and afterwards I realize how stupid I was but I just cant figure it out.
Every help is appreciated. Thank you!

The problem is that
double baseCost;
double baseIncome;
int count =0;
double cost = baseCost*Math.pow(1.07,count);
baseCost being the member variable of the class, is intialized to 0.0
SO "cost" set to 0.0 and it never changed after that.
You should move the cost calculation in the constructor.
public Upgrade(double baseC, double baseIn){
baseCost = baseC;
baseIncome = baseIn;
cost = baseCost*Math.pow(1.07,count);
}

public class Upgrade
{
double baseCost;
double baseIncome;
int count =0;
double cost ;
double goldPerSecond;
public Upgrade(double baseC, double baseIn)
{
baseCost = baseC;
cost = baseCost * Math.Pow(1.07,count);
baseIncome = baseIn;
}
}
Your Upgrade class should be similar to what I have created here. If there is a non static filed in the class and you are assigning value to that variable in the way you were doing it will not work.
In your case you also cannot use the static variable as the variable baseCost is passed as constructor parameter and will not be available until you create an instance of upgrade class.
If Condition if(goldCount >= U.cost){} Here the cost will have value of zero only as it would not get updated.

Here is your problem:
int count =0;
double cost = baseCost*Math.pow(1.07,count); // cost is set and will not be updated
Pls note that you update baseCost in your constructor, but before that the default value 0.0 is being used for baseCost * Math.pow(...);. But even if you update that, by having it done in the constructor, still you will not see any price going up, because the cost is not being recalculated at all.
Set the initial value in the constructor (or have baseCost always being added to the cost when accessing the cost).
Make a method which adds one to count and then does Math.pow(...) on cost again.
Now for a much better solution: hence, in this case the attribute cost is useless. Change it into a method:
public double getCost() {
return baseCost*Math.pow(1.07,count);
}
call it (change 2x U.cost --> U.getCost()) and your sky will be blue again, no further change needed where ever.

You are missing getter/setter for cost i guess. Therefore it always return 0.0.
I mean try to create an Upgrade object with the constructor, then print out the cost. No matter what you give in the constructor, the cost for the object always print out "0.0".

Related

Compound Interest Program Syntax Error

I have the below code to run a compound interest program but I do not know why it is not working. Eclipse is giving me the error message: "The value of the local variable amount is not used."
package loops;
public class CompoundInterest {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("How much did you put into the bank?");
double deposit = IO.readDouble();
System.out.println("What is the bank's interest rate?");
double rate = IO.readDouble();
System.out.println("How many times will it compound?");
double compound = IO.readDouble();
System.out.println("How many years?");
double years = IO.readDouble();
for (int i = 1; i<=20; i++){
double amount = deposit * Math.pow(1+(rate/compound), years*compound);
}
}
}
Strictly speaking, this is a compiler warning (not an error). It's technically "legal" to have variables you don't actually use, but the compiler's telling you that it's probably a mistake. In this case, as others have indicated, you assign a value to amount but you never actually do anything with it.
As a general tip, it's helpful to pay close attention to the text of the warning - in this case, it was what it said (you don't do anything with the amount variable). Eric Lippert has an extremely helpful article available on how to debug small programs that I recommend taking a look at when you get a chance. (His explanation of "rubber-duck debugging" alone makes the article more than worth the read).
Just add a statement inside your loop to use amount as -
for (int i = 1; i<=20; i++){
double amount = deposit * Math.pow(1+(rate/compound), years*compound);
System.out.println(amount); // just a type of use
}
The warning is to notify that the amount calculated in the statement is being not in use. Once used(even for displaying as above) the warning shall go away.

Commenting a default constructor when writing a class

In my Java basic class my teacher told me to comment any arbitrary choice that I make when I write a default constructor for a class. (She told us that we must create a default constructor for every class that we design) So for example, I'm writing a class named RoomDimension, and I created a default constructor as follows:
public class RoomDimension {
//Fields
private double length; //Length of a carpet
private double width; //Width of a carpet
/**
*
*/
public RoomDimension(){
length = 0.0;
width = 0.0;
}
I'm using here 0.0 as my flag to indicate the user has entered nothing or an invalid input. Should I then comment the fact that 0.0 is used as an indication of an invalid input in the documentation comment(/**/)? I know that if I were to use -1 as my flag (or an initialization of a field in default constructor), I would definitely comment that -1 indicates an invalid input because I made that decision arbitrarily. I'm asking whether 0 has to be commented or not because I don't know if 0 is an arbitrary choice or not. Would you, as a programmer, bother to indicate that? Or, is it okay if I just assume that the user knows it without telling them?
As to whether zero should be commented, I think it would be best to indicate it is a flag in order to remind yourself in the future, or any other programmer that looks at your code.
As for using zero as a flag, I think it would be better practice to throw an exception when length and height are less than or equal to zero. It would be easier to read in the future, and more efficient to handle when a user does enter a non-positive number.
She told us that we must create a default constructor for every class
that we design
And I told for my teacher: Who don't know is teaching, who know is doing!
If you don't create a default constructor, the compiler will do it, did you know? - how about your teacher?
Many tools, which generates, transform data will cry, nags, crash if they don't find a COMPILED "default constructor". But they will completely ignore the comments.
So back to your class:
public class RoomDimension {
static {
System.out.println("I an a static initializer, If the classloader will touch your class, I will be called first! ex. RoomDimension.anyStaticmethod() or before new RoomDimension()");
}
{
System.out.println("I am instance initializer. whenever you call any constructor, I will run before the constructor body, try me with: new RoomDimension()");
}
//Fields
private double length; //Length of a carpet
private double width; //Width of a carpet
public RoomDimension() {
length = 0.0;
width = 0.0;
}
}
By the way in your code:
public RoomDimension() {
length = 0.0;
width = 0.0;
}
it is completely useless, because before constructor, it will be an initialisation and that will do exactly the same, because you have declared as properties and they will be initialize, before constructor:
private double length; //Length of a carpet
private double width; //Width of a carpet
If you want to know it is initialized or not, use Double instead of double and check for null value.
Ex:
private Double length; //Length of a carpet
private Double width; //Width of a carpet
I would set the values of those to be nullable.
public class RoomDimension
{
private double? length;
private double? width;
}
public RoomDimension()
{
}
What this does for you is allow the values of length and width to take the value of null. So when you call the default constructor, they are automatically set to null.
This will help you start thinking in terms of objects, because when you have objects that contain other objects you cant set all the contained objects to 0.0, you just create a null object. Also when you perform actions on that object you just check if its null beforehand this helps to avoid null reference exceptions.

Java function is updating its input variable

I'm doing a lab at the moment working on fitness functions. The problem is I'm making a SmallChange() function that does what it says, annoyingly it seems to update the variable you give it, when it shouldn't.
Here's a copy of the full class: https://gist.github.com/1710367
Line 38 is the problem line.
And below is the function. When I give it solution as an input it updates solution with the small change it makes, but I can't figure out how or why.
Anyone know where I'm going wrong? It's starting to hurt my brain.
// Edits either the angle or velocity of our solution
// by a small amount (about 1% of the diffrence between max and min)
public static Double[] SmallChange(Double[] sol) {
// Pick a 0 or 1
switch (r.nextInt(2)) {
case 1: // Changing the angle
// The angle change amount
Double angle = (angleLimits[1] - angleLimits[0]) * 0.01;
// Make the change, either + or -
if (r.nextInt(2) == 0) {
sol[0] += angle;
} else {
sol[0] -= angle;
}
// Check it's within the limits
if (sol[0] > angleLimits[1]) {
sol[0] = angleLimits[1];
} else if (sol[0] < angleLimits[0]) {
sol[0] = angleLimits[1];
}
break;
case 0: // Changing the velocity
// The velocity change amount
Double velocity = (velocityLimits[1] - velocityLimits[0]) * 0.01;
// Make the change, either + or -
if (r.nextInt(2) == 0) {
sol[1] += velocity;
} else {
sol[1] -= velocity;
}
// Check it's within the limits
if (sol[1] > velocityLimits[1]) {
sol[1] = velocityLimits[1];
} else if (sol[1] < velocityLimits[0]) {
sol[1] = velocityLimits[1];
}
break;
}
return sol;
}
In Java, everything is passed by value - but that value is always either a primitive, or a reference.
So the value of any array variable is a reference to an array object. When you use that variable as an argument, the value (the reference) ends up as the initial value of the parameter. It's still referring to the same array object as the caller's variable - so any changes made to the array will be seen by the caller.
So just to clarify, your statement here is incorrect:
annoyingly it seems to update the variable you give it, when it shouldn't
It hasn't changed the value of the variable at all: that variable in the calling code still has the same value it did before, a reference to the same array. It's just that the method is changing the contents of the array.
It's like copying down your address on a piece of paper, then giving that to someone: they can't change where you live, but they can change the colour of your front door.
Now, to fix your problem...
If you want to clone the array, you'll have to do so explicitly. For example:
public static Double[] smallChange(Double[] sol) {
Double[] ret = (Double[]) sol.clone();
// Now work on ret instead of sol, and return ret at the end
You could reassign to sol, but personally I wouldn't.
Note that you might also want to use a double[] instead of Double[].

How to write a method to calculate compound interest by the year?

public class Balance {
public static void main(String[] args) {
System.out.printf("%.2f\n", balance(0.0, 0.0, 0.0));
}
/**
* #param principal
* #param rate
* #param years
* #return
*/
public static double balance(double principal, double rate, double years) {
double amount = 0;
Scanner sc = new Scanner(System.in);
System.out.print("Enter the initial investment amount: ");
principal = sc.nextDouble();
System.out.print("Enter the interest rate: ");
rate = sc.nextDouble();
System.out.print("Enter the number of years: ");
years = sc.nextDouble();
for (int i = 1; i < years; i++) {
amount = principal * Math.pow(1.0 + rate, years);
amount += principal;
}
return amount - principal;
}
}
My problem is with the printf line that I am using within the main method. Eclipse wants me to change the method balance from void to Object[]. When I do this I must return a value from balance. So I guess my question is, how would I return the proper value? Am I on the right track? Thank you for your time and constructive criticism. :)
EDIT - Thanks for the help everyone, much appreciated :) My math is off. I end up with 1000 more than I should have. hmmm.
So should I just take a 1000 from amount like so:
return amount - 1000;
Or this:
return amount - principal;
EDIT this is what I am going with since it is due tonight. Thanks to all for the assistance. :)
A few points:
balance() cannot be void, because you use its return value in S.out.printf(). Do you want balance to print to the screen, or do you want it to yield a number?
Your loop for (years = 0; years > 10; years++) won't run. Think about why. It might help to convert the for into a while, to visualize why.
You read in years as a double, but then use it as a counter in your loop. What type should it actually be?
Your balance() function takes three parameters, then immediately gets input and obliterates them. Do you want balance() to be provided these numbers, or do you want it to fetch them?
Otherwise, you seem to be on the right track.
The problem is that balance doesn't return anything, (it's a void function). Change it to:
public static double balance(double principal, double rate, double years) {
...
And inside that function, return the balance.
Java is telling you it wants an Object[] because printf is defined like this:
public static void printf(String format, Object ... params) {
// params is an Object[]
}
What this lets you do is pass parameters like this:
printf("some string", first, second, etc);
It lets you pass as many parameters as you want, and the function can handle them as if you passed an array.
It's exactly the same as if it was defined like this:
public static void printf(String format, Object[] params);
And you used it like this:
printf("some string", new Object[] { first, second, etc});
It's just easier to use.
EDIT:
The other option is to not print anything in main, but I would definitely advise returning the result and printing it in main. This follows the principle of making each function do as little as possible. balance should just calculate the balance. Printing it is unrelated.
Please consider a more drastic re-working of your code; as it is, your balance() function is doing all the work of your program (and your printf() line feels like an afterthought). If you break apart your code based on what the code does, I think you can do much better:
create a function that prompts the user and then reads in their input
create a function that calls the previous function three times for principal, rate, and years
create a function that computes and populates a payment schedule. Keep track of year, balance, payment, principal payment, and interest payment. (Or just the variables you're interested in -- but be aware that programs tend to grow new features, and these variables are often the second thing that users (or professors) ask to know when paying down a loan.)
create a function that prints the selected columns from your payment schedule.
create a function that orchestrates the previous functions.
When you re-write your program to use a GUI or webservice in three weeks, you'll definitely thank yourself for having written each function to do one task, and do it well. You'll also find it far easier to test smaller pieces of code that do only one task.
There is the risk of over engineering a too-generic solution -- what I'm really trying to suggest is a functional decomposition of your code into multiple smaller routines that do exactly what their name says. You might never move the program into a GUI or webservice or whatever, but you'll definitely be happier when someone reports that your amortization schedule is wrong, that you can control it via simpler programming, rather than having to re-type inputs all day long.
Yours is wrong, do this:
public static void main(String[] args) {
balance(1000.0, .05, 8.5);
}

making sure i am doing this problem correctly

this is my first programming course, and i want to make sure i am doing this problem correctly. if you could check over my work it would be greatly appreciated.
Write a method to compute and return the balance for a checking account, given the starting balance and an array of Check objects. You may assume that the Check class already exists and has a method to get the amount from a particular check object called: double getAmount()
The array is not full, and may have gaps in it – make sure you test to see if there is an object there before you try to access it! Make your code work for any length array!
The header for the method is provided for you:
public double computeBalance(double startingBalance, Check[] register) {
int i = 0; // i must be initialized and declared somewhere at least
double total = 0.0;
while ((i >= check.length) && check[i] != null) { // is >= correct? you do i++!
total = (total + getAmount(check[i])); // should you add/compute somewhere
// the given amounts
i++;
}  
System.out.println(total);
}
Forget programming for a second. If I told you "Here's the starting balance in your account." and then handed you a bunch of checks and told you to compute the ending balance, how would you do it? Once you understand that, you can start to work on the programming problem.
Some questions:
Where are you tracking the account balance?
What will happen in your loop if one of the slots in register is empty (i.e. null)?
What is this check variable in your loop? Where is it being declared? Is check really what it should be called?
The function is declared as returning double. What are you returning?
Have you tried compiling your code? What happens?
I understand that you are asking for more than for the solution itself but there are obviously better people to guide you. You can use my example as a reference to what others are explaining to you.
public double computeBalance(double startingBalance, Check[] register) {
// let's start off from the starting balance
double total = startingBalance;
// go over all elements starting from 0
for (int i = 0; i < check.length; i++) {
// make sure you did not encounter null element
if (register[i] != null) {
// increase the total by the amount of the Check
total += register[i].getAmount();
}
}
// and finally return the resulting value
return total;
}
The execution will end when you reach a gap. Use an if-statement inside the loop for the null check instead.
If you could run your code through a compiler (which it sounds like you can't, or at least aren't being encouraged to), it would tell you that it has no idea what i, check, or getAmount are.
A method body that doesn't refer to the method parameters is generally missing something -- especially if the parameter declarations were given by your instructor.
Look again at your loop condition. What is the value of i going to be at the beginning?

Categories