Java if statement checking [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I'm making a terrible 2D remake of Minecraft as a class project in java, and I have a crafting bench thing (or whatever it's called) and I have an if statement that checks if you have one piece of wood in the top left and nothing in the other 3, or if you have one piece of wood in the top right and nothing in the other 3, and so on...
The following if statement which I'm using seems to let you have a "wood" block in multiple slots at the same time and still lets you get the "plank" block. (id1 - id4 represent the crafting bench slots) 2x2 crafting bench Tile.wood is a wood block, Tile.blank is basically a null block or nothing.
//this if statement is what I need to change maybe?
if ((id1.id == Tile.wood && id2.id == Tile.blank
&& id3.id == Tile.blank && id4.id == Tile.blank) ||
(id1.id == Tile.blank && id2.id == Tile.wood
&& id3.id == Tile.blank && id4.id == Tile.blank) ||
(id1.id == Tile.blank && id2.id == Tile.blank
&& id3.id == Tile.wood && id4.id == Tile.blank) ||
(id1.id == Tile.blank && id2.id == Tile.blank
&& id3.id == Tile.blank && id4.id == Tile.wood)) {
//this code I don't need to change, it works fine
Inventory.inv_result.id = Tile.plank;
Inventory.inv_result.blockNum += 4;
System.out.println("You can have 4 planks");
}
So once again you should only be allowed to have one block in one place at one time, otherwise it will do nothing.
How can I fix it so I only get the "plank" block if there is only a single "wood" block in one of the four slots?

The if-condition looks untidy but will work perfectly fine. However, you can modularize it for better understanding & debugging.
Create few utility methods to do jobs for you, as below:
boolean isWood(<id object>) {
if(Tile.wood.equals(<id object>))
return true;
else
return false;
}
boolean isBlank(<id object>) {
if(Tile.blank.equals(<id object>))
return true;
else
return false;
}
void doProcess(){
Inventory.inv_result.id = Tile.plank;
Inventory.inv_result.blockNum += 4;
System.out.println("You can have 4 planks");
}
Then re-write your if-condition like below
if(isWood(id1.id) && isBlank(id2.id) && isBlank(id3.id) && isBlank(id4.id))
doProcess();
else if(isWood(id2.id) && isBlank(id1.id) && isBlank(id3.id) && isBlank(id4.id))
doProcess();
else if(isWood(id3.id) && isBlank(id2.id) && isBlank(id1.id) && isBlank(id4.id))
doProcess();
else if(isWood(id4.id) && isBlank(id2.id) && isBlank(id3.id) && isBlank(id1.id))
doProcess();
Shishir

i think if statement is ok even though it is so long. Try to use .equal() instead of == in the if statement.

The problem you have with your if-condition has nothing to do with the if-condition but some other part of your crafting bench code. You should post your crafting bench code for us to find the actual problem.
Besides about the untidiness and stuff...
This may not be the answer to your question but this will definitely make it easier for you to do many recipes:
// These are your function calls. One line per recipe. Way better than multiple if functions
// example for shaped crafting using minecraft's crafting bench recipe.
shapedCrafting(new int[]{Tile.plank, Tile.plank, Tile.plank, Tile.plank}, 4, Tile.plank);
// example for shapeless crafting using your recipe
shapelessCrafting(new int[]{Tile.plank}, 4, Tile.plank);
This would be an example of your crafting bench with an array instead of variables:
// This array resembles your crafting bench grid (2x2) in this case.
public static int[] arrayCraftingSlots = {Tile.plank, 0, 0, Tile.wood};
The function for shaped crafting:
/* int elements[] - takes in the crafting layout (this should equal your crafting bench grid)
* int amount - the amount of the item or tile you get as a result
* int result - the id of the result you get
*/
public static void shapedCrafting(int elements[], int amount, int result)
{
for(int i = 0; i < elements.length; i++)
{
if(arrayCraftingSlots[i] != elements[i])
{
return;
}
}
Inventory.inv_result.id = result;
Inventory.inv_result.blockNum += amount;
System.out.println("You can have " + amount + " " + result);
}
And the function for shapeless crafting:
I've restricted this one to 1 instance of an item per recipe just like in Minecraft. So using 2 planks in one shapeless recipe would not be possible. Of course you can change that if you want to. Keep in mind you have to change a bit of the algorithm as well.
/* int elements[] - list of elements that need to be anywhere in the crafting bench
* int amount - the amount of the item or tile you get as a result
* int result - the id of the result you get
*/
public static void shapelessCrafting(int elements[], int amount, int result)
{
for(int element : arrayCraftingSlots)
{
boolean in = false;
for(int i = 0; i < elements.length; i++)
{
if(element == elements[i] || element == 0)
{
in = true;
}
}
if(!in)
{
return;
}
}
for(int element : elements)
{
int occassions = 0;
for(int i = 0; i < arrayCraftingSlots.length; i++)
{
if(element == arrayCraftingSlots[i])
{
occassions++;
}
}
if(occassions > 1 || occassions == 0)
{
return;
}
}
Inventory.inv_result.id = result;
Inventory.inv_result.blockNum += amount;
System.out.println("You can have " + amount + " " + result);
}

