太多'if'陈述?
下面的代码确实工作,我需要它,但它很丑陋,过度或其他一些事情。 我研究过公式并试图写出一些解决方案,但我最终得到了类似的陈述。
在这种情况下,是否有一种数学公式可以使我受益?
为了解释代码,这是一种基于同时回合的游戏..两个玩家每个都有四个动作按钮,结果来自一个数组(0-3),但变量'one'&'two'可以是如果这有助于分配任何东西 结果是,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;
}
如果你不能提出一个公式,你可以使用一个表来获得如此有限的结果:
final int[][] result = new int[][] {
{ 0, 0, 1, 2 },
{ 0, 0, 2, 1 },
{ 2, 1, 3, 3 },
{ 1, 2, 3, 3 }
};
return result[one][two];
由于您的数据集非常小,您可以将所有内容压缩为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}的映射。 每个答案都已经接近如何实现该地图。
此外,您可以在许多答案中看到重述问题的地图,即1个2位数的基数4的数字N(1,2),其中一个是数字1,两个是数字2,并且N = 4 * 1 +两个; N = {0,1,2,...,15} - 十六个不同的值,这很重要。 该函数的输出是一个1位数的基数4数{0,1,2,3} - 4个不同的数值,也很重要。
现在,1位数的基数4数字可以表示为2位数的基数2数字; {0,1,2,3} = {00,01,10,11},所以每个输出只能用2位编码。 从上面可以看出,只有16个不同的输出,所以16 * 2 = 32位就是编码整个地图所必需的; 这可以全部适合1个整数。
常数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。
我不喜欢除JAB之外的任何解决方案。 其他人都不容易阅读代码并理解正在计算的内容 。
下面是我将如何编写这段代码 - 我只知道C#,而不是Java,但是你得到的图片是:
const bool t = true;
const bool f = false;
static readonly bool[,] attackResult = {
{ f, f, t, f },
{ f, f, f, t },
{ f, t, t, t },
{ t, f, t, t }
};
[Flags] enum HitResult
{
Neither = 0,
PlayerOne = 1,
PlayerTwo = 2,
Both = PlayerOne | PlayerTwo
}
static HitResult ResolveAttack(int one, int two)
{
return
(attackResult[one, two] ? HitResult.PlayerOne : HitResult.Neither) |
(attackResult[two, one] ? HitResult.PlayerTwo : HitResult.Neither);
}
现在,它更清楚地说明这里计算的是什么:这强调我们计算谁受到什么攻击,并返回两个结果。
然而,这可能会更好; 该布尔数组有点不透明。 我喜欢桌子查找的方法,但我倾向于用这种方式编写它,以清楚地表明游戏的语义是什么。 也就是说,与其说“零攻击和一个防守不会造成一击”,而不是找到一种让代码更清楚的方式,意味着“低踢攻击和低防守不会造成打击”。 使代码反映游戏的商业逻辑。
链接地址: http://www.djcxy.com/p/36377.html上一篇: Too many 'if' statements?
下一篇: C# Bitwise Operators