下面的代码确实按照我需要的方式工作,但它很丑,过多或其他一些事情。我已经看了公式,并试图写一些解决方案,但我最终得到了类似数量的语句。
在这种情况下,是否有一种数学公式对我有益,或者是否可以接受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;
}
这使用了一点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;
}
}
或者我应该建议把这两个信息分离成单独的变量?
主要基于上面这样的位操作的代码通常很难维护。
我想到的第一件事基本上与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型仍然有点难看:
static final int BLOCK_HIGH = 0;
static final int BLOCK_LOW = 1;
static final int ATTACK_HIGH = 2;
static final int ATTACK_LOW = 3;
public static int fightMath(int one, int two) {
boolean player1Wins = handleAttack(one, two);
boolean player2Wins = handleAttack(two, one);
return encodeResult(player1Wins, player2Wins);
}
private static boolean handleAttack(int one, int two) {
return one == ATTACK_HIGH && two != BLOCK_HIGH
|| one == ATTACK_LOW && two != BLOCK_LOW
|| one == BLOCK_HIGH && two == ATTACK_HIGH
|| one == BLOCK_LOW && two == ATTACK_LOW;
}
private static int encodeResult(boolean player1Wins, boolean player2Wins) {
return (player1Wins ? 1 : 0) + (player2Wins ? 2 : 0);
}
使用结构化类型作为输入和输出会更好。输入实际上有两个字段:位置和类型(阻挡或攻击)。输出也有两个字段:player1Wins和player2Wins。将其编码为单个整数会使代码更难阅读。
class PlayerMove {
PlayerMovePosition pos;
PlayerMoveType type;
}
enum PlayerMovePosition {
HIGH,LOW
}
enum PlayerMoveType {
BLOCK,ATTACK
}
class AttackResult {
boolean player1Wins;
boolean player2Wins;
public AttackResult(boolean player1Wins, boolean player2Wins) {
this.player1Wins = player1Wins;
this.player2Wins = player2Wins;
}
}
AttackResult fightMath(PlayerMove a, PlayerMove b) {
return new AttackResult(isWinningMove(a, b), isWinningMove(b, a));
}
boolean isWinningMove(PlayerMove a, PlayerMove b) {
return a.type == PlayerMoveType.ATTACK && !successfulBlock(b, a)
|| successfulBlock(a, b);
}
boolean successfulBlock(PlayerMove a, PlayerMove b) {
return a.type == PlayerMoveType.BLOCK
&& b.type == PlayerMoveType.ATTACK
&& a.pos == b.pos;
}
不幸的是,Java并不擅长表达这类数据类型。
感谢@Joe Harper,因为我最终使用了他的答案的变体。为了进一步瘦身,每4个结果中有2个是相同的,我进一步瘦身。
我可能会在某个时候回到这个问题上,但如果没有由多个if语句引起的主要阻力,那么我现在就保留这个问题。我将进一步研究表格矩阵和开关语句解决方案。
public int fightMath(int one, int two) {
if (one === 0) {
if (two === 2) { return 1; }
else if(two === 3) { return 2; }
else { return 0; }
} else if (one === 1) {
if (two === 2) { return 2; }
else if (two === 3) { return 1; }
else { return 0; }
} else if (one === 2) {
if (two === 0) { return 2; }
else if (two === 1) { return 1; }
else { return 3; }
} else if (one === 3) {
if (two === 0) { return 1; }
else if (two === 1) { return 2; }
else { return 3; }
}
}