views:

130

answers:

4

I need to loop through a number (xx). xx always starts at zero. My problem is that if the moveDirection variable is +1 then xx increases until it reaches the positive of range. If moveDirection is -1, then xx decreases until reaching the negative of range.

In the code below, I have done this by having an if statement test for moveDirection first, then I have duplicated the for loop, and edited the values for each case. My code happens to be in ActionScript3, but the language does not matter.

var p:Point;
var xx:int;

if (moveDirection > 0)
{
    for (xx = 0; xx < range; xx++)
    {
        if (hitTestPoint(xx, yy))
        {
            return true;
        }
    }
}
else 
{
    for (xx = 0; xx > range; xx--)
    {
        if (hitTestPoint(xx, yy))
        {
            return true;
        }
    }
}

Is there a better way of doing this, maybe without duplicating the for loop? If there is any other advice, it would be greatly appreciated.

A: 

Here's an example in Java (see also on ideone.com):

static void go(final int range, final int direction) {
    for (int i = 0; i != direction*range; i += direction) {
        System.out.println(i);
    }       
}

Then you can do:

        go(5, +1); // 0, 1, 2, 3, 4
        go(5, -1); // 0, -1, -2, -3, -4

If you want to accommodate non-unit step, it's simplest to define a third parameter as follows:

static void go(final int range, final int step, final int direction) {
    for (int i = 0; i < range; i += step) {
        System.out.println(i * direction);
    }       
}

Then you can do:

        go(10, 3, +1); // 0, 3, 6, 9
        go(10, 3, -1); // 0, -3, -6, -9
polygenelubricants
That's not right; the condition in the second clause of the for loop also differs. And direction could have a magnitude greater than 1.
Borealid
+10  A: 
for (xx = 0; xx != range; xx += moveDirection)
{
    if (hitTestPoint(xx, yy))
    {
        return true;
    }
}

This assumes that moveDirection will be either 1 or -1 for going up or down, respectively. Also, you'll have to slightly change your range for the != to work properly. But, it does cut down on code.

fire.eagle
I'd change the name `moveDirection` to `movementVector` or something, to be clear about what it stores. `moveDirection` sounds too much like an enum or something :)
Porges
True. I was just being lazy and using pre-defined variables so I didn't have to define them myself. :P
fire.eagle
Very elegant! Thank you so much. I am always amazed by all the different ways for loops (or any other loops) can be used.
TandemAdam
@Porges : And movementVector sounds too much like a vector. :) I prefer moveDirection.
Stephen
+1  A: 

From the looks of the code, it doesn't really matter which direction the loop runs -- you're just returning true if hitTestPoint returns true for some value in the range. If that's so, another possibility would be something like:

var start:int = min(0, range);
var stop:int = max(0, range);

for (xx = start; xx!=stop; xx++)
    if (hitTestPoint(xx,yy)
        return true;
Jerry Coffin
If there are multiple values of xx for which hitTestPoint(xx, yy) is true, or especially if hitTestPoint has side-effects, this certainly can change the behavior.
Don Roby
+1  A: 

Another possibility:

int i;
for (i = abs(range), xx = 0; --i >= 0; xx += moveDirection){
  if (hitTestPoint(xx, yy) return true;
}
Mike Dunlavey
This is a good one. It means there is no/less chance of infinite loop, where i is moving in the wrong direction to range.
TandemAdam