JAN
JAN

Reputation: 21865

Switch case for two INT variables

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

Upvotes: 6

Views: 6326

Answers (6)

A.H.
A.H.

Reputation: 66273

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.

Upvotes: 2

janos
janos

Reputation: 124704

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;
}

Upvotes: 1

JAN
JAN

Reputation: 21865

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 .

Upvotes: 0

danieln
danieln

Reputation: 4973

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);

Upvotes: 6

Aubin
Aubin

Reputation: 14863

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.

Upvotes: 0

bluevoid
bluevoid

Reputation: 1359

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..
}

Upvotes: 2

Related Questions