Troubles with variable scope outside the for loop - java

So, there is a class Hotel, that contains 20 Rooms in form of a matrix 4x5 (4 floors, 5 rooms on every floor). The class Room has the properties:
floorNumber(int),
roomNumber(int),
numberOfBeds(int),
occupation(boolean)
etc.
For occupation, true means busy, and false means free.
One of methods I have to implement in Hotel is the one that reserves a room
reserve(int floorNumber, int roomNumber)
This method should check if occupation is true or false.
If it is true, then reservation fails, and if it is false, I should set occupation to true, with method
setOccupation(boolean t).
Also, method reserve return boolean (true or false), depending on whether reservation succeeded or not.
In that method, you guess, is problem with scope of one variable.
So there it is:
public boolean reserve(int floorNumber, int roomNumber){
boolean flag = false;
for ( int i = 0; i < 5; i++){
if(rooms[floorNumber][i].getRoomNumber() == roomNumber){//every element in matrix rooms has this property: rooms[floorNumber][some_number_from_1_to_5]
if (rooms[floorNumber][i].getOccupancy() == false){
rooms[floorNumber][i].setOccupancy(true);
flag = true;
}
else
flag = false;
}
}
return flag;
}
The problem is, when I set (in first line) flag to true, function returns true, and when I set flag to false, function returns false.
The reason I have to assign some value to flag in first line is because compiler shows:
Error: variable flag might not have been initialized
So, the problem is that it seems like method never executes code with for loop.
I know that variables defined in loop don't exist outside loop, but those defined outside should change their values in loop.
Like in this question here:
Java - Access variable inside and outside of for-loop

There is a simpler way to accomplish what you want to do. You don't need a boolean flag at all; you can just return true immediately on success or return false if the entire loop executed without finding a room.
public boolean reserve(int floorNumber, int roomNumber){
for (int i = 0; i < 5; i++) {
//every element in matrix rooms has this property:
//rooms[floorNumber][some_number_from_1_to_5]
if (rooms[floorNumber][i].getRoomNumber() == roomNumber){
if (rooms[floorNumber][i].getOccupancy() == false){
rooms[floorNumber][i].setOccupancy(true);
return true;
}
}
}
return false;
}
But if you insist on applying your original approach that uses a flag, then: First give it a value of false (in case no room succeeded). When we find an unoccupied room (successful), set it to true. If we find an occupied room, don't touch the flag value.
public boolean reserve(int floorNumber, int roomNumber){
boolean flag = false;
for (int i = 0; i < 5; i++) {
//every element in matrix rooms has this property:
//rooms[floorNumber][some_number_from_1_to_5]
if (rooms[floorNumber][i].getRoomNumber() == roomNumber){
if (rooms[floorNumber][i].getOccupancy() == false){
rooms[floorNumber][i].setOccupancy(true);
flag = true;
} // else DO NOTHING
}
}
return flag;
}

I found what the problem was.
It was actually index floorNumber in matrix rooms[floorNumber][] that goes from 0 to 3 (there are 4 floors), of course.
But in real life, floor numbers go from 1, and I passed argument to
reserve(int floorNumber,int roomNumber)
without considering that.
So, I just decremented floorNumber by 1 in body of method, and it works now.

Related

poker game straight in java

