checkDeath() not being called - java

I am working on a Tower Defense project and I am running into a little issue.
public void loseHealth(int amo) {
health -= amo;
checkDeath();
}
public void checkDeath() {
if(health == 0) {
deleteMob();
}
}
This works, but when I try the following the health reaches zero and the mob does not get deleted. I have been trying to get this working for about 2 days and cannot seem to get it right. I have been unsuccessful at finding something to read that could help but I may not be looking in the right place.
public void loseHealth(int amo) {
shot = Value.damage[0] += amo;
health -= shot;
checkDeath();
}
public void checkDeath() {
if(health == 0) {
deleteMob();
}
}
I declared an array and that consists of:
public static int[] damage = {5, 10};
The reason I have two here is because I have two towers I am trying to have do different damage. Right now I just want to get it working I can do the part for the different towers. If there is more information you need please let me know.

That is because your health variable is getting decreased below 0. Therefore, health == 0 will always return false. Try the following instead:
public void checkDeath() {
if(health <= 0) {
deleteMob();
}
}

It looks possible that your loseHealth method could produce a negative value for health. If this is the case then your checkDeath method would have to use if(health <=0) for the condition.

Your problem is that you're checking explicitly if your health integer is at 0. Most likely, the mob's health counter is a negative number after getting inflicted damage.
Use
if(health <= 0)
Instead of
if(health == 0)

Related

Java recursive function below what is the problem?

