if statement not resolving despite condition being met C++ - c++

I'm working on a university assignment wherein I have to re-create the classic Frogger game. Having trouble with tyre movement.
for (int tZ = 0; tZ < kTyreColumnLength; tZ++)
{
for (int tX = 0; tX < kTyreRowLength; tX++)
{
eachTyre = tX + tZ;
tyre[eachTyre] = tyreMesh->CreateModel(0, -2.50, 0);
tyre[eachTyre]->Scale(10);
tyre[eachTyre]->SetX(tyreXs[tX]);
tyre[eachTyre]->SetZ(tyreZs[tZ]);
if (tZ % 2 == 0)
{
tyreMovingLeft[eachTyre];
}
}
}
Basically, the way I'm drawing my tyres is through nested for loops. The inner loop draws3 tyres, and is repeated for each row (outer loop)
I'm then trying to assign each "even" row tyre, a Boolean to track its direction.
tZ % 2 ==0 IS correctly resolving to true/false each time the outer loop iterates, the debugger says the condition IS being met, but it's just never executing.

You never actually performed an assignment, you just indexed your array.
tyreMovingLeft[eachTyre];
You probably meant
tyreMovingLeft[eachTyre] = true;

Thr issue is that the inner block doesn’t have any effect:
tyreMovingLeft[eachTyre];
So it's optimized out by compiler. Didn't yoy mean some assignment or passing the result to some function?

Related

Spawning monsters at random locations

std::string monsterNames[2] {"Weezer", "Leppin"};
for (int vecID = 1; vecID < 5; ++vecID)
{
if(newmonster.monsterData[vecID-1].posX != newmonster.monsterData[vecID].posX && newmonster.monsterData[vecID-1].posY != newmonster.monsterData[vecID].posY)
{
int randIndex = rand()% 2;
int randPosX = rand()% 3;
int randPosY = rand()% 3;
newmonster.CreateMonster(monsterNames[randIndex], randPosX, randPosY);
newmonster.monsterData.push_back(newmonster);
}
else
{
continue;
}
}
Yes, this code does not run because of the if statement. No monsters are created until after the statement, therefore array index is out of bounds.
Basically, the program randomises the monster names and coordinates and all works well without the if statement. But I need to check whether a monster already exists at that location and if it doesn't, re-run the loop.. How to do this in a more sensible way? xD
If I don't have the for loop, the random numbers will always be the same.
I will propose the next solution, you can extract the if statement code into a new function "generateRandomMonster", so you can call it once before the for bucle and reduce the iterations in one, in this way you can ensure that the newmonster array already have one monster and the if statement doesn't break your code.
I hope this solution helps you.
Br.
Your check is wrong. If it happens that last two monsters are in the same location then stop making monsters. Surely that's not what you want.
In your place I would run a while loop until newmonster.monsterData.size() == 5. In loop I would make random coordinates and add the monster only if none of the already created monsters share the location. For that check you need an inner loop.

Change for loop condition with respect to an external flag (cpp)

I have a code block as following, where the inner for loop code remains the same but only the loop condition changes based on the reverseFlag. Is there a better way to code this without having to copy paste the content of the for loop twice ?
bool reverseFlag=false;
if (reverseFlag)
{
for(int i = 1; i < TotalFrames; i++)
{...}
}
else
{
for(int i = TotalFrames-1; i >0; i--)
{...}
}
Yes, you can do it in a single for loop, like this:
int from, to, step;
if (reverseFlag) {
from = TotalFrames-1;
to = -1;
step = -1;
} else {
from = 0;
to = TotalFrames;
step = 1;
}
for (int i = from ; i != to ; i+= step) {
...
}
A single conditional ahead of the loop prepares loop's parameters - i.e. its starting and ending values and the step, and then the loop uses these three values to iterate in the desired direction.
There are several options. You can:
Use two loops but put the loop body in a separate function/object/lambda.. to avoid duplication.
Use an increasing loop and calculate the real index within the loop:
j = reverseFlag ? TotalFrames - i : i;
Pre-calculate the loop conditions as #dasblinkenlight suggested.
Note that if you have a performance critical loop, some of these methods could hurt performance. If in doubt, check what your compiler does and measure the elapsed time.

C++ Assignment don't work

