下面的代码确实按照我需要的方式工作,但它很丑,过多或其他一些事情。我已经看了公式,并试图写一些解决方案,但我最终得到了类似数量的语句。

在这种情况下,是否有一种数学公式对我有益,或者是否可以接受16个if语句?

为了解释代码,这是一款基于同时回合制的游戏。两名玩家各有四个操作按钮,结果来自一个数组(0-3),但变量“1”和“2”可以赋值任何东西,如果这有帮助的话。结果是,0 =双方都不赢,1 = p1赢,2 = p2赢,3 =双方都赢。

public int fightMath(int one, int two) {

    if(one == 0 && two == 0) { result = 0; }
    else if(one == 0 && two == 1) { result = 0; }
    else if(one == 0 && two == 2) { result = 1; }
    else if(one == 0 && two == 3) { result = 2; }
    else if(one == 1 && two == 0) { result = 0; }
    else if(one == 1 && two == 1) { result = 0; }
    else if(one == 1 && two == 2) { result = 2; }
    else if(one == 1 && two == 3) { result = 1; }
    else if(one == 2 && two == 0) { result = 2; }
    else if(one == 2 && two == 1) { result = 1; }
    else if(one == 2 && two == 2) { result = 3; }
    else if(one == 2 && two == 3) { result = 3; }
    else if(one == 3 && two == 0) { result = 1; }
    else if(one == 3 && two == 1) { result = 2; }
    else if(one == 3 && two == 2) { result = 3; }
    else if(one == 3 && two == 3) { result = 3; }

    return result;
}

当前回答

既然您更喜欢嵌套的if条件,这里有另一种方法。 注意,它没有使用result成员,也没有改变任何状态。

public int fightMath(int one, int two) {
    if (one == 0) {
      if (two == 0) { return 0; }
      if (two == 1) { return 0; }
      if (two == 2) { return 1; }
      if (two == 3) { return 2; }
    }   
    if (one == 1) {
      if (two == 0) { return 0; }
      if (two == 1) { return 0; }
      if (two == 2) { return 2; }
      if (two == 3) { return 1; }
    }
    if (one == 2) {
      if (two == 0) { return 2; }
      if (two == 1) { return 1; }
      if (two == 2) { return 3; }
      if (two == 3) { return 3; }
    }
    if (one == 3) {
      if (two == 0) { return 1; }
      if (two == 1) { return 2; }
      if (two == 2) { return 3; }
      if (two == 3) { return 3; }
    }
    return DEFAULT_RESULT;
}

其他回答

((two&2)*(1+((one^two)&1))+(one&2)*(2-((one^two)&1)))/2

我想到的第一件事基本上与Francisco Presencia给出的答案相同,但有所优化:

public int fightMath(int one, int two)
{
    switch (one*10 + two)
    {
    case  0:
    case  1:
    case 10:
    case 11:
        return 0;
    case  2:
    case 13:
    case 21:
    case 30:
        return 1;
    case  3:
    case 12:
    case 20:
    case 31:
        return 2;
    case 22:
    case 23:
    case 32:
    case 33:
        return 3;
    }
}

你可以进一步优化它,使最后的情况(3)为默认情况:

    //case 22:
    //case 23:
    //case 32:
    //case 33:
    default:
        return 3;

此方法的优点是,与其他一些建议的方法相比,更容易看到1和2的哪个值对应于哪个返回值。

由于您的数据集非常小,您可以将所有内容压缩为1个长整数并将其转换为公式

public int fightMath(int one,int two)
{
   return (int)(0xF9F66090L >> (2*(one*4 + two)))%4;
}

更多的位变体:

这利用了所有东西都是2的倍数这一事实

public int fightMath(int one,int two)
{
   return (0xF9F66090 >> ((one << 3) | (two << 1))) & 0x3;
}

神奇常数的起源

我能说什么呢?世界需要魔法,有时某些事情的可能性需要它的创造。

解决OP问题的函数的本质是从2个数字(1,2),域{0,1,2,3}到范围{0,1,2,3}的映射。每个答案都涉及了如何实现该映射。

此外,您可以在许多答案中看到问题的重述,即12个以4为基数的2位数字N(1,2)的映射,其中1是数字1,2是数字2,N = 4* 1 + 2;N ={0,1,2,…,15}——16个不同的值,这很重要。函数的输出是一个以4为基数的1位数字{0,1,2,3}——4个不同的值,这也很重要。

现在,1位以4为底的数可以表示为2位以2为底的数;{0,1,2,3} ={00,01,10,11},因此每个输出只能用2位编码。从上面来看,只有16种不同的输出可能,所以16*2 = 32位是编码整个地图所必需的;这些都可以装进一个整数。

常数M是映射M的编码,其中M(0)以位M[0:1]编码,M(1)以位M[2:3]编码,M (n)以位M[n*2:n*2+1]编码。

剩下的就是索引和返回常量的右边部分,在这种情况下,你可以将M右移2*N次,并取2个最低有效位,即(M >> 2*N) & 0x3。表达式(one << 3)和(two << 1)只是相乘,同时注意到2*x = x << 1和8*x = x << 3。

您可以使用一个开关大小写,而不是多个if

还要提到的是,因为你有两个变量,那么你必须合并这两个变量,以使用它们在开关

检查这个Java开关语句来处理两个变量?

我个人喜欢级联三元运算符:

int result = condition1
    ? result1
    : condition2
    ? result2
    : condition3
    ? result3
    : resultElse;

但在你的情况下,你可以使用:

final int[] result = new int[/*16*/] {
    0, 0, 1, 2,
    0, 0, 2, 1,
    2, 1, 3, 3,
    1, 2, 3, 3
};

public int fightMath(int one, int two) {
    return result[one*4 + two];
}

或者,你可以注意到比特的模式:

one   two   result

section 1: higher bits are equals =>
both result bits are equals to that higher bits

00    00    00
00    01    00
01    00    00
01    01    00
10    10    11
10    11    11
11    10    11
11    11    11

section 2: higher bits are different =>
lower result bit is inverse of lower bit of 'two'
higher result bit is lower bit of 'two'

00    10    01
00    11    10
01    10    10
01    11    01
10    00    10
10    01    01
11    00    01
11    01    10

所以你可以使用魔法:

int fightMath(int one, int two) {
    int b1 = one & 2, b2 = two & 2;
    if (b1 == b2)
        return b1 | (b1 >> 1);

    b1 = two & 1;

    return (b1 << 1) | (~b1);
}