6

Consider the following code :

if (xPoint > 0 && yPoint > 0) {
    m_navigations = Directions.SouthEast;
}
else if (xPoint > 0 && yPoint < 0) {
    m_navigations = Directions.NorthEast;
}
else if (xPoint < 0 && yPoint > 0) {
    m_navigations = Directions.SouthWest;
}
else if (xPoint < 0 && yPoint < 0) {
    m_navigations = Directions.NorthWest;
}
else if (xPoint == 0 && yPoint < 0) {
    m_navigations = Directions.North;
}
else if (xPoint == 0 && yPoint > 0) {
    m_navigations = Directions.South;
}
else if (xPoint > 0 && yPoint == 0) {
    m_navigations = Directions.East;
}
else if (xPoint < 0 && yPoint == 0) {
    m_navigations = Directions.West;
}

This is quite ugly , and I want to use switch case , but how can I use switch with 2 variables ?

I thought about something like this - the answer of @Frits van Campen , but I need to use > and < operators ...

Thanks

Community
  • 1
  • 1
JAN
  • 21,236
  • 66
  • 181
  • 318

6 Answers6

6

You can do everything with enums. I created examples for the first two values, you can continue with the rest.

public enum Direction
{
    SouthEast(1,1),
    NorthEast(1,-1);

    int _xPoint, _yPoint;

    Direction(int xPoint, int yPoint)
    {
        _xPoint = xPoint;
        _yPoint = yPoint;
    }

    public static Direction getDirectionByPoints(int xPoint, int yPoint)
    {
        for (Direction direction : Direction.values())
        {
            if(   Integer.signum(xPoint) == direction._xPoint 
               && Integer.signum(yPoint) == direction._yPoint )
            {
                return direction;
            }
        }
        throw new IllegalStateException("No suitable Direction found");
    }
}

So you can just call:

m_navigations = Direction.getDirectionByPoints(xPoint,yPoint);
Aubin
  • 14,617
  • 9
  • 61
  • 84
danieln
  • 4,795
  • 10
  • 42
  • 64
2

Use signum to get -1, 0 or 1 on the direction like this:

String direction = Integer.signum(xPoint)+","+Integer.signum(yPoint);
switch(direction){
  case "1,1": 
    m_navigations = Directions.SouthEast;
    break;
  case "-1,0"
    m_navigations = Directions.West;
    break;

etc..
}
bluevoid
  • 1,274
  • 13
  • 29
  • Beware that using `String`s in `case` statement is only available after Java 1.7+ – Chan Apr 13 '13 at 18:32
  • I know, the answer from Frits van Campen that @ron refers to uses strings in the switch aswell, so I assume that ron knows that. – bluevoid Apr 13 '13 at 18:41
2

The simplest and easiest solution is to use multidimensional arrays.

public class CalculateDirections {
    private final static Directions DIRECTION_MAP[][] = {
        {Directions.NorthWest, Directions.North, Directions.NorthEast},
        {Directions.West, null, Directions.East},
        {Directions.SouthWest, Directions.South, Directions.SouthEast},
    };

    public static void main(String[] args) {
        int x = Integer.valueOf(args[0]);
        int y = Integer.valueOf(args[1]);

        int signumX = Integer.signum(x);
        int signumY = Integer.signum(y);
        Directions direction = DIRECTION_MAP[signumY + 1][signumX + 1];

        System.out.println(direction);
    }
}

enum Directions {
    SouthEast, NorthEast, SouthWest, NorthWest, North, South, East, West
}

There are several advantages:

  • No if/else cascades which take some runtime and are hard to manage.
  • No creation of temporary Strings. In a tight game loop this may be important.
  • No linear search through lists or arrays.
A.H.
  • 63,967
  • 15
  • 92
  • 126
1

Similar to other answers but without strings. Just for fun :-)

public Directions getDirection(int xPoint, int yPoint) {
    int num = 8 * (xPoint == 0 ? 0 : xPoint > 0 ? 1 : 2);
    num += yPoint == 0 ? 0 : yPoint > 0 ? 1 : 2;
    switch (num) {
    case 01:
        return Directions.South;
    case 02:
        return Directions.North;
    case 010:
        return Directions.East;
    case 011:
        return Directions.SouthEast;
    case 012:
        return Directions.NorthEast;
    case 020:
        return Directions.West;
    case 021:
        return Directions.SouthWest;
    case 022:
        return Directions.NorthWest;
    }
    return Directions.None;
}
janos
  • 120,954
  • 29
  • 226
  • 236
0
boolean xNeg  = xPoint  < 0;
boolean yNeg  = yPoint  < 0;
boolean xZero = xPoint == 0;
boolean yZero = yPoint == 0;

We have four bits, we have 2^4 possibilities, an array of Directions may do the rest...

int index =
   ((xNeg ?1:0)<<3)|
   ((yNeg ?1:0)<<2)|
   ((xZero?1:0)<<1)|
   ((yZero?1:0)<<0);
Directions dir = directions[index];

with directions a static final array of Directions initialized at class loading time.

static final Directions[] directions = {
   Direction.NorthEast, // false, false, false, false ==> x  > 0 && y  > 0
   Direction.East,      // false, false, false, true  ==> x  > 0 && y == 0
   Direction.North,     // false, false, true , false ==> x == 0 && y  > 0
   ...
}

Indexing an array with an integer computed from ternaries, shift and or operators is less CPU consuming than a string concatenation used in a string switch and works well from Java 1.0.

Aubin
  • 14,617
  • 9
  • 61
  • 84
0

At the moment :

    String direction = Integer.signum(xPoint) + "|" + Integer.signum(yPoint);
    switch(direction)
    {
        case "1|1":
            {m_navigations = Directions.SouthEast; break;}
        case "1|-1":
            {m_navigations = Directions.NorthEast; break;}
        case "-1|1":
            {m_navigations = Directions.SouthWest; break;}
        case "-1|-1":
            {m_navigations = Directions.NorthWest; break;}
        case "0|-1":
            {m_navigations = Directions.North; break;}
        case "0|1":
            {m_navigations = Directions.South; break;}
        case "1|0":
            {m_navigations = Directions.East; break;}
        case "-1|0":
            {m_navigations = Directions.West; break;}
        default: break;         
    }

Now I'll try what @danieln has suggested .

JAN
  • 21,236
  • 66
  • 181
  • 318