Related
I'm working on a brickout game clone, so I'm trying to add a multiply the ball feature to the game. This Video shows the feature.
Here is my code:
//access to all active balls
Ball[] balls = FindObjectsOfType<Ball>();
//loop for the length of the balls
for (int i = 0; i <= balls.Length; i++)
{
if (balls.Length >= 1000)
{
return;
}
else
{
// here I'm trying to fix the issue by checking if the ball exists, so I will call the function if not. return. but console show me same message
if (balls[i] != null)
{
balls[i].CallM3x();
i++;
}
}
}
The unity console message is:
IndexOutOfRangeException: Index was outside the bounds of the array.
My code above is working fine, but the issue is some balls destroy before the for loop end its work by less than a second .
Any idea how to avoid this?
There are two fundamental issues with your loop:
you're looping up to i <= balls.Length which will always throw an error (there is no a[10] in an array of length 10).
you're incrementing i again within the loop, which will skip items
Change the loop condition to i < balls.Length and remove the i++ within the loop.
Also, you don't need to check if (balls.Length >= 1000) within the loop every time - you can check that before the loop (but what's the problem with a collection with more than 10,000 items?)
the issue is some balls destroy before the for loop end its work by less than a second
I don't see how this can be a problem. You're creating an array of references that you're looping over. Even if items are destroyed within the game, the object references still exist within your array. There may be some other flag to tell you that an object is destroyed (I am not a Unity expert), but they would not change to null inside your array.
A simple way to avoid the issue of re-referencing objects you have deleted in a loop is by counting i down from balls.Length to 0 instead of up from 0 to balls.Length.
for (int i = balls.Length - 1; i >= 0; i--)
Also, you might want to look again at your for-loop: you are going up to <= balls.Length, allowing the highest index to be = balls.Length. That index is out of bounds though, because we start counting at 0. I suggest using < instead of <= here.
Ball[] balls = FindObjectsOfType<Ball>();
for (int i = 0; i < balls.Length; i++)
{
if (balls.Length >= 1000)
{
return;
}
else
{
if (balls[i] != null)
{
balls[i].CallM3x();
// i++; <- This is your problem. Remove it.
}
}
}
I 'm not sure how to explain this and I cannot find an answer anywhere. I have a for loop that loops through lines that are represented through strings.
for (int i = 0; i < dataLines.Length; i++)
{
jumpPoint:
Debug.Log("Jumped");
string[] words = dataLines[i].Split();
.
.
. "words[] manipulation and reading"
.
.
}
I have no problems with any of my data processing or things that happen in the loop.
But I have an instance where i need to go to a previous dataLine[] and continue from that point (also re-runs code that has already been run since that point).
What I am doing essentially boils down to
i = ?; //arbitrary number for the situation that is definitely not out of bounds for the loop
goto jumpPoint;
Ive also tried without the jump point also just letting the loop cycle to the next after resetting the for loop index.
I know it's not an issue with the jump point as its used for unrelated things and the jump works fine. Also worth mentioning, that in those instances, I am increasing the i index so the for loop prematurely advances and that works perfect.
So why can I not go backwards in the loop? Is that just something that is not possible?
Not sure if I understand but you mean something like this:
var i = 0;
var startRun = true;
while (true)
{
if (!startRun && i == dataLines.Length - 1)
return;
if (startRun)
startRun = false;
/* do stuff */
if (needToJump)
{
clearLogicOrWhatever();
i = whereYouNeedToJump;
}
else
i++;
}
Of course you will need more validation if going out of index, if step exists or in range and other stuff, this is just like a proof of concept / pseudo.
Nothing is stopping you from going backwards in the loop. You are in control of your code logic, so all you have to do is when your "jumpPoint" condition is met, just change the iterator i back to the previous value that you desire.
For example: Let's say I want to jump back and re-run something because it had the word "jump" in it.
Console.WriteLine("App started.");
List<string> dataLines = new List<string>() { "this is a phrase", "This is another but with jump in it", "this is the last" };
bool alreadyJumped = false;
for (int i = 0; i < dataLines.Count; i++)
{
Console.WriteLine($"Currently Iterating: {i}");
string[] words = dataLines[i].Split();
Console.WriteLine($"Do some with this data: {dataLines[i]}");
if (words.Contains("jump") && !alreadyJumped)
{
alreadyJumped = true;
// Reset the i value so that the next iteration will run again.
i = i - 1;
}
else if (alreadyJumped)
{
// Once
alreadyJumped = false;
}
}
Console.WriteLine("App done.");
This will produce this output:
App started.
Currently Iterating: 0
Do some with this data: this is a phrase
Currently Iterating: 1
Do some with this data: This is another but with jump in it
Currently Iterating: 1
Do some with this data: This is another but with jump in it
Currently Iterating: 2
Do some with this data: this is the last
App done.
In C# a question has been bugging me for a while and its what is that actual major difference between a While and For Loop. Is it just purely readability ie; everything you can essentially do in a for loop can be done in a while loop , just in different places. So take these examples:
int num = 3;
while (num < 10)
{
Console.WriteLine(num);
num++;
}
vs
for (int x = 3; x < 10; x++)
{
Console.WriteLine(x);
}
Both code loops produce the same outcome and is the only difference between the two that the for loop forces you to declare a new variable and also set the iteration value each loop cycle at the start? Maybe I'm missing something else in terms of any major differences but it would good if someone can set me straight regarding this. Thanks.
is the only difference between the two that the for loop forces you to declare a new variable and also set the iteration value each loop cycle at the start?
The for loop forces you to nothing. You can omit any of the 3 elements. The smallest form is
for(;;) // forever
{
DoSomething();
}
But you can use the 3 elements to write more concise code:
for(initializer; loop-condition; update-expression)
{
controlled-statements;
}
is equivalent to:
{
initializer;
while(loop-condition)
{
controlled-statements;
continue_target: // goto here to emulate continue
update-expression;
}
}
Note the outer {} braces, in for(int i = 0; ...; ...) the i is local to the for-loop. A clear benefit.
But the major difference in usage is when you call continue; inside the loop, much easier to get the logic wrong in a while-loop than in a for-loop.
Yes, they're exactly the same in the background (in Assembly, that is).
Usually, it is more common to use the for loop when the number of repeats is known and we're not going to change our counter(index).
while loop also has the advantage of a sentinel loop which is easier for example when taking inputs from a user until something specific is given.
Fundamentally, the differences are:
For loop knows in advance how many times it will loop, whereas a while loop doesn’t know.
For loop has an initialization step whereas a while loop doesn’t
For loop uses a “step value” or increment/decrement step, whereas a while loop doesn’t.
Here is an example of a Java for loop looping from 0 to 99 and printing out the numbers. Notice how the loop is initialized and incremented as part of the for loop structure.
for(int i=0; i<100; i++) {
System.out.println(i);
}
Here is an example of a Java while loop printing out all the elements in an integer array. Notice how the loop variable is initialized before the loop and is incremented inside the loop body.
int [] intArray = {1, 3, 5, 7, 9};
int i=0;
while(i<intArray.length) {
System.out.println(intArray[i++]);
}
When you are sure what will be the end value or how much the loop should execute(until what value), use 'for' loop, otherwise use 'while' loop.
Using C# (or VB.NET) which loop (for loop or do/while loop) should be used when a counter is required?
Does it make a difference if the loop should only iterate a set number of times or through a set range?
Scenario A - The for loop
for (int iLoop = 0; iLoop < int.MaxValue; iLoop++)
{
//Maybe do work here
//Test criteria
if (Criteria)
{
//Exit the loop
break;
}
//Maybe do work here
}
Advantages
Counter is declared as part of loop
Easy to implement counter range
Disadvantages
Have to use an if to leave the loop
Scenario B - The do/while loop
int iLoop = 0;
do
{
//Increment the counter
iLoop++;
//Do work here
} while (Criteria);
or
int iLoop = 0;
while (Criteria)
{
//Increment the counter
iLoop++;
//Do work here
}
Advantages
Leaving the loop is part of the loop structure
Choice to evaluate before or after loop block
Disadvantages
Have to manage the counter manually
Just for completeness, you could also use option D:
for (int iLoop = 0; Criteria; iLoop++)
{
// work here
}
(where Criteria is "to keep running")
the condition in a for loop doesn't have to involve iLoop. Unusual, though, but quite cute - only evaluates before work, though.
How about the best of both worlds:
for (int iLoop = 0; iLoop < int.MaxValue && !Criteria; iLoop++)
Edit: Now that I think about it, I suppose comparing against int.MaxValue wasn't part of the criteria, but something to emulate an endless for loop, in that case you could just use:
for (int iLoop = 0; !Criterea; iLoop++)
for (int iLoop = 0; iLoop < int.MaxValue && !Criteria; iLoop++) {
//Do work here...
}
Instead of a dummy criteria in the for loop, you can use the actual criteria that you want to use for the loop:
Scenario A2 - the for loop with custom criteria:
for (int iLoop = 0; Criteria; iLoop++) {
// do work here
}
This is equivalent to:
{
int iLoop = 0;
while (Criteria) {
// do work here
iLoop++;
}
}
If you have a loop counter, you should generally use a for loop to make that clearer.
I ususually use for, cause it's simple. I use while when counter is needed after or before loop or if using for is impossible.
You can always add the exit criteria to for loop:
for (int iLoop = 0; iLoop < int.MaxValue && Criteria; iLoop++)
{
//Maybe do work here
}
I would really go for whatever looks most readable in your particular case.
There's no reason not to use a for loop in this case. Even if you have other criteria, it's perfectly valid to write:
for (int iLoop = 0; iLoop < int.MaxValue && Criteria; iLoop++) { ... }
for loops consist of the following:
for ( initialization; condition; action )
you don’t need an extra if to check your criteria, what do you think is i < value? it’s nothing more than a criteria.
i use loops when they fit the problem, there’s no definite answer
Write some test cases and see which works best for you. Have a look a this link: .Net/C# Loop Performance Test (FOR, FOREACH, LINQ, & Lambda)
Personally I would go with the for loop.
It is better to read, more commonly used and very optimized.
for (int iLoop = 0; iLoop < int.MaxValue && !Criteria; iLoop++)
{
// Do Work
}
Edit: int.MaxValue && !Criteria <- a definietely better approach than my initial one ;)
I'd tend to use for if I'm actually using the counter in the loop, say as an index into an array, and as part of the criteria, i.e. "stop at the end of the array" rather than "just don't overflow".
If I'm looping over something with unknown length, such as lines in a file, or just maintaining the counter to use the total after the loop, then I'll use do or while.
However, it really comes down to what's more readable for a particular situation. I expect that you'd struggle to tell from the compiled IL which version was used.
((((difference b/w while and do while--> let me tell you with one example :
if a person going into a hall to fix a bomb inside the hall, he must be checked when getting in.. in another case if a person going into a hall to steal something from there he must have been checked when coming out of the hall.. so based on the process only we have to use our looping condition....))))
The for loop can execute a block of code for a fixed or given number of times.if your counter variable depends on that block of code(means inside the looping condition), you can use the for loop
At least for me i use for() when i need to traverse an array and when no breaking is needed. And do() and while() when i need to process something for an unknown time.
In a C# (feel free to answer for other languages) loop, what's the difference between break and continue as a means to leave the structure of the loop, and go to the next iteration?
Example:
foreach (DataRow row in myTable.Rows)
{
if (someConditionEvalsToTrue)
{
break; //what's the difference between this and continue ?
//continue;
}
}
break will exit the loop completely, continue will just skip the current iteration.
For example:
for (int i = 0; i < 10; i++) {
if (i == 0) {
break;
}
DoSomeThingWith(i);
}
The break will cause the loop to exit on the first iteration - DoSomeThingWith will never be executed. This here:
for (int i = 0; i < 10; i++) {
if(i == 0) {
continue;
}
DoSomeThingWith(i);
}
Will not execute DoSomeThingWith for i = 0, but the loop will continue and DoSomeThingWith will be executed for i = 1 to i = 9.
A really easy way to understand this is to place the word "loop" after each of the keywords. The terms now make sense if they are just read like everyday phrases.
break loop - looping is broken and stops.
continue loop - loop continues to execute with the next iteration.
break causes the program counter to jump out of the scope of the innermost loop
for(i = 0; i < 10; i++)
{
if(i == 2)
break;
}
Works like this
for(i = 0; i < 10; i++)
{
if(i == 2)
goto BREAK;
}
BREAK:;
continue jumps to the end of the loop. In a for loop, continue jumps to the increment expression.
for(i = 0; i < 10; i++)
{
if(i == 2)
continue;
printf("%d", i);
}
Works like this
for(i = 0; i < 10; i++)
{
if(i == 2)
goto CONTINUE;
printf("%d", i);
CONTINUE:;
}
When to use break vs continue?
Break - We're leaving the loop forever and breaking up forever. Good bye.
Continue - means that you're gonna give today a rest and sort it all out tomorrow (i.e. skip the current iteration)!
(Corny stories ¯¯\(ツ)/¯¯ and pics but hopefully helps you remember.
Grip Alert: No idea why those words are being used. If you want to skip the iteration, why not use the word skip instead of continue? This entire Stack overflow question and 1000s of developers would not be confused if the proper name was given.)
break would stop the foreach loop completely, continue would skip to the next DataRow.
There are more than a few people who don't like break and continue. The latest complaint I saw about them was in JavaScript: The Good Parts by Douglas Crockford. But I find that sometimes using one of them really simplifies things, especially if your language doesn't include a do-while or do-until style of loop.
I tend to use break in loops that are searching a list for something. Once found, there's no point in continuing, so you might as well quit.
I use continue when doing something with most elements of a list, but still want to skip over a few.
The break statement also comes in handy when polling for a valid response from somebody or something. Instead of:
Ask a question
While the answer is invalid:
Ask the question
You could eliminate some duplication and use:
While True:
Ask a question
If the answer is valid:
break
The do-until loop that I mentioned before is the more elegant solution for that particular problem:
Do:
Ask a question
Until the answer is valid
No duplication, and no break needed either.
All have given a very good explanation. I am still posting my answer just to give an example if that can help.
// break statement
for (int i = 0; i < 5; i++) {
if (i == 3) {
break; // It will force to come out from the loop
}
lblDisplay.Text = lblDisplay.Text + i + "[Printed] ";
}
Here is the output:
0[Printed] 1[Printed] 2[Printed]
So 3[Printed] & 4[Printed] will not be displayed as there is break when i == 3
//continue statement
for (int i = 0; i < 5; i++) {
if (i == 3) {
continue; // It will take the control to start point of loop
}
lblDisplay.Text = lblDisplay.Text + i + "[Printed] ";
}
Here is the output:
0[Printed] 1[Printed] 2[Printed] 4[Printed]
So 3[Printed] will not be displayed as there is continue when i == 3
Break
Break forces a loop to exit immediately.
Continue
This does the opposite of break. Instead of terminating the loop, it immediately loops again, skipping the rest of the code.
Simple answer:
Break exits the loop immediately.
Continue starts processing the next item. (If there are any, by jumping to the evaluating line of the for/while)
By example
foreach(var i in Enumerable.Range(1,3))
{
Console.WriteLine(i);
}
Prints 1, 2, 3 (on separate lines).
Add a break condition at i = 2
foreach(var i in Enumerable.Range(1,3))
{
if (i == 2)
break;
Console.WriteLine(i);
}
Now the loop prints 1 and stops.
Replace the break with a continue.
foreach(var i in Enumerable.Range(1,3))
{
if (i == 2)
continue;
Console.WriteLine(i);
}
Now to loop prints 1 and 3 (skipping 2).
Thus, break stops the loop, whereas continue skips to the next iteration.
Ruby unfortunately is a bit different.
PS: My memory is a bit hazy on this so apologies if I'm wrong
instead of break/continue, it has break/next, which behave the same in terms of loops
Loops (like everything else) are expressions, and "return" the last thing that they did. Most of the time, getting the return value from a loop is pointless, so everyone just does this
a = 5
while a < 10
a + 1
end
You can however do this
a = 5
b = while a < 10
a + 1
end # b is now 10
HOWEVER, a lot of ruby code 'emulates' a loop by using a block.
The canonical example is
10.times do |x|
puts x
end
As it is much more common for people to want to do things with the result of a block, this is where it gets messy.
break/next mean different things in the context of a block.
break will jump out of the code that called the block
next will skip the rest of the code in the block, and 'return' what you specify to the caller of the block. This doesn't make any sense without examples.
def timesten
10.times{ |t| puts yield t }
end
timesten do |x|
x * 2
end
# will print
2
4
6
8 ... and so on
timesten do |x|
break
x * 2
end
# won't print anything. The break jumps out of the timesten function entirely, and the call to `puts` inside it gets skipped
timesten do |x|
break 5
x * 2
end
# This is the same as above. it's "returning" 5, but nobody is catching it. If you did a = timesten... then a would get assigned to 5
timesten do |x|
next 5
x * 2
end
# this would print
5
5
5 ... and so on, because 'next 5' skips the 'x * 2' and 'returns' 5.
So yeah. Ruby is awesome, but it has some awful corner-cases. This is the second worst one I've seen in my years of using it :-)
Please let me state the obvious: note that adding neither break nor continue, will resume your program; i.e. I trapped for a certain error, then after logging it, I wanted to resume processing, and there were more code tasks in between the next row, so I just let it fall through.
To break completely out of a foreach loop, break is used;
To go to the next iteration in the loop, continue is used;
Break is useful if you’re looping through a collection of Objects (like Rows in a Datatable) and you are searching for a particular match, when you find that match, there’s no need to continue through the remaining rows, so you want to break out.
Continue is useful when you have accomplished what you need to in side a loop iteration. You’ll normally have continue after an if.
if you don't want to use break you just increase value of I in such a way that it make iteration condition false and loop will not execute on next iteration.
for(int i = 0; i < list.Count; i++){
if(i == 5)
i = list.Count; //it will make "i<list.Count" false and loop will exit
}
Since the example written here are pretty simple for understanding the concept I think it's also a good idea to look at the more practical version of the continue statement being used.
For example:
we ask the user to enter 5 unique numbers if the number is already entered we give them an error and we continue our program.
static void Main(string[] args)
{
var numbers = new List<int>();
while (numbers.Count < 5)
{
Console.WriteLine("Enter 5 uniqe numbers:");
var number = Convert.ToInt32(Console.ReadLine());
if (numbers.Contains(number))
{
Console.WriteLine("You have already entered" + number);
continue;
}
numbers.Add(number);
}
numbers.Sort();
foreach(var number in numbers)
{
Console.WriteLine(number);
}
}
lets say the users input were 1,2,2,2,3,4,5.the result printed would be:
1,2,3,4,5
Why? because every time user entered a number that was already on the list, our program ignored it and didn't add what's already on the list to it.
Now if we try the same code but without continue statement and let's say with the same input from the user which was 1,2,2,2,3,4,5.
the output would be :
1,2,2,2,3,4
Why? because there was no continue statement to let our program know it should ignore the already entered number.
Now for the Break statement, again I think its the best to show by example. For example:
Here we want our program to continuously ask the user to enter a number. We want the loop to terminate when the user types “ok" and at the end Calculate the sum of all the previously entered numbers and display it on the console.
This is how the break statement is used in this example:
{
var sum = 0;
while (true)
{
Console.Write("Enter a number (or 'ok' to exit): ");
var input = Console.ReadLine();
if (input.ToLower() == "ok")
break;
sum += Convert.ToInt32(input);
}
Console.WriteLine("Sum of all numbers is: " + sum);
}
The program will ask the user to enter a number till the user types "OK" and only after that, the result would be shown. Why?
because break statement finished or stops the ongoing process when it has reached the condition needed.
if there was no break statement there, the program would keep running and nothing would happen when the user typed "ok".
I recommend copying this code and trying to remove or add these statements and see the changes yourself.
As for other languages:
'VB
For i=0 To 10
If i=5 then Exit For '= break in C#;
'Do Something for i<5
next
For i=0 To 10
If i=5 then Continue For '= continue in C#
'Do Something for i<>5...
Next