下面的代码确实按照我需要的方式工作,但它很丑,过多或其他一些事情。我已经看了公式,并试图写一些解决方案,但我最终得到了类似数量的语句。
在这种情况下,是否有一种数学公式对我有益,或者是否可以接受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;
}
除了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);
}
现在,这里计算的内容更加清楚了:这强调了我们正在计算谁受到了什么攻击,并返回两个结果。
然而,这可能会更好;布尔数组有点不透明。我喜欢表格查找方法,但我更倾向于以一种能够明确游戏语义的方式来编写它。也就是说,与其“攻击为零,防御为一,结果是没有命中”,不如找到一种方法,让代码更清楚地暗示“低踢攻击和低阻挡防御,结果是没有命中”。让代码反映游戏的业务逻辑。
说实话,每个人都有自己的代码风格。我没想到性能会受到太大影响。如果您比使用开关箱版本更能理解这一点,那么请继续使用此版本。
您可以嵌套if语句,因此最后的if检查可能会略微提高性能,因为它不会经过那么多if语句。但是在你的java基础课程中,它可能不会有什么好处。
else if(one == 3 && two == 3) { result = 3; }
所以,与其…
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; }
你会做……
if(one == 0)
{
if(two == 0) { result = 0; }
else if(two == 1) { result = 0; }
else if(two == 2) { result = 1; }
else if(two == 3) { result = 2; }
}
按照你的喜好重新格式化。
这并没有使代码看起来更好,但我相信它可能会加快一点速度。
一个好的观点是将规则定义为文本,这样你就可以更容易地推导出正确的公式。这是从laalto漂亮的数组表示中提取出来的:
{ 0, 0, 1, 2 },
{ 0, 0, 2, 1 },
{ 2, 1, 3, 3 },
{ 1, 2, 3, 3 }
这里我们有一些一般性的评论,但你应该用规则来描述它们:
if(one<2) // left half
{
if(two<2) // upper left half
{
result = 0; //neither hits
}
else // lower left half
{
result = 1+(one+two)%2; //p2 hits if sum is even
}
}
else // right half
{
if(two<2) // upper right half
{
result = 1+(one+two+1)%2; //p1 hits if sum is even
}
else // lower right half
{
return 3; //both hit
}
}
当然,您可以将其压缩为更少的代码,但理解您编写的代码而不是寻找紧凑的解决方案通常是一个好主意。
if((one<2)&&(two<2)) result = 0; //top left
else if((one>1)&&(two>1)) result = 3; //bottom right
else result = 1+(one+two+((one>1)?1:0))%2; //no idea what that means
对复杂的p1/p2点击的一些解释会很棒,看起来很有趣!
我想到的第一件事基本上与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的哪个值对应于哪个返回值。