Related

Converting code python to Java that finds the minimum number of steps to get to 1

In this foobar coding question, you're supposed to return the minimum number of steps to get from the given String to the number 1. For example, with the parameter "15", the method would return 4. With the parameter 4, the method would return 2.
I've found the solution in python and was trying to convert to Java, but the Java code does not pass half of the secret tests(I do not know what[enter image description here] the test cases are) while the python code passes the tests. This is the python code:`
def solution(n):
n=int(n)
res = 0
while(n!=1):
if(n%2==0):
n=n/2
elif((n==3) or ((n+1)&n) > ((n-1)&(n-2))):
n-=1
else:
n+=1
res+=1
return res
` code passes are the cases. My question was trying to figure out what I'm doing wrong in my Java code. This is the Java code:
public static int solution(String x) {
int counter = 0;
int number = Integer.parseInt(x);
while(number != 1) {
if(number%2 == 0) {
number = number/2;
}
//else if(number == 3 || number%4 == 1) {
else if((number == 3) || ((number +1)&number) > ((number-1)&(number-2))) {
number-=1;
}
else {
number+=1;
}
counter+=1;
}
return counter;
}
`.

If-else with two possible ways

Could you please help me find a solution for my code? I'm making a new Android app in which I need to make some calculations and the scenario is the following:
There are four fields to be calculated. Two EditText (number decimal) field are obligatory and the other two are optional, BUT, if the optional fields are filled, then it needs to be in the calculation, otherwise only the obligatory fields will be used.
Right now I'm totally OK with calculating the obligatory fields but when I try some if-else clause to include the optional fields in the calculation, the app goes bananas.
I'm not sure where I should make this two-step option, if I should use boolean to check the option field condition, if I just keep using if-else...
The problem is not the calculatin itself, but having two ways for the code to follow: One using only the obligatory fields if nothing else is inserted and the other one using all four fields.
Thanks everyone!
Code below is only using the two obligatory fields.
public void calcularResultado(View view) {
//check for blank values in obligatory fields
if (editGasolina.length() == 0) {
editGasolina.setError("Insira o valor");
}
if (editEtanol.length() == 0) {
editEtanol.setError("Insira o valor");
//runs the code
} else {
double valorGasolina = Double.parseDouble(editGasolina.getText().toString());
double valorEtanol = Double.parseDouble(editEtanol.getText().toString());
double valorResultado = valorEtanol / valorGasolina;
double porcentagem = (valorResultado) * 100;
String valorResultadoTexto = Double.toString(porcentagem);
valorResultadoTexto = String.format("%.2f", porcentagem);
if (valorResultado >= 0.7) {
textResultado.setText("GASOLINA");
textRendimento.setText(valorResultadoTexto + "%");
} else {
textResultado.setText("ETANOL");
textRendimento.setText(valorResultadoTexto + "%");
}
You almost got it. What happens now, since you have an if-if-elseconstruction, it considers the first if statement to be seperate from the if-else block below. That is to say, if editEtanol.length() == 0 evaluates to false, it will execute the else block below, even if editGasolina.length() == 0 evaluates to true.
Changing the line if (editEtanol.length() == 0) { to else if (editEtanol.length() == 0) { should already help alot. Hope that helps!
public void calcularResultado(View view) {
//check for blank values in obligatory fields
if (editGasolina.length() == 0) {
editGasolina.setError("Insira o valor");
}
if (editEtanol.length() == 0) {
editEtanol.setError("Insira o valor");
//runs the code
} else {
double valorGasolina = Double.parseDouble(editGasolina.getText().toString());
double valorEtanol = Double.parseDouble(editEtanol.getText().toString());
boolean optionalField1Used = optionalEditText1.length() != 0;
boolean optionalField2Used = optionalEditText2.length() != 0;
double valorResultado = 0;
if (!optionalField1Used && !optionalField2Used) {
valorResultado = valorEtanol / valorGasolina;
} else if (optionalField1Used && !optionalField2Used) {
valorResultado = //some other calculation
} else if (!optionalField1Used && optionalField2Used) {
valorResultado = //yet another calculation
} else {
valorResultado = //calculation if both optional fields used
}
double porcentagem = (valorResultado) * 100;
String valorResultadoTexto = Double.toString(porcentagem);
valorResultadoTexto = String.format("%.2f", porcentagem);
if (valorResultado >= 0.7) {
textResultado.setText("GASOLINA");
textRendimento.setText(valorResultadoTexto + "%");
} else {
textResultado.setText("ETANOL");
textRendimento.setText(valorResultadoTexto + "%");
}
Let us assume that the optional fields are called edit1 and edit2. I also assume that in order to use the alternative computation, both optional values must be present.
To enhance code clarity, I would define two Boolean variables to explicitly indicate whether the mandatory and optional fields have values. Something like the following.
public void calcularResultado(View view) {
var mandatoryValues = true;
var optionalValues = false;
if (editGasolina.length() == 0 {
editGasolina.setError("Insira o valor");
mandatoryValues = false;
}
if (editEtanol.length() == 0 {
editEtanol.setError("Insira o valor");
mandatoryValues = false;
}
if (edit1.length() > 0 && edit2.length() > 0) {
optionalValues = true;
}
if (mandatoryValues) {
if (optionalValues) {
// do alternative computation
} else {
// do computation for mandatory values only
}
}
}
Note that if either mandatory value is absent, no computation is performed.
Hope it helps - Carlos

Why are variable changes not persisting a method call?

I'm trying to program a bug to move around an array attached to a custom Room object, whilst keeping count of how many times each tile has been stepped on.
The Room object is working properly, as are the movement and the counting. However, the bug's coordinates, bugX and bugY, are somehow reverting to 0 after exiting the nextMove method. Their values only revert when exiting the method; even the last line of code in the nextMove method itself uses their new values.
Relevant portion of the method is attached, but other sections can be added upon request.
if (dirNum == 0 && bugY < length-1) //Move up
bugY++;
else if (dirNum == 1 && bugX < width-1) //Move right
bugX++;
else if (dirNum == 2 && bugY > 0) //Move down
bugY--;
else if (dirNum == 3 && bugX > 0) //Move left
bugX--;
else {
System.out.println("Error: Cannot move " + direction + ".");
canMove = false;
dirNum = generator.nextInt(4);
continue;
}
This is the context for the command itself.
while (endSim == false) {
nextMove(bugX, bugY);
System.out.print(room.printRoom() + "\n\nNext move? (y/n) ");
simSentinel = in.next();
if (simSentinel.charAt(0) == 'n')
endSim = true;
}
The declarations where the starting coordinates are assigned aren't inside any loops, let alone where the variable itself is called.
The problem is the one described by #T.J.Crowder in his answer though applied to java.
Variables passed as parameters in java are passed by value. If the value is changed by the method receiving the parameter, the change only affects the value inside that method. The "outside" value doesn't change.
What you can do is to encapsulate the coords in an object and pass the encapsulating object as a parameter.
Then the method will receive the object by value, and change it's state (instead of the value of the object).
For a deeper understanding see this question
EDIT I:
I cleand up the code a bit. Though it is is missing the declaration of room and simSentinel, if you add that you should have a running example.
public class Bug{
public int x=0;
public int y=0;
}
public class SimpleSim {
private int dirNum = 0;
private int length = 20;
private int width = 20;
private boolean canMove = true;
private Random generator = new Random();
private boolean endSim = false;
public static void main(String [] args) {
SimpleSim simpleSim = new SimpleSim();
simpleSim.start();
}
private void start() {
Bug myBug = new Bug();
// Give the bug some initial x, y values.
myBug.x = 0;
myBug.y = 0;
while (endSim == false) {
nextMove(myBug);
System.out.print(room.printRoom() + "\n\nNext move? (y/n) ");
simSentinel = in.next();
if (simSentinel.charAt(0) == 'n')
endSim = true;
}
}
}
public void nextMove(Bug bug){
if (dirNum == 0 && bug.y < length-1) //Move up
bug.y++;
else if (dirNum == 1 && bug.x < width-1) //Move right
bug.x++;
else if (dirNum == 2 && bug.y > 0) //Move down
bug.y--;
else if (dirNum == 3 && bug.x > 0) //Move left
bug.x--;
else {
System.out.println("Error: Cannot move " + "?" + ".");
canMove = false;
dirNum = generator.nextInt(4);
}
}
}
It seems that you are passing your bugX and bugY parameters by value. In this case, changing their value inside the method won't affect their values outside the method.
You may want to make your nextMove method return the new values for bugX and bugY after they are computed so that you can gather them back into your actual bugX and bugY variables

How to render sprite array efficiently in j2me game?

I am working on a landscape java game.
I have a sprite array like this;
Sprite stickArray[] = new Sprite[10];
and initializing it like this with visibility as false.
for (int j = 0; j < stickArray.length; j++) {
if (stickArray[j] != null) {
stickArray[j].setPosition(stickX, stickY);
stickArray[j].setVisible(false);
}
}
Later I want to position it like one after another vertically on repeating a key.pressBool is false initially.
public void keyRepeatInGame(int keyCode) {
int gameKey = getGameAction(keyCode);
Graphics g = getGraphics();
if (gameKey == FIRE || keyCode == KEY_NUM5) {
pressBool = true;
}
}
Later I have written code like this;
Initially one Sticksprite is there.above this sprite, I want to place each sticks on clalling keyrepeat()in space key.
for (int i = 0; i < stickArray.length; i++) {
if (pressBool) {
if (i == 0) {
stickArray[i].setPosition(stickSprite.getX(),
stickSprite.getY() - stickSprite.getHeight());
stickArray[i].setVisible(true);
} else {
stickArray[i].setPosition(stickArray[i-1].getX(),
stickArray[i-1].getY() - stickArray[i].getHeight());
stickArray[i].setVisible(true);
}
}
}
This code is working partially.Stick is getting added on the sprite,all at once.
How can I change the code to make the sticks repeatedly getting added on calling keyrepeat() only, and make it visible one by one properly?
I changed the code with an additional condition and break statement like this;
if (pressBool) {
if (stickSprite != null && !stickArray[i].isVisible()
&& stickArray[i] != null) {
if (i == 0) {
stickArray[i].setPosition(
stickSprite.getX(),
stickSprite.getY());
stickArray[i].setVisible(true);
break;
} else if (i > 0) {
stickArray[i].setPosition(
stickArray[i].getX(),
stickArray[i - 1].getY()
- stickArray[i].getHeight());
stickArray[i].setVisible(true);
break;
}
}
}
It worked.

Repeat an increment of loop

For my science fair project, I'm wanting to give a graphical update to a French-teaching program that's so old it's emulated in DosBOX. That's all well and good but I'm having problems. I'm writing the base logic of the program in a console application just to get that together. I've created a Question class that's in a array list/collection known as "test1".
I have a loop that iterates through the list and with each iteration, it runs another method called evaluate:
public static boolean evaluate(Question question, Scanner scanner)
{
System.out.println(question.getPhrase()); // prints the question
String answer = scanner.nextLine(); // gets the answer
if (answer.compareTo(question.getCorrectAnswer()) == 0)
return true; // compares the answer to the correct answer w/i the current instance of "Question"
else
return false; // if it's not right, returns "false" meaning the question wasn't correct
}
The loop looks as such:
for (Question question : test1)
{
if (evaluate(question, scan))
{
incorrect = 0;
continue;
}
else
{
incorrect++;
System.out.println(incorrect);
}
if (incorrect == 3)
System.out.println("you have failed");
break;
}
I want to make it so that if you answer a question incorrectly, it spits out the phrase again and increases "incorrect" by 1 and, if you hit 3, terminates the list (I think I've got this implemented correctly if I could just get it to repeat the question). Right now it moves to the next item in the list and thus the next question even if and I don't want that.
Sorry if my code is awful, I'm still relatively new to programming.
Create a while loop inside of the for loop that says if the question isn't answered correctly, then repeat so that way in each question the question will be asked until its correct. Keep everything inside the for loop in the while loop that you should create:
for (Question question : test1)
{
while(!evaluate(question, scan)) {
if (evaluate(question, scan))
{
incorrect = 0;
continue;
}
else
{
incorrect++;
System.out.println(incorrect);
}
if (incorrect == 3)
System.out.println("you have failed");
break;
}
}
Instead of doing a foreach loop the way you're doing it now, you can do the following:
for (int i = 0; i < test1.size(); i++) {
Question question = test1.get(i);
if (evaluate(question, scan)) {
...
} else {
incorrect++;
test1.add(question);
}
if (incorrect == 3) { ... }
}
This is assuming you're using a data structure that uses size() and add() as methods; you can adjust it to what you're using.
This will repeat questions later, though not immediately after. If you want to repeat it immediately after, just decrement i-- in the else case:
for (int i = 0; i < test1.size(); i++) {
Question question = test1.get(i);
if (evaluate(question, scan)) {
...
} else {
incorrect++;
i--;
}
if (incorrect == 3) { ... }
}
You can also nest a loop for the else case:
for (Question question : test1) {
boolean passed = True;
incorrect = 0;
while (!evaluate(question, scan)) {
incorrect++;
if (incorrect == 3) { passed = False; break; }
}
if (!passed) { System.out.println("you have failed"); break; }
}

Categories