下面的代码确实按照我需要的方式工作,但它很丑,过多或其他一些事情。我已经看了公式,并试图写一些解决方案,但我最终得到了类似数量的语句。
在这种情况下,是否有一种数学公式对我有益,或者是否可以接受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;
}
我想到的第一件事基本上与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的哪个值对应于哪个返回值。
我个人喜欢级联三元运算符:
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);
}
我希望我正确理解了逻辑。比如:
public int fightMath (int one, int two)
{
int oneHit = ((one == 3 && two != 1) || (one == 2 && two != 0)) ? 1 : 0;
int twoHit = ((two == 3 && one != 1) || (two == 2 && one != 0)) ? 2 : 0;
return oneHit+twoHit;
}
检查一个击中高或一个击中低不被阻止,同样的球员二。
编辑:算法不完全理解,“命中”奖励时,我没有意识到(谢谢elias):
public int fightMath (int one, int two)
{
int oneAttack = ((one == 3 && two != 1) || (one == 2 && two != 0)) ? 1 : (one >= 2) ? 2 : 0;
int twoAttack = ((two == 3 && one != 1) || (two == 2 && one != 0)) ? 2 : (two >= 2) ? 1 : 0;
return oneAttack | twoAttack;
}
这使用了一点bitmagic(你已经通过在一个整数中保存两个比特信息(low/high & attack/block)来做到这一点):
我没有运行,只是在这里输入,请仔细检查。这个想法肯定有效。
编辑:现在对每个输入进行测试,工作正常。
public int fightMath(int one, int two) {
if(one<2 && two<2){ //both players blocking
return 0; // nobody hits
}else if(one>1 && two>1){ //both players attacking
return 3; // both hit
}else{ // some of them attack, other one blocks
int different_height = (one ^ two) & 1; // is 0 if they are both going for the same height - i.e. blocker wins, and 1 if height is different, thus attacker wins
int attacker = one>1?1:0; // is 1 if one is the attacker, two is the blocker, and 0 if one is the blocker, two is the attacker
return (attacker ^ different_height) + 1;
}
}
或者我应该建议把这两个信息分离成单独的变量?
主要基于上面这样的位操作的代码通常很难维护。