public static int score(int[][] array, int win, int turn) {
int score = 0;
if (GamePrinciples.gameEnd(array, win)) {
if (GamePrinciples.draw(array)) {
score = 0;
} else if (GamePrinciples.winningBoard(array, win)[0] == 1) {
score = 1;
} else {
score = -1;
}
} else {
for (int[][] i : children(array, win, turn)) {
score += score(i, win, GamePrinciples.nextPlayer(turn));
}
}
return score;
}
briefly this program is part of my minimax algorithm. So the problem is that I get a stack over flow. Where am I going wrong?
if an array is in ending mode then if it is a draw it gives a score of zero if player one wins then a score of one and if player two wins it gives a score of two.
if the array is however not in the ending state we get the children of the array (immediate children that is the boards that result from the current board with only one move). The score of the board will be the sum of the score of each of its children. The logic seems okay and the other methods such as children, nextPlayer, winningBoard, draw all work fine with testing. So I am guessing there is problem with this kind of recursive implementation. Can anyone help? Thanks in advance
Your code seems wrong in the loop:
for (int[][] i : children(array, win, turn)) {
I haven’t tested, but you should call the method children() outside the for.
By calling the method within the for clause, you are always returning the initial array instead of iterating through it.
So try putting the children() method return to a variable and iterate through this variable.
Something like:
… c = children(…)
for(int[][] i : c) {
…

Random number guessing game with limitations after each guess

I am making a number guessing game:
The computer generates a number inside an interval
I try to guess it and receive a reply whether it's higher/lower than my guess or equals to my guess and I've won
There is an interval in which I can guess, as well as a guess attempt limit
The trick is, however, that I need to implement another condition: each guess should "shrink" the interval in which I'm able to guess. For example: computer generates 50, I guess 25, computer replies "The random number is larger.". Now knowing that, I should not guess anything lower than 25 again, it's unreasonable. In case I guess i.e. 15, the computer should reply "The guess doesn't make sense.". I understand that I somehow need to save each guess value to a new variable, but nothing seems to work. I'm a beginner, please bear with the following code, I've tried a lot of things:
public String guess(int guess)
{
int lowerBound = 0;
int upperBound = 99;
Set<Integer> lowerGuesses = new TreeSet<>();
Set<Integer> higherGuesses = new TreeSet<>();
if (gameOver) {
return "The game is over.";
}
if (guess < 0 || guess > 99) {
return "The guess is out of bounds.";
}
if (guessCount < maxGuessCount) {
if (guess < secretNumber) {
if (lowerGuesses.contains(guess)) {
return "The guess doesn't make sense.";
}
else {
guessCount++;
lowerBound = guess;
lowerGuesses.add(guess);
return "The random number is larger.";
}
}
if (guess > secretNumber) {
if (higherGuesses.contains(guess)) {
return "The guess doesn't make sense.";
}
else {
guessCount++;
upperBound = guess;
higherGuesses.add(guess);
return "The random number is smaller.";
}
}
if (lowerGuesses.contains(guess)) {
return "The guess doesn't make sense.";
}
if (higherGuesses.contains(guess)) {
return "The guess doesn't make sense.";
}
}
if (guess < lowerBound || guess > upperBound) {
return "The guess doesn't make sense.";
}
if (guessCount == maxGuessCount) {
gameOver = true;
victorious = false;
return "Ran out of guess attempts.";
}
guessCount++;
gameOver = true;
victorious = true;
return "You won.";
}
Thank you in advance!
First, to avoid confusion, let's rename the method in order to make sure that its name is not an exact match with its parameter, so this is how it should look like:
public String makeGuess(int guess)
avoid naming different entities in the same name space with the exact same name (local variables being present in different methods or parameters having similar names with data members for the purpose of initialization are an exception). From now on, you will call the method as makeGuess(25), for example.
Now, to the actual problem. You have an incorrect assumption. You assume that you need to keep track of past intervals. That's not the case. You can just change the edges of the intervals. Also, your code is superfluous, I advise you to refactor it. Finally, you always initialize upper bounds, local bounds and higher and lower guesses as local variables, so they will never be kept track of. Instead of this, you need to perform the following simple measures in order to make this work:
Define the bounds and limit as data members
protected int lowerBound = 0;
protected int higherBound = 99;
protected int lb = 0;
protected int hb = 99;
protected int limit = 5;
protected int guessCount = 0;
protected int randomizedNumber; //Initialize this somewhere
Note that I have hard-coded some values. You might want to make this dynamic with initialization and stuff like that, but that's outside the scope of the answer. lowerBound, higherBound, limit are game settings. while lb, hb, guessCount represent the game state. You could separate this logic into another class, but for the sake of simplicity, even though I would program differently, I will leave them here in this case.
Have a method that initializes the game
public void initialize() {
lb = lowerBound;
hb = higherBound;
guessCount = 0;
}
So you separate your concern of game initialization from the outer logic of starting and maintaining a game.
Implement makeGuess in a simplistic way
public String makeGuess(int guess) {
if (++guessCount >= limit) return "The game is over.";
else if ((lb > guess) || (hb < guess)) return "The guess doesn't make sense";
else if (randomizedNumber == guess) return "You won.";
else if (guess < randomizedNumber) {
hb = guess;
return "The random number is smaller.";
} else {
lb = guess;
return "The random number is larger.";
}
}
NOTE: I dislike mixing up the logic with the output layer, the reason I did it in the method above was that you have mentioned you are a beginner and my intention is to make this answer understandable for the person who just begun programming and is very confused. For the purpose of actual solutions, you should return a state and in a different layer process that state and perform the console/UI operations you need. I will not go through the details now, as it would also be outside of scope, but for now, please have some success with the solution above, but THEN you should DEFINITELY look into how you need to code, because that is almost as important as making your code work.

Health counter for game

I am having an issue with a health counter in my battleship game. What I need is that when the method is called, it will take 1 off of health. So let's say that the health is at 3, the method is called when the players ship takes a hit. Then I need it to go health-1, and keep that value. Then when the health=0, the game will end.
Any questions and improvements to this code is welcome, as well as criticism.
UPDATED:
public static void enemyShoot (int row, int col)
{
int shot1;
int shot2;
int health = 3;
Random enemyshot = new Random();
shot1 = enemyshot.nextInt(5)+1;
shot2 = enemyshot.nextInt(5)+1;
if (shot1 == row && shot2 == col)
{
System.out.println("You Have Been Hit");
health = Health(health);
}
}
public static int Health (int health)
{
if (health == 0){
System.out.println("You dead");
System.exit(0);
}
health = health-1;
return health;
}
You are initializing health to 0
int health = 0;
Then when your shot hits the target you
Health(health);
Which subtracts 1 and then tests for 0
health = health-1;
if (health == 0)
your health is now at -1 so it never == 0
You should set health to some positive value and or change your test to
if (health <= 0)
When you pass health as a parameter to Health method, it makes a copy to use in this method. So, when you decrement and analyse it, the copy gets decremented to 2 (if you initially passed 3), but the original variable is still equal to 3. So, in fact, the health counter is never decremented.
It's called "passing argument by value", you can check out this question: What's the difference between passing by reference vs. passing by value?
The right thing to do is to decrement the value inside your method and then return the result. You should also call your method like this:
health = Health(health);
Also, arsendavtyan91 is right, you start with health = 0... you might want to pass the actual value to the method enemyShoot
You were close with your Health method, what you would want is something like this:
public static void hit() {
this.health--;
if (health <= 0) {
System.out.println("You died.");
System.exit(0);
}
}
Java is a pass-by-reference so you need to update the health of the object that just got hit. In this case I am assuming your Health() is inside of that object.
Otherwise you start with your health = 3; and every time it gets hit it will become health = 2; but the object that is being hit will always stay at 3 health. Again, without seeing any more of your code I can't tell exactly the best way to do this, so I had to assume a few things.
It should be noted that this will exit the program very quickly and you won't even see the You died message.
You need not subtract if health is equal to zero.
The game will continue since you always initialize health on the line int health = 3; in the enemyShoot() method, right before going to call the Health() method.
So I suggest you declare health inside the class (like a global variable) and initialise it by passing it to the a constructor like this:
int health;
public ClassName(int health){//this is a constructor with the `health` argument
this.health = health;
}
public static void enemyShoot (int row, int col)
{
int shot1;
int shot2;
Random enemyshot = new Random();
shot1 = enemyshot.nextInt(5)+1;
shot2 = enemyshot.nextInt(5)+1;
if (shot1 == row && shot2 == col)
{
System.out.println("You Have Been Hit");
health = Health(health);
}
}
public static int Health (int health)
{
if (health == 0){
System.out.println("You dead");
System.exit(0);
}
health = health-1;
return health;
}
First, you should really read more about the basics of object oriented programming. My answer is based on that little snippet of code you provided, so I'm not sure if there already is a proper implementation...
However, I think what you want is to create a Battleship Object, which has initial health as a member variable. You could define coordinates, orientation etc with parameters, but I'll leave them out from this example. After you have managed to create this object, use enemyShoot method to calculate if battleship has been hit and decrease health that is the case. Which comes out something like this:
public class Battleship {
int m_health;
public BattleShip() {
m_health = 3;
}
public enemyShoot(int x, int y) {
// TODO: calculate if hit
if (hit == true) {
m_health--;
if (m_health == 0)
System.out.println("You dead");
System.exit(0);
}
}
}
So to use the code above I would put it in a file called Battleship.java and create a main method which would initialize the objects I wish to use
public static void main(String ... args) {
Battleship bs = new Battleship(); // <-- Creates a new Battleship object
bs.enemyShoot(0,0); // <-- shoot the battleship
bs.enemyShoot(0,0);
bs.enemyShoot(0,0); // <--At this point battleship would be destroyed, if hit
}
The problem with the Health method you provide is that is takes primitive data type int as parameter (initially set as 0) which gets assigned -1 every time Health is called. Callign this method does not have affect on health value inside enemyShoot method, since this is NOT an Object but a inner method variable of primitive data type.
Hope this helps you to get on with your assignment. :)

while loop not ending when required

So some background information, I'm new to programming and am still learning, so I apologize for my trivial error making. I am making my own text based game just to further practice etc.
Here is the link to everything on dropbox for more context:
https://www.dropbox.com/sh/uxy7vafzt3fwikf/B-FQ3VXfsR
I am currently trying to implement the combat system for my game, and I am running into the issue of the combat sequence not ending when required. The 'combat sequence' is a while loop as follows:
public void startCombat()
{
inCombat = true;
while(inCombat != false)// && herohealth > 0 && monsterhealth > 0)
{
checkAlive();
heroHitMonster();
checkAlive();
monsterHitHero();
}
attackinghero.setHeroHealth(herohealth);
attackedmonster.setMonsterHealth(monsterhealth);
}
where the checkAlive() method is as follows:
public void checkAlive()
{
if(herohealth <= 0)
{
System.out.println("You have died.");
attackinghero.clearInventory();
inCombat = false;
}
else if(monsterhealth <= 0)
{
System.out.println("You have killed the "+attackedmonster.getmonsterName()+"!");
inCombat = false;
combatlocation.removeMonster(attackedmonster.getmonsterName());
}
else
{
//
}
}
I am trying to get it to end the combat sequence when either the 'hero' or 'monster' health become <= 0,
however it is currently finishing the while loop and therefore producing the result of the hero being hit even if he killed the monster in his first hit.
This is what is currently being 'printed to screen'
rat loses 5 health!
You have killed the rat!
Hero loses 1 health!
Any help is much appreciated, thanks in advance.
checkAlive shouldn't be void it should be Boolean and should return inCombat, and in your function startCombat you should do inCombat=checkAlive();
The while loop will only evaluate after both actions. You need a way to break the loop after the hero hits the monster. I would personally change the checkAlive method to return a boolean, and put the hit methods in if statements in the while loop:
if(checkAlive())
{
heroHitMonster();
}
if(checkAlive())
{
monsterHitHero();
}
You should end the loop at the end of the checkAlive instead of changing the boolean value.
If you killed the monster at first hit, you still execute the monsterHitHero() even, if the monster is killed. The function to hit should be conditioned to the life of heroes/monster.

Given a number, find which numbers below it divide it using recursion

I can't seem to figure this one out. I need to count how many numbers below a given number in which it is divisible.
Here is what I've tried:
public int testing(int x) {
if (x == 0) {
System.out.println("zero");
return x;
}
else if ((x % (x-1)) == 0) {
System.out.println("does this work?");
x--;
}
return testing(x-1);
}
That doesn't work and I don't know where to go from here. Anyone know what to do?
This is what is wrong:
public int testing(int x) {
If you want to make it recursive, you need to pass both the number to test and the number that you are currently checking. The first one will not change through the recursion, the second one will decrement. You cannot do what you express with only one parameter (unless you use a global variable).
This is not a task that should be solved with recursion.
If you MUST use recursion, the simplest way to do it is to have a second parameter, which is essentially an "I have checked until this number". Then you can increase/decrease this (depending on if you start at 0 or the initial number) and call the recursive on that.
Thing is, Java isn't a functional language, so doing all this is actually kind of dumb, so whoever gave you this exercise probably needs a bop on the head.
Your problem is that your expression x % (x - 1) is using the "current" value of x, which decrements on every call to the recursive function. Your condition will be false all the way down to 2 % (2 - 1).
Using a for loop is a much better way to handle this task (and look at the Sieve of Eratosthenes), but if you really have to use recursion (for homework), you'll need to pass in the original value being factored as well as the current value being tried.
You have a problem with your algorithm. Notice the recursion only ends when x == 0, meaning that your function will always return 0 (if it returns at all).
In addition, your algorithm doesn't seem to make any sense. You are basically trying to find all factors of a number, but there's only one parameter, x.
Try to make meaningful names for your variables and the logic will be easier to read/follow.
public int countFactors(int number, int factorToTest, int numFactors)
{
if (factorToTest == 0) // now you are done
return numFactors;
else
// check if factorToTest is a factor of number
// adjust the values appropriately and recurse
}
There is no need to use recursion here. Here's a non-recursive solution:
public int testing(int n) {
int count = 0;
for (int i = 1; i < n; i++)
if (n % i == 0)
count++;
return count;
}
BTW, you should probably call this something other than testing.
Using recursion:
private static int getFactorCount(int num) {
return getFactorCount(num, num - 1);
}
private static int getFactorCount(int num, int factor) {
return factor == 0 ? 0 : (num % factor == 0 ? 1 : 0)
+ getFactorCount(num, factor - 1);
}
public static void main(String[] args) {
System.out.println(getFactorCount(20)); // gives 5
System.out.println(getFactorCount(30)); // gives 7
}

Categories

Resources