Sorry for this very simple looking problem, but I have no idea what causes it:
In a C++ project I have a loop in a loop in a loop and have to leave the inner two so I have a variable for a query. In the first iteration it works fine, but in the second the assign from dtime to abbruch does not work. In the Debugger dtime has correctly the value "1" and abbruch "0" but this stays after the assignment. Both are of type long.
for (sect = 0; sect <= sections; sect++)
{
abbruch = 0;
for(line = 0; line < maxlines ; line ++)
{
abbruch = dtime[sect][0];
if(abbruch != 0)
{
break;
}
for (index = 0; index < 30; index ++)
{
if (complicated query)
{
dtime[sect][0] = DiffTime[maxlines * sect + line];
break;
}
}
}
}
I use VS2012 Ultimate.
Has anyone an idear how this can happen ot how to solve it?
Did you maybe mean to put this?
abbruch = dtime[sect][line];
(line instead of 0)
But also what Bathseba said is true. A break will only break one for-loop.
break will only take you out of the current for loop. In your case, the loop over index will not be called following a break when abbruch != 0 as that break will take you out of the loop over line. The other break statement will take you out of the loop over index.
That's the rationale, but, by far the best thing to do is to step through with a debugger. I wouldn't use break statements in this way as it's too confusing. Consider breaking the triple loop structure into function calls using return statements in place of breaks.
Also, it's a good idea to localise the interating variables in the for loops, e.g.
for (int sect = 0; sect <= sections; sect++)

Vector push_back in while and for loops returns SIGABRT signal (signal 6) (C++)

I'm making a C++ game which requires me to initialize 36 numbers into a vector. You can't initialize a vector with an initializer list, so I've created a while loop to initialize it faster. I want to make it push back 4 of each number from 2 to 10, so I'm using an int named fourth to check if the number of the loop is a multiple of 4. If it is, it changes the number pushed back to the next number up. When I run it, though, I get SIGABRT. It must be a problem with fourth, though, because when I took it out, it didn't give the signal.
Here's the program:
for (int i; i < 36;) {
int fourth = 0;
fourth++;
fourth%=4;
vec.push_back(i);
if (fourth == 0) {
i++;
}
}
Please help!
You do not initialize i. Use for (int i = 0; i<36;). Also, a new variable forth is allocated on each iteration of the loop body. Thus the test fourth==0 will always yield false.
I want to make it push back 4 of each number from 2 to 10
I would use the most straight forward approach:
for (int value = 2; value <= 10; ++value)
{
for (int count = 0; count < 4; ++count)
{
vec.push_back(value);
}
}
The only optimization I would do is making sure that the capacity of the vector is sufficient before entering the loop. I would leave other optimizations to the compiler. My guess is, what you gain by omitting the inner loop, you lose by frequent modulo division.
You did not initialize i, and you are resetting fourth in every iteration. Also, with your for loop condition, I do not think it will do what you want.
I think this should work:
int fourth = 0;
for (int i = 2; i<=10;) {
fourth++;
fourth%=4;
vec.push_back(i);
if (fourth==0) {
i++;
}
}
I've been able to create a static array declaration and pass that array into the vector at initialization without issue. Pretty clean too:
const int initialValues[36] = {0,1,2...,35};
std::vector foo(initialValues);
Works with constants, but haven't tried it with non const arrays.

Beginner for loop problem

