I have looked at other do while issues on StackOverflow, but I could not find the solution to my issue. I have variables initialized outside the do{ and they are being use within, but when the variables reach a certain value, the while method does not jump out.
Here is what I have:
int aiShotHit = 0;
int shotHit = 0;
do{
showBoard(board);
bAi.showAi(ai);
shoot(shoot,ships);
bAi.aiHit(aiShoot);
attempts++;
if(hit(shoot,ships)){
hint(shoot,ships,aiShips,attempts);
shotHit++;
System.out.println("\nShips Left on the Board: " + shotHit);
}
else
hint(shoot,ships,aiShips,attempts);
changeboard(shoot,ships,board);
if(bAi.aiHit(aiShoot,aiShips)){
hint(shoot,ships,aiShips,attempts);
aiShotHit++;
}
else
System.out.print("");
bAi.changeAi(aiShoot,aiShips,ai);
}while(shotHit !=3 || aiShotHit !=3);
if (shotHit == 3){
System.out.println("\n\n\nBattleship Java game finished! You Beat the Computer");
}
System.out.print("You lost! The Ai beat you");
You probably started out by saying, I want this to loop until shotHit is 3 or until aiHShotHit is 3.
That would be
while (!(shotHit == 3 || aiShotHit == 3));
which is "loop while it is not the case that either shotHit or aiShotHit contains the value 3", but it's kind of ugly so you wanted to apply the negation operator to each subexpression and get rid of some parens. The mistake was thinking you can move the negation operator without changing anything else to get
while (shotHit != 3 || aiShotHit != 3);
This exits the loop only in the event that shotHit is 3 at the same time that aiShotHit is 3. Not what you want.
The correct transformation is
while (shotHit != 3 && aiShotHit != 3);
This much was covered in the comments. The guidelines for how to safely transform this kind of expression are De Morgan's rules, which describe how to transform conjunctions and disjunctions in terms of each other. Following those rules lets you can move the negation operator and change the parenthesization without changing the meaning of the expression:
"not (A or B)" is the same as "(not A) and (not B)"
"not (A and B)" is the same as "(not A) or (not B)"
Needing to reorganize an expression to make it more readable comes up a lot in programming and this is a tool you need in order to do it safely. If you want to know more about De Morgan's rules you might want to read this answer.
Related
I'm running my code on sonarqube, but it shows there's an issue with my code, saying"Merge this if statement with the enclosing one." I tried it, but still have no idea how to solve it.
if (splitStrings.length == 2) {
if (!splitStrings[1].matches("\\d{1,3}")
|| Integer.parseInt(splitStrings[1]) > 100
|| Integer.parseInt(splitStrings[1]) < 1) {
throw new IllegalArgumentException("Invalid Input");
}
}
You could do three things:
Either you need to chain the conditions as below:
if (splitStrings.length == 2
&& (!splitStrings[1].matches("\\d{1,3}")
|| Integer.parseInt(splitStrings[1]) > 100
|| Integer.parseInt(splitStrings[1]) < 1)) {
throw new IllegalArgumentException("Invalid Input");
}
You could declare local variable for Integer.parseInt(splitStrings[1]) inside the first if after adding the matches condition in it.
if (splitStrings.length == 2 && splitStrings[1].matches("\\d{1,3}")) {
int val = Integer.parseInt(splitStrings[1]);
if (val > 100 || val < 1)) {
throw new IllegalArgumentException("Invalid Input");
}
}
Even though i won't recommend it, you could also suppress the warning using //NOSONAR in the line in which warning is displayed or add #SuppressWarnings("squid:S1066") at the method level.
Try this.
if (splitStrings.length == 2
&& (!splitStrings[1].matches("\\d{1,3}")
|| Integer.parseInt(splitStrings[1]) > 100
|| Integer.parseInt(splitStrings[1]) < 1)) {
throw new IllegalArgumentException("Invalid Input");
}
You should merge them by && between them and wrap the second with brackets, like:
if(splitStrings.length == 2 && (!splitStrings[1].matches("\\d{1,3}") || Integer.parseInt(splitStrings[1]) > 100 || Integer.parseInt(splitStrings[1]) < 1)){
//code here
}
Integer.parseInt may be skipped altogether if a better regexp is provided to check for the digits in the range [1..100], thus the conditions could be simplified:
if (splitStrings.length == 2 && !splitStrings[1].matches("(?!0)\\d{1,2}|100")) {
throw new IllegalArgumentException("Invalid Input");
}
Online demo of the regexp: (?!0)\d{1,2}|100 validating positive cases 0 < x <= 100
(?!0)\d{1,2} - 1 or 2 digit numbers except 0 excluded with negative lookahead (?!0): 1 - 99
|100 - OR 100
In my opinion the assertion that combining if statements makes code more readable is flawed. Often it makes sense to ask a series of questions in sequence, especially when each part is asking an essentially independent question.
This can (in direct opposition of the SonarQube assertion) make each part more readable. It also allows for correct placement of useful comments in cases where the meaning is not stupidly obvious.
Another valid reason for nested if statements would be to follow certain easily recognized coding patterns. An example would be in ASP.Net applications where Page_Load methods may often have an if (!PostBack) block, which can then contain additional logic that may include additional nested conditions. If there is only one nested condition and it is combined, later changes may need to undo that merge. (There may be a case at that point for refactoring the logic into a separate method at that point, but that is a different subject.)
The question of whether or not to combine nested if statements should be left to the discretion and good judgement of the author (and code reviewer) based on which form is more readable and/or maintainable.
In your particular case, your logic is asking two questions: (1) "Does the input have two parts?" and (2) "Is the second part valid"?
So yes, your nested if statements can be combined into a single (but logically more complex) statement, but this is not necessarily better.
case "119":
PotionsUpgrade();
if(potionAttack & potionDefence & potionStrength==20){
System.out.println("You have reached the max amount of upgrades");} else{
cost=potionsUpgrade;
gold=gold-cost;}
Store(); //this is running the Store method
break;
okay this is one of my cases in my game that i am building in java. I want to figure out how to check if all three of the numbers equal 20 then to tell the player that he has reached the max amount of upgrades on the potion. Else to keep buying the upgrade.
This isn't doing what you think:
if (potionAttack & potionDefence & potionStrength==20) {
You have to be pretty specific with code, it's not going to interpret something that may intuitively sound logical. It has to be specifically logical. In this case you have three distinct logical cases you want to check. Each one individually looks like:
potionAttack == 20
So to put all three together, each one would still look like that individually:
if (potionAttack == 20 && potionDefence == 20 && potionStrength == 20) {
(Note also the use of && instead of &. Different problem in the code, but not the primary one being addressed here.)
`if(potionAttack == 20 & potionDefence == 20 & potionStrength == 20)`
The oher is the same ,but you can format it better like this
`if(potionAttack == 20 & potionDefence == 20 & potionStrength == 20){
System.out.println("You have reached the max amount of upgrades");
}
else{
cost = potionsUpgrade;
gold = gold - cost;
}`
You are using & instead of the logical and operator, &&.
I'm studying for my computer science final and am going back over some of the things that I never quite grasped when we went over them in class. The main thing being recursion. I think I've got the hang of the simple recursion example but am trying to work through one that was on a previous exam and am having trouble figuring out how it should be done.
Here is the question:
Texas numbers (Tx(n)) are defined as follows for non-negative numbers (assume true):
Tx(n) = 10 if n is 0
Tx(n) = 5 if n is 1
Tx(n) = 2*(Tx(n-1) + Tx(n-2) if n >= 2
We are then to write the recursion function for Texas numbers, after making some corrections after the test, here's what I've come up with, I think it's right, but not 100% sure.
public int Tx(int n) {
if(n == 0)
return 10;
else if (n == 1)
return 5;
else
return 2*(Tx(n-1) + Tx(n-2));
}
Then we are asked to computer the value of Tx(5). This is where I'm stuck. If the return statement for the else was simply n-1, I think I'd be able to figure it out, but the n-1 + n-2 is completely throwing me off.
Can anyone explain how this would work, or share some links that have similar examples. I have tried looking this up online and in my textbook but the examples I've found are either so advanced that I have no clue what's going on, or they only deal with something like return n-1, which I already know how to do.
Let's start with Tx(2). n > 1, so we have 2*(Tx(n-1) + Tx(n-2)) which is 2*(Tx(1) + Tx(0)).
But we already know Tx(1) and Tx(0)! So just substitute them in and you get 2*(5 + 10) -> 30. Great, so now we know T(2).
What about T(3)? 2*(Tx(2) + Tx(1)). Nice, we already know these too :) Again, just fill them in to get 2*(30 + 5) -> 70.
You can work forwards to get to Tx(5).
Your code is logically correct, you should just be using == to test equality, a single = is for assignment.
When you run your method, it will work backwards and solve smaller and smaller subproblems until it gets to a point where the answer is known, these are your base cases.
Tx(3)
2* Tx(2) + Tx(1)
2*Tx(1) + Tx(0) (5)
(5) (10)
In order for recursion to work, whatever you are doing each time to break the problem down into smaller problems needs to make some progress towards the base case. If it doesn't, you will just infinitely recurse until your computer runs out of space to store all of the repeated calls to the same function.
public int Tx(int n) {
if(n == 0)
return 10;
else
return Tx(n+1); // n will never reach 0!
}
Tx(1) becomes Tx(2) -> Tx(3) -> Tx(4) -> Tx(5) etc.
Your implementation is good, only one minor mistake - in the conditions you should replace = with == - it's not an assignment - it's a comparison.
By the way, what would you expect your method to return for Tx(-1) ?
You have implemented it right just change = with ==.
If you want to further reduce the time complexity you can store the result in an array global to the function so that your function doesnot compute results again and again for a same number this will only save you some time for large computations.
You can use something like this.
public int tx(int n , int []arr) {
if (arr[n] == 0) {
if (n == 1) {
arr[n] = 10;
}
else if (n == 2) {
arr[n] = 5;
}
else {
arr[n] = 2 * (tx((n - 1), arr) + tx((n - 2), arr));
}
}
return arr[n];
}
See whenever you ask the computer for the value Tx(5) it will call the recursive function and so the program will execute the else part because value of n=5.
Now in the else part 2*(Tx(n-1)+Tx(n-2)) will be executed.
In first iteration it will become 2*((2*(Tx(3)+Tx(2)))+(2*(Tx(2)+Tx(1)))) . The iteration will be continued until the value of n become 0 or 1.
Okay, I'm making this new game in Java. This might be a simple question, but can anyone please help me with this?
So, if the "Guy" collides with the platforms, he can't move right (obviously).
This is what I got:
if(Guy.x + Guy.width == (platform2.x ^ platform3.x)) {} else{
goRight();
}
The "^" is supposed to be "or".
I have a void called goRight();
so it would be like "if Guy's x plus Guy's width is the same as platform2 or platform3's x then go right. I don't want to have to do this:
if(Guy.x + Guy.width == platform2.x || Guy.x + Guy.width == platform3.x)) {} else{
goRight();
}
And plus, I have like 20 more platforms so it would be easier the first way if it's possible.
And I have to make the left collision detection too.
You will have to repeat the conditions.
One (better) solution would be to create a collection with your x variables and using the .contains() method on it. That would make your code a lot more readable.
Alternatively, put all your platforms in a collection, loop over it and check each value's x variable.
You need some more advanced structures to store information about your platforms. Consider having a Set of the x-coordinates of your platforms and performing the operation 'contains`
for example:
Set<Integer> xcoords = new HashSet<Integer>();
xcoords.add(platform2.x);
xcoords.add(platform3.x);
if (xcoords.contains(Guy.x + Guy.width)){
} else {
goRight();
}
If Platform is a class that has an x value, then I'd suggest putting put all of your platforms into a collection of some kind and iterating over it. Inside a loop, do something like
for(Platform p: platforms){
if(Guy.getX() + Guy.getWidth() == p.getX()){
//whatever
}else{
goRight()
}
}
That's the way the language is designed... So it is useless to fight against it.
All you can do is use auxiliary variables to shorten the expressions. But you will always have to right something like if(a == b || a == c).
OK so I seem to be getting an Array Index out of Bounds error in a part of my code. Specifically in lines 85-102...
My code: http://www.sosos.pastebin.com/f0JQBWui
I just want it to check for blocked tiles AHEAD of time that way my sprite doesn't move in the direction it can't. This exception only happens when I am on the RIGHT or BOTTOM corners of my map.
My GUESS of why this error happens if because when I am on the corner.. it checks for the tiles to the RIGHT and BOTTOM of it which are not there...
1) The way you implemented blocked(tx,ty), it only accepts legal board coordinates (0<=tx<=12 and 0<=ty<=8). Otherwise it checks an illegal array position, producing an ArrayIndexOutOfBoundsException. Are you sure this is your intention? I think it makes sense to consider off board tiles as blocked.
2) In lines 85-102 there seems to be many errors. I think you meant something like:
if (spawnX == 0 || blocked(spawnX - 1, spawnY)) {
left = false;
System.out.println("You can't go left!");
}
if (spawnX == 12 || blocked(spawnX + 1, spawnY)) {
right = false;
System.out.println("You can't go right!");
}
if (spawnY ==0 || blocked(spawnX, spawnY - 1)) {
up = false;
System.out.println("You can't go up!");
}
if (spawnY == 8 || blocked(spawnX, spawnY + 1)) {
down = false;
System.out.println("You can't go down!");
}
Anyway, if you fix (1) as I suggested, the extra bound condition per direction is unecessary.
3) isInBound(r,c) is implemented incorrectly. It always returns false, due to the conditions on c.
4) There are many other problems with the code, but I will not enter into details. As a principle, try to make your design simple and make sure the code does not repeat itself.
You're going to have to do some bounds-checking in your blocked() function. Make sure that the coordinates they're giving you actually exist and return some "blocked" value if they don't.
The description of getting the error at the bottom or right would seem to suggest that you need to test if the value exceeds the array bounds. Have a look at Array.length