At the moment, I have this:
do{
if (i < y){ //y is a constant
ObsHandler.obsPartsHandler(); //increment i twice
ObsHandler.search();
}
else {
break;
}
} while (!endline.equals(null)); // endline is changed during each loop cycle
With this loop, and the inputs I have, endline can not be null; this renders the while loop breaking condition redundant. When I try and convert this loop to a for loop, I get a misplaced construct error from Eclipse.
i.e:
for (i < y) {
ObsHandler.obsPartsHandler(); //increment i twice
ObsHandler.search(); }
Whilst, the while loop I have works, it seems like bad practice to me.
Any suggestions? Thanks.
If you don't need to check endLine, you can still use a while loop:
while (i < y) {
ObsHandler.obsPartsHandler(); //increment i twice
ObsHandler.search();
}
If you also need to check endLine:
while (i < y && !endline.equals(null)) {
ObsHandler.obsPartsHandler(); //increment i twice
ObsHandler.search();
}
Note: the difference between do / while (your initial code) and while { } is that in the first case the loop is always run at least once. With a while { }, it is not run at all if the condition is not true at the beginning. That is the same behaviour as a for loop (won't run if the condition is false before the loop).
If you want to use a for loop, you need to have all three parts of a standard for. Since you have two conditions, they need to be both included in the condition part:
for ( ; i < y && !endline.equals(null); ) {
ObsHandler.obsPartsHandler();
ObsHandler.search();
}
You probably have some initialization code for i, like i=0, which could also go into the initialization section of the for loop. Otherwise, if all you have is a set of conditions to check without some array or list you are iterating, while or do is really the better fit.
A while loop seems like the natural choice for your code. I would just simplify it to:
do {
ObsHandler.obsPartsHandler(); //increment i twice
ObsHandler.search();
} while (i < y && !endline.equals(null)); // endline is changed during each loop cycle
or, if you need to check the conditions before:
while (i < y && !endline.equals(null)) {
ObsHandler.obsPartsHandler(); //increment i twice
ObsHandler.search();
}
for (boolean start=true;(start || endline != null) && i < y;){
start=false;
ObsHandler.obsPartsHandler(); //increment i twice
ObsHandler.search();
}
(startendline != null) is only tested the second time.
i < y is only tested the first time.
Related
I'm making a project for an online course. I don't want the computer-generated coordinates(xOfCompShips, yOfCompShips) to repeat themselves or be the same as those inputted by the user(xOfPlayerShips, yOfPlayerShips). So in case, the same coordinates are generated the if statement would decrease the value of i and make the loop run once more, replacing the duplicated coordinates. By printing lines for debugging I found out that the break statement seems to break the for loop with k and the control goes back to the for loop with i and without any new values being assigned to xOfCompShips,yOfCompShips(or perhaps same values being reassigned to them), the control goes back to the for loop with k and again back to the for loop with i and it keeps going back and forth.
I tried removing the break statement but then if the first random coordinates are a duplicate pair, the array is accessed for index = -1.
for(int i = 0; i < xOfCompShips.length; i++) {
xOfCompShips[i] = (int)Math.floor(Math.random() * 10);
yOfCompShips[i] = (int)Math.floor(Math.random() * 10);
for(int k = 0; k < xOfPlayersShips.length; k++) {
if((xOfCompShips[i] == xOfCompShips[k] && yOfCompShips[i] == yOfCompShips[k])
|| (xOfCompShips[i] == xOfPlayersShips[k] && yOfCompShips[i] == yOfPlayersShips[k])){
i--;
break;
}
}
}
I expect new random values are to be assigned to xOfCompShips and yOfCompShips each the if statement is executed.
(int) Math.floor(Math.random() * C) is the wrong way to do it, this doesn't get you quite uniform output, and it's also needlessly complicated. Make an instance of java.util.Random (and don't keep recreating it; make one instance once, and reuse it), and call rnd.nextInt(10) on that.
you loop k from 0 to xOfPlayersShips, and then use k as index to xOfCompShips. I doubt that's right.
as part of your loop, you say: if (xOfCompShips[i] == xOfCompShips[k] && yOfCompShips[i] == yOfCompShips[k]) restart loop. if i and k are the same, obviously that is true. i starts at 0, k starts at 0.. 0 == 0.
A run with a debugger would have shown you this rather quickly.
Have you tried also breaking out of the outer loop (i.e. k--;), if I understand correctly (which I don't think I do), you're changing i over and over but k is always the same triggering the loop to change i more.
for(int i = 0; i < xOfCompShips.length; i++) {
xOfCompShips[i] = (int)Math.floor(Math.random() * 10);
yOfCompShips[i] = (int)Math.floor(Math.random() * 10);
for(int k = 0; k < xOfPlayersShips.length; k++) {
if((xOfCompShips[i] == xOfCompShips[k] && yOfCompShips[i] == yOfCompShips[k]) ||
(xOfCompShips[i] == xOfPlayersShips[k] && yOfCompShips[i] == yOfPlayersShips[k])){
i--;
**k--;**
break;
}
}
}
I have the following for-loop , used in my State-Capital program:
for (int i = modlastNum; i < StateResponses.length ; i++) {
/* Code inside */
}
I want to let i become 0 , whenever the current i would reach the value of 199. I tried using the following method but it doesn't work right :
for (int i = modlastNum; i < StateResponses.length ; i++) {
/* Code inside */
if ((i % 199) == 0 ) { i = 0; }
}
Instead it turns i to 0, then to 1 at the beginning of the for-loops inner code.
i will be incremented after every block execution, ie 0 will become 1. What if you try to apply the next change
if ((i % 199) == 0 ) { i = -1;}
However it would be great to know what goal are you trying to achieve here, because above code is not easy to understand.
You need to set i to -1.
Look at for loop syntax first. The for loop
for (int i = 0; i < value; i++) {
//code here
}
means
int i = 0;
while (i < value) {
//code here
i++
}
So, at the end of your code, i is incremented by one. You need to set i = -1 in order for i to be equal to 0 on the next iteration of the for loop.
have you thought of using break or maybe setting i =-1... If you aren't using the loop after setting i =0 then call break at the end of call inside if
You can try to incorporate the update in the for loop description - there's a whole section for exactly that, remember. The format is
for ( <initialisation> ; <termination condition> ; <increment> ) {
body
}
What you're talking about is actually updating the loop variable so it should go in the increment section of the for statement. A bit like this...
for (int i = modlastNum;
i < StateResponses.length ;
i = (i % 199) == 0 ? 0 : i + 1) {
<loop body>
}
You can do something similar in the loop body by setting i to -1 rather than 0 but ideally you should avoid updating the loop counter within the body itself if you're using this style of for.
for (int i = lowerBound; i == upperBound; i++) {
//Code goes here
}
I want the last time the for loop is run to have i equaling upperBound. Is this the right syntax? If so why might one ever use <= or >=?
Thanks in advance. :)
A for loop can always be translated to a while loop as follows:
for(initialization; condition; step) {
block;
}
To
initialization;
while (condition) {
block;
step;
}
So if your condition is i == upperBound, the loop will never run, because the condition doesn't start out as true. <= will do what you want, though.
for (int i = lowerBound; i == upperBound; i++) {
//Code goes here
}
The part inside for loop executes when it checks the constraint/condition mentioned inside for loop statement.
Example
for( int i =0; i == 10 ; i++){
saySomething();
}
will run only when i == 10 ie i would have been i=10 , while if you had written i<10 or i<=10 it would have run each time that condition is true.
Here is a quick example : link for for loop.
To run all + equals to upperBound, you need to use <=
One may might use >= if you're counting backwards, <= and if you're counting forwards.
Use:
i <= upperBound
inside the loop.
The reason being that the loop is testing against all constraints in that loop and will only run when it ticks these off as being true. i is only equal to upperbound in one case and never while i it is also equal to lowerbound, so it won't run.
(Eek. First ever answer here! I hope this helps!)
I've got 2 for loops, one nested inside of another. They loop through a 2D array of buttons to get the source of each button thats been clicked using the action listener.
When the button is found I pass the position/array indexs of the button to an external method. However when the button is found from the array of buttons the first for loop evaluates its termination condition to FALSE but still increments the value of i. Leading to an off by one error. My code is in the standard action performed method, with "event" being the ActionEvent. buttons[][] is a JButton array defined as an instance variable. It is of size 10 x 10 and is already added to the panel.
int i = 0; //this will loop through the columns in the array
int j = 0; //loop through the rows
boolean locatedSource = false; //allows me to escape both loops
for(i = 0; !(locatedSource) && i < buttons.length; i++) //problem here, when i < buttons.length is FALSE i still gets incremented, leading to an off by one error
{
for(j = 0; !(locatedSource) && j < buttons.length; j++)
{
if(event.getSource() == buttons[i][j])
{
locatedSource = true;
break;
}
}
}
//do stuff with i and j in another method. Leads to array out of bounds error / off by one error
}
I should of mentioned, I'm not looking to solve this problem with the use of labels, they seem to be discouraged.
Explanation of the problem
The increment expression of a for loop is executed after each loop iteration not before. See the following quote from the Oracle Java tutorial:
The for statement provides a compact way to iterate over a range of values. Programmers often refer to it as the "for loop" because of the way in which it repeatedly loops until a particular condition is satisfied. The general form of the for statement can be expressed as follows:
for (initialization; termination;
increment) {
statement(s)
}
When using this version of the for statement, keep in mind that:
The initialization expression initializes the loop; it's executed once, as the loop begins.
When the termination expression evaluates to false, the loop terminates.
The increment expression is invoked after each iteration through the loop; it is perfectly acceptable for this expression to increment or decrement a value.
For loop solution
You can re-write your loop so that the increment is the first statement inside the loop.
for (i = 0; !(locatedSource) && i < buttons.length;) {
i++;
for (j = 0; !(locatedSource) && j < buttons.length;) {
j++;
if (event.getSource() == buttons[i][j]) {
locatedSource = true;
}
}
}
While Loop Version
Given that the loop variables are both initialised outside of the loop and you don't want to use a for-loop increment expression it might be clearer to rewrite the code to use while-loops as follows:
while (!(locatedSource) && i < buttons.length) {
i++;
while (!(locatedSource) && j < buttons.length) {
j++;
if (event.getSource() == buttons[i][j]) {
locatedSource = true;
}
}
}
Three possible solutions:
Explicitely set a "found" index and do not reuse your for loop indices.
Factor the searching out in an own method and return directly from the loop.
Decrement i by 1 after finishing the loops.
Use some boolean flag set it in inner loop and check it in the beginning of outer loop.
Here is code:
boolean found = false;
for (i = 0; i < 10; i++) // problem here, when i < buttons.length is FALSE i still gets
// incremented, leading to an off by one error
{
if (found) {
i--;
break;
}
for (j = 0; j < 5; j++) {
if (i == 5 && j == 3) {
found = true;
break;
}
}
//if (found) {
// break;
//}
}
Your code contains a comment "problem here, when i < buttons.length is FALSE i still gets incremented, leading to an off by one error", which is wrong in the ordering of the events.
First the cycle update block gets executed (like i++) and after that the condition is checked (like `i < buttons.length').
Meaning, that i == buttons.length is the correct state after the cycle ends without triggering the locatedSource condition.
I created a couple for loops that print lines as such (each new number starts a new line, it doesn't show here):
1
22
333
4444
etc. until it reaches 9 then goes back down to 1.
I am supposed to translate it into both a while and do while loop and have been trying for the past hour and can't seem to do it.
public static void main(String[] args) {
for (int x=1; x <= 9; x++) {
for (int y = 1; y <=x ; y++){
System.out.print( x + "");
}
System.out.println();
}
// TODO code application logic here
for (int x=9; x >=1; x--) {
for (int y = 1; y <=x ; y++){
System.out.print( x + "");
}
System.out.println();
} int y =1;
int x = 1;
while (x <9){
while (y <=x){
y++;
System.out.print(x +"");{
}
System.out.println();
}
x++;
}
A for loop statement has three parts in the for (init; condition; post). These parts are separated by semicolons. The init part specifies an initial statement, the condition is what determines if the loop body is executed or not and the post specifies a post loop statement.
You can do the same thing with a while loop except that instead of a single statement, it is actually several statements. However a while loop is not exactly like a for loop since the continue statement and how it behaves is a concern. More about that later.
A hint is that the various parts of the for statement are separated by semicolons which are also used to separate statements in Java.
Consider the following for loop source example.
int i;
for (i = 0; i < 5; i++) {
// for loop body
}
So you would have an init statement before the loop statement, i = 0 then the loop statement itself containing the condition, i < 5, and as the last line in the loop before the closing curly brace, you would put the post loop condition, i++.
The do while is a bit more complicated because of when the while condition is evaluated. In both the for loop and the while loop, the condition is evaluated and if the expression is not true then the loop body is not executed at all, it is skipped. In the case of the for loop, the init statement is executed and then the condition is evaluated to determine if the for loop body should be executed. Since a while loop does not have an init statement as part of the while statement, the condition is evaluated and if not true, the while loop body is not executed.
A do while loop has a condition that is not evaluated until after the first time through the do while loop body. So the statements within the do while loop are always executed at least once. Then the do while condition is evaluated and if true, execution returns to the top where the do is and the do while loop body is executed again.
Some code of several variations of loops where the init is i = 0 and where the condition is i < 5 and the post is i++. In all cases I have the variable i defined out side of the loop body. In the case of a for loop, defining the variable i within the for statement causes the scope of the variable i, its visibility, to be restricted to the for loop body which would not be the case for the other types of loops.
int i;
for (i = 0; i < 5; i++) {
// for loop body
}
int i = 0;
while (i < 5) {
// while loop body
i++;
}
int i = 0;
do {
// do while loop body
i++;
} while (i < 5);
I mentioned that what happens when the continue statement is executed can make a difference when comparing these forms of loops. The way to think of it is that when a continue statement is executed then there is a jump to the closing brace of the loop statement enclosing the continue statement. So this introduces something to consider.
Look at the above examples but with a continue statement. In all of the examples below there is a continue statement which causes execution to skip to the end of the loop body when the variable i has a value of 3.
With this change the for loop will continue incrementing the variable i because it's post, the third part of the for statement, is executed at the end of the loop. However with the while loop and the do while loop, the incrementing of the variable i is part of the loop body so when the continue is executed skipping to the end of the loop, the increment of the variable i is also skipped.
int i;
// first time init variable i to zero then evaluate condition
for (i = 0; i < 5; i++) { // evaluate condition and execute loop body if true
// for loop body
if (i == 3)
continue; // when i == 3 continue is executed to skip to end of loop
} // at point of braces, post executed, condition evaluated
int i = 0;
while (i < 5) { // evaluate condition and execute loop body if true
// while loop body
if (i == 3)
continue; // when i == 3 continue is executed to skip to end of loop
i++; // variable i only incremented when this statement is executed
} // braces indicate end of loop so jump back to top of loop
int i = 0;
do {
// do while loop body
if (i == 3)
continue; // when i == 3 continue is executed to skip to end of loop
// more statements which may be skipped by the continue
i++; // variable i only incremented when this statement is executed
} while (i < 5); // evaluate condition and jump to top of loop if true
You could make a change to the do while loop while condition to move the incrementing of the variable i into the while condition evaluation by using a pre-increment operator, the ++ operator, on the variable as in the following. We use the pre-increment operator because we want to increment the variable i before we check its value.
int i = -1; // need to start at -1 since the while will increment at beginning of the loop
while (++i < 5) { // increment variable i, evaluate condition and body of loop if true
// while loop body
if (i == 3)
continue; // when i == 3 continue is executed to skip to end of loop
} // braces indicate end of loop so jump back to top of loop
int i = 0;
do {
// do while loop body
if (i == 3)
continue; // when i == 3 continue is executed to skip to end of loop
// more statements which may be skipped by the continue
} while (++i < 5); // increment variable i, evaluate condition and jump to top of loop if true
Try this as your while loop:
int y = 1;
int x = 1;
while (x < 9) {
y = 1;
while (y <= x) {
y++;
System.out.print(x + "");
}
System.out.println();
x++;
}
A for loop is a construct that is extremely similar to a while loop, except that it provides some extra niceties that reduce boilerplate code.
The beginning of a for loop sets your initial variable (in your case, x), your condition clause (x <= 9) and your incrementor (x++). A while loop does not do these things for, it simply runs a block of code while the condition clause in the () is met.
Converting a for loop to a while is simple-
for(int x = 0; x < 10; x++) {
int x = 0;
while(x < 10) {
x++;
}
The while loop has all the same features as the for loop, but without the syntactic sugar. This should help you convert the loops in your question, and in general.