[EDIT]Whoops there was a mistake in the code, and now all the responses to the question seem bizzare, but basically the for loop used to be, for(i=0; i<15; i++). I also edited to make the question more clear.[/EDIT]
I am trying to make a for loop, that checks a 16 element array, so it loops from 0 to 15. I then use the i variable later, however sometimes i == 16, which causes problems by being out of bounds.
I have a solution but it doesnt seem elegant, which makes me think I am missing something. I've tried while loops, but I can never get any loop to go from 0 to 15, and never end at a value greater than 15.
Is there any way to make a loop go and check all 16 elements of the array, while never being greater than 15 at the end of the loop?
int i;
for(i=0; i<16; i++)
{
someClass.someMethod(i);
if(someClass.Test())
{
break;
}
}
if (i == 16)
{
i = 15;
}
I suggest using some other variable other than i after your loop is finished. The criteria of using a for loop instead of a while loop is that you know beforehand exactly how many times a for loop will execute. If you already know this, just set some other variable to the ending value of your loop and use it instead of giving i a dual purpose.
int j = 15;
for(int i=0; i <= j; i++)
{
someClass.array[i];
}
// continue on using j, which value hasn't changed
Well for starters, your sample code loops from 0 to 14. But if you loop from 0 to 15, naturally i has to be 16 before the loop can end. What happens is it becomes 16, THEN your loop notices it's out of bounds and breaks out. If you want it to end at 15, honestly the easiest thing to do is just decrement just after the loop end.
i is incremented on last check to be 16, which is not less than 15, so loop exits with i being 16.
Maybe it's useful to know that:
for (before; check; after) { body }
it's the same as:
before
while(check) {
body
after
}
If you think at your for loop in that term, maybe you'll find out easily why i, at the exit, is 16.
There seems to be some fundamental flaws in your approach.
You shouldn't really use an index variable outside the scope of the loop.
You should use a variable or function to determine the limit of the loop.
It would be better to use iterators instead of numeric indexes.
Generic algorithms can remove the need for loops.
Just my $0.02.
So - if you're checking a 16 element array, normally you'd do this:
for(i=0; i<16; i++)
How for works, is it starts with the first statement of three:
i=0
Then it does your check, in the second statement:
i < 16 // True here, since 0 < 16
That happens before your loop. Then it runs the block of your loop with that set:
someClass.array[i]; //0
Finally, it does the final statement:
i++
Then it repeats the second and third statements, in a sequence.
Before the last run, i == 14, then it does i++, setting i to 15, and executes the block. Finally, it does i++, setting:
i==16
At this point, the condition is no longer true:
i < 16 // False, since i==16
At this point, your block does not execute, but i is still set to 16.
You must have missed something.
In this loop it wouldn't even hit 15, you'd need to say i <= 15, as soon as i = 14 it'd run once and bail.
The for loop is equivalent to the following while loop:
i = 0;
while(i < 16) {
someClass.array[i];
i++;
} // while
i needs to reach 16 to get out of the loop correctly.
Technically there are ways of writing the loop such that i is 15 on exiting the loop, but you shouldn't do them:
int i = 0;
while (1) {
someclass.someMethod(i);
if (i < 15) {
i++;
} else {
break;
}
}
Yes, it does what you ask. But the flow is horrible.
You cannot accomplish this with the built-in loop structures, and as Bill The Lizard said, you probably don't really want to reuse the for-loop variable.
But, if you really want to, here's a way to do it. The trick is to put the loop condition in the middle of the loop:
int i = 0;
while (true)
{
someclass.array[i];
if (i == 15)
break;
++i;
}
The key issue to understand here is that there are 17 different answers to the question "What value of i causes the test to succeed?". Either i can be in {0, 1, ..., 15}, or no value of i causes the test to succeed, which is denoted by i == 16 in this case. So if i is restricted to only 16 values, the question cannot be answered.
There are legitimate cases where you do not want to go past the last valid value. For instance, if you had 256 values and for some reason you only have one byte to count with. Or, as happened to me recently, you want to examine only every ith element of an array, and the last addition to your iterator takes you far beyond the end of the array. In these cases loop unrolling is necessary.
However, for this problem it would be cleaner to use a flag:
bool flag = false;
for (int i = 0; i < 15; ++i)
{
someClass.someMethod(i);
if (someClass.Test())
{
flag = true;
break;
}
}
Then it's clear whether or not the test ever succeeded.
If your loop terminates natuarally, rather than with a break, i will be 16. There's no way to avoid this. Your code is perfectly acceptable if what you want is for i to end up as 15 or less:
int i;
for (i=0; i<16; i++) {
someClass.someMethod(i);
if (someClass.Test())
break;
}
if (i == 16)
i = 15;
Anything that changes i from 16 to 15 after the loop body will do:
if (i == 16) i = 15;
i = (i == 16) ? 15 : i;
i = MAX (15,i); /* where MAX is defined :-) */
and so on.
However that assumes that i is going to be used for something meaningful as a post-condition with respect to that loop. I find that's rarely the case, people tend to re-initialize it before re-use (such as another for loop).
In addition, what you are doing makes it very difficult (impossible, even) to figure out as a post-condition, wheteher your loop terminated normally or whether it terminated prematurely because someClass.Test() returned true for i == 15. This means using i to make further decision is fraught with danger.
My question would be: Why do you think you need to leave i as 15 or less?
I am trying to make a for loop, that
checks a 16 element array, so it loops
from 0 to 15. I then use the i
variable later, however sometimes i ==
16, which causes problems by being out
of bounds.
You need to check for the case where your for loop didn't break, because this information determines whether or not whatever you wanted to do with i is valid.
There are a couple of ways to do this. One is to keep track of it in a bool, such as "foundClass" or "testSucceeded". Default it to false, then set it to true on your break. Enclose any uses of i later in the function in "if (foundClass) { }" blocks.
Another is to just do what you've done. Although your fallback doesn't look right at all. If you're setting i to 15, you're lying to your code and telling it that someClass.Test() succeeded for i == 15, which isn't true. Avoid setting the value to something that's wrong just so your code doesn't error later on. It's much better to put bounds checks around the actual usage of i later in the code.
for(int i=0; i<17; i++)
{
if(i<16)
{
someClass.someMethod(i);
if(someClass.Test())
{
break;
}
}
else if(i==16)
{
i=15;
}
}
if you say you have an array with 16 elements, you don't have to define that, use the array to get that info (DO NOT DUPLICATE INFORMATION)
afterwards if you want to get the last index again use the array to get that info.
for(int i = 0; i < myArray.length; ++i){
myArray[i].somemethod();
}
// lastindex = myArray.length-1;