my problem is that this is sound logic but the execution is incorrect (the submit server won't take it). So I'm trying to check if my hand of 5 cards has a straight (that's 2, 3, 4, ,5 6, etc. numbers in consecutive order) and then if the fifth card is an ace i want it to evaluate as the value 10 so it'd be like 6 7 8 9 A(A has a card value of 1) and this is my current code
public static boolean hasStraight(Card [] cards) {
boolean isTrue = false;
for(int atPos =0; atPos<cards.length-1; atPos++){
Card ogCard = cards[atPos];
Card notOgCard = cards[atPos+1];
if (ogCard.getValue() == (notOgCard.getValue()-1)){
if ((cards[3]).getValue()==9){
if (cards[4].getValue() ==1);
isTrue = true; //accounting for ace in last position
}
else if(ogCard.getValue() == (notOgCard.getValue()-1)){
isTrue = true; //accounting for ace not in first position
}
}
}
return isTrue;
}
this is what I have so far not sure what's next.
Your code seems to be going the wrong way.
First you set isTrue to false, but then set it to true any time the array is in strictly increasing order. Thus, it will resolve as true if just the first two are 1,2.
I would set it to true in the beginning, then make it false if they array is ever not in increasing order.
Your constructions of ifs and else ifs are also...interesting.
The if ((cards[3]).getValue()==9){ line will most likely never run as you want it to, as ogCard.getValue() == (notOgCard.getValue()-1) will not be true (and thus the second if statement will never run) when the ace is in the last position. I would just remove the wrapping if statement, as it doesn't really test anything useful.
Your described method also doesn't handle valid aces not in the last position.
My recommendation would look something like this:
public static boolean hasStraight(Card [] cards) {
boolean isTrue = true;
for(int atPos =0; atPos<cards.length-1; atPos++){
Card ogCard = cards[atPos];
Card notOgCard = cards[atPos+1];
if (! (ogCard.getValue() == (notOgCard.getValue()-1) || (ogCard.getValue()==9&&notOgCard.getValue()==1) ) ) {
isTrue=false;
}
}
return isTrue;
}

Efficient solution to update a variable based on values of several variables

I have an update method which gets called every time the screen refreshes itself.
Inside this method I check the value of about about 50 objects to be zero. If all the values are zero I return a true else false is returned.
This is how I have implemented and want to know if there is a better way to do it.
public boolean update()
{
float totalVel = 0;
for(int i=0; i< this.numOfObjects; i++)
{
totalVel += BagOfWordsAverage[i];
}
if(totalVel == 0)
return true;
return false;
}
Depending on the boolean value returned, the caller of the udpate function allows certain inputs from the user. So if False is returned, the user cannot tap on the screen but in the case of true the user is allowed to do whatever she wants.
BagOfWordsAverage is a float array. I simply add the values of the entire array and check if the total is 0. No item in the array can take a negative value.
Is there a better way to achieve what I want to achieve? The challenge is that if the number of objects increased to 5000 will my method scale? Since this is for an App, speed is very important.
If all the values are zero I return a true else false is returned.
So, as soon you see a non-zero value, you can return false immediately.
If you get out of the loop,
that must mean that everything was zero, and you can return true.
public boolean update()
{
for(int i=0; i< this.numOfObjects; i++)
{
if (BagOfWordsAverage[i] > 0) return false;
}
return true;
}
Btw a better way to iterate over arrays in Java:
public boolean update()
{
for (float value : BagOfWordsAverage)
{
if (value > 0) return false;
}
return true;
}
Also, the naming convention in Java is camelCase for variable names,
so I suggest to rename BagOfWordsAverage to bagOfWordsAverage.
An efficient solution is not to loop at all. You can have a map for every index with a value more than zero. If the map's size is 0, then you know that the array's total is zero.
You didn't post your code structure, but something like this might give you an idea:
Map<Integer, Boolean> moreThanZero = new HashMap<>();
public void someActionOnArray(int index) {
/*
do some action
*/
float value = bagOfWordsAverage[index];
if (value > 0) {
moreThanZero.put(index, true);
}
if (value == 0) {
if (moreThanZero.containsKey(index)) {
moreThanZero.remove(index);
}
}
}
public boolean update() {
return (moreThanZero.size() == 0);
}
Every method that modify the array should check the modified value at the current index. If it's more than zero, mark the index on the map. If it's less than zero, remove it if it exist.
This might cost you some memory if the size of indices with value more than zero is large, but you'll gain speed as you don't have to loop every time you refresh.
One way that you could slightly improve the speed of your method would be to check each value and see if it is zero, and if it isn't, return false immediately. If you make it through the loop without finding any values other than zero, you can return true.
public boolean update()
{
for(int i=0; i< this.numOfObjects; i++)
{
if (BagOfWordsAverage[i] != 0)
{
return false;
}
}
return true;
}
Note that while the actual average case run-time of your function will improve with this change (i.e if there is a nonzero in the middle of the array, your run-time will be O(n/2) rather than O(n)), big-O analysis typically omits all but the highest-order function, and considers things like O(3n), O(n/2) to be simplified to simply O(n), as they are run on linear time.
As far as your question regarding an array of 5000 items, average case would take half the time of your original function, but in the worst case, the speed would be the same. If there are no assumptions we can make about where the possible location of these nonzero numbers would be, there is no other option than to check each index of the array individually.
Hopefully this helps.
You want to return false as soon as you get a non-zero value right? Do something like:
for(int i = 0; i < foo.length; i++) {
if (foo[i] > 0) {
return false;
}
}
return true;

Changing boolean value inside if-statement?

I'm studying for the OCA Java SE7 Associate exam. One of my practice exam questions had the following code snippets:
boolean flag = true;
if (flag = false) {
System.out.println("1");
}
else if (flag) {
System.out.println("2");
}
else if (!flag) {
System.out.println("3");
}
else
System.out.println("4");
Notice the if (flag = false) conditional. The question asked what the output of this snippet would be. All the numbers were provided as answer choices and then there was a choice that said "compiler error," which is what I selected. I was wrong. The output would be 3. I tested in Eclipse and it also came back with 3.
I then tested with
int x = 3;
int y = 1;
if (x = y) {
// whatever
}
and, of course, got an error.
Why can the flag be changed from true to false inside the if-statement, but the value of x can't be changed in the similar scenario? Is it because flag is a boolean type and x is type int? I Googled this, but was unable to find anything.
Because the assignment of x = y doesn't equate to a boolean evaluation.
if is expecting the result of the operation to give either a true or false return.
Something like if ((x = y) == y) would work (the evaluation would return true)
flag = false is an assignment, so it is carried out. After the assignment on the first if, it evaluates to false because it was just set to it. For equality it should have been flag == false, but since it was an assignment, the top if was evaluated to false, and since it was changed to false, when you get to !flag, that passes because flag is no longer true, and it prints 3.
You got an error with if(x = y) because after the assignment, the value couldn't be evaluated as a boolean outcome whereas if(flag = false) can evaluate to boolean after the assignment.
The big thing to remember about high-level languages is that it takes more than one low-level statement to perform the logic of even a simple if, and with the assignment case, there is a minimum of 2 operations going on, first the assignment, then the equality.
if (flag = false) will set the flag variable to false, then check if(flag).
You are suggesting doing if(x = 1) which could set x to 1, but if(x) is not valid.
It would print 3 because the boolean variable is assigned false (and checked for true) then checked for false and finally for !false which is true.

Android compare booleans

I am making a simple app where you have to toggle buttons/booleans trying to guess the correct combination. I was wondering the simplest way to compare the toggles booleans against the "right" combination. For example if user has:
boolean 1: true
boolean 2: false
Boolean 3: true
but the correct combination is:
boolean 1: true
boolean 2: true
Boolean 3: true
I want the user to see a message that says you have 2 out of 3 correct. I have
public void go(View view){
if (bool1 == true && boo12 == true && bool3 == true) {
// do this
} else {
// display the correct amount of booleans the user has correct.
}
}
Create a BitSet for the correct combination (set the bits that correspond to "true", clear the bits that correspond to "false").
When you want to check the user's input, create a BitSet from the buttons that are pressed (set "true", clear "false").
Correctness can be checked with correctValue.equals(usersAttempt).
A count can be obtained by doing usersAttempt.xor(correctValue) then usersAttempt.cardinality() will return the number of incorrect values.
This requires a bare minimal amount of coding. For your example:
// Correct: [true,true,true]
BitSet correct = new BitSet(3);
correct.set(0); // <= true
correct.set(1); // <= true
correct.set(2); // <= true
// User's attempt (buttonN.isChecked() is just placeholder, drop in whatever
// code you actually use to get the state of your buttons):
BitSet attempt = new BitSet(3);
attempt.set(0, button0.isChecked()); // <= true in your example
attempt.set(1, button1.isChecked()); // <= false in your example
attempt.set(2, button2.isChecked()); // <= true in your example
// Check answer (produces false in your example):
boolean matchIsPerfect = attempt.equals(correct);
// Get the count (produces 1 in your example):
attempt.xor(correct);
int incorrectCount = attempt.cardinality();
// To get the correct count just subtract 'incorrectCount' from total.
// Another way to check if attempt is correct is 'if (incorrectCount == 0)'.
// Note that the remaining bits set in 'attempt' after the above xor()
// will correspond to the individual inputs that weren't correct.
This will let you support any size, the code is clear and you don't need to do any of the logic on your own. Note that you can simplify the button -> user's attempt setup if you have an array of buttons or can access user input given an index.
If the conditions are not always to be true, say bool3 needs to be false, you can use something like this maybe. Otherwise, as the other answers mentioned, an array would work best probably.
int correctCount = 0;
if (bool1) correctCount++;
if (bool2) correctCount++;
if (!bool3) correctCount++;
if (correctCount == 3) {
// do this
} else {
Toast.makeText(context, String.valueOf(correctCount) + " out of 3 correct", Toast.LENGTH_LONG).show();
}
Assuming that your "right" combination will include both true and false values, the following method will return the number of matches, or -1 if the array lengths don't match:
private int getMatches(boolean[] toggleValues, boolean[] matchPattern)
{
if(toggleValues.length != matchPattern.length)
return -1;
int matches = 0;
for (int j = 0; j < toggleValues.length; j++)
{
if(toggleValues[j] == matchPattern[j])
{
matches++;
}
}
return matches;
}
As an example, if you have 3 ToggleButtons, tb1, tb2, and tb3, the following will return 2:
tb1.setChecked(true);
tb2.setChecked(false);
tb3.setChecked(false);
final boolean[] matchPattern = {true, false, true};
final boolean[] toggleValues = {tb1.isChecked(), tb2.isChecked(), tb3.isChecked()};
int matches = getMatches(toggleValues, matchPattern);
This method will allow you to easily change the matching pattern without changing code, e.g by reading stored values into the matchPattern array from a file or SharedPreferences.
you can do it, as the number of boolean values can be more than 3. you may want to use for loop (easy way) and iterate it for the end of the value and return the number of counts to the value k. here k-> number of true boolean values and b is an array containing the array of boolean values.
public void go(View view){
boolean b[]={bool1,bool2,bool3,bool4,bool5,bool6,bool7,bool8,bool9,bool10};
int k=0;
for(int i=0;i<b.length;i++)
{
if(b[i]==true)
{
k++;
}
}
if(k==b.length)
{
do task
}
else
{
Toast.makeText(getApplicationContext(), k+ "out of "+b.length+ "correct",Toast.LENGTH_LONG).show();
}
}

Why is this while loop infinite?

int MATCH_LENGTH = 0;
int FINAL_MATCH_LENGTH = 0;
int FINAL_MATCH_POS = 0;
while (window.contains(next)) {
int MATCH_POS = window.indexOf(next);
boolean nextMatches = true;
while (nextMatches = true) {
int index = window.indexOf(next);
index++;
int positionOfNext = fileArray.indexOf(next);
positionOfNext++;
MATCH_LENGTH++;
char afterNext = fileArray.get(positionOfNext);
char afterNextInWindow = window.get(index);
if (afterNext != afterNextInWindow) {
nextMatches = false;
if (MATCH_LENGTH > FINAL_MATCH_LENGTH) {
FINAL_MATCH_POS = MATCH_POS;
FINAL_MATCH_LENGTH = MATCH_LENGTH;
MATCH_LENGTH = 0;
}
window.remove(window.indexOf(next));
}
}
}
I am running into an infinite loop here. I think it is because of the nextMatches boolean variable. However, I am not sure how that affects the program, as I have the condition for the while loop as while (window.contains(next)). However, I am removing the occurrences of next one by one, so eventually while (window.contains(next)) will have to return false and the while loop will have to break. My reasoning here might be flawed though with the remove line window.remove(window.indexOf(next));.
Or is some other part of my reasoning flawed?
You made the classic = vs == mistake
while (nextMatches = true)
should be
while(nextMatches)
As a general rule, don't compare booleans to true and false. It just leads to these sort of weird bugs and makes the code less legible in my opinion. If you name your variables properly, Java conventions has booleans sound like a conditional. For example: isEmpty or isFull. This way things read like english: while(isFull)
I'm a bit confused on your logic, especially since int index = window.indexof(next) will not change anything. index will be redefined.
The problem is here while (nextMatches = true) try put instead
while (nextMatches == true)
I found the problem. It was this line: int index = window.indexOf(next);.
I kept on redefining index as the same number over and over again, which caused the infinite loop. Problem solved!
while (nextMatches == true) {
This condition will be false iff nextMatches is assigned with false.
The only place you are assigning it false, is in following code block:
if (afterNext != afterNextInWindow) {
nextMatches = false;
...
Since, while is running infinite for you, it means nextMatches is never assigned with false when code executes, i.e if condition is always false.
This means, that in every iteration of while; afterNext is always equals to afterNextInWindow.

Categories