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

在这种情况下,是否有一种数学公式对我有益,或者是否可以接受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;
}

当前回答

我没有使用Java的经验,所以可能会有一些错字。请将此代码视为伪代码。

我会选择一个简单的开关。为此,您需要一个单一的数字求值。然而,对于这种情况,由于0 <= one < 4 <= 9和0 <= two < 4 <= 9,我们可以将这两个整型都转换为简单的整型,方法是1乘以10再加上2。然后在结果数字中使用一个开关,就像这样:

public int fightMath(int one, int two) {
    // Convert one and two to a single variable in base 10
    int evaluate = one * 10 + two;

    switch(evaluate) {
        // I'd consider a comment in each line here and in the original code
        // for clarity
        case 0: result = 0; break;
        case 1: result = 0; break;
        case 1: result = 0; break;
        case 2: result = 1; break;
        case 3: result = 2; break;
        case 10: result = 0; break;
        case 11: result = 0; break;
        case 12: result = 2; break;
        case 13: result = 1; break;
        case 20: result = 2; break;
        case 21: result = 1; break;
        case 22: result = 3; break;
        case 23: result = 3; break;
        case 30: result = 1; break;
        case 31: result = 2; break;
        case 32: result = 3; break;
        case 33: result = 3; break;
    }

    return result;
}

还有另一个简单的方法,我只是想指出一个理论代码。然而,我不会使用它,因为它有一些额外的复杂性,你通常不想处理。额外的复杂性来自于以4为基数,因为计数是0、1、2、3、10、11、12、13、20,……

public int fightMath(int one, int two) {
    // Convert one and two to a single variable in base 4
    int evaluate = one * 4 + two;

    allresults = new int[] { 0, 0, 1, 2, 0, 0, 2, 1, 2, 1, 3, 3, 1, 2, 3, 3 };

    return allresults[evaluate];
}

这只是额外的说明,以防我在Java中遗漏了一些东西。在PHP中我会这样做:

function fightMath($one, $two) {
    // Convert one and two to a single variable in base 4
    $evaluate = $one * 10 + $two;

    $allresults = array(
         0 => 0,  1 => 0,  2 => 1,  3 => 2,
        10 => 0, 11 => 0, 12 => 2, 13 => 1,
        20 => 2, 21 => 1, 22 => 3, 23 => 3,
        30 => 1, 31 => 2, 32 => 3, 33 => 3 );

    return $allresults[$evaluate];
}

其他回答

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

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

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

如果你无法想出一个公式,你可以使用一个表格来描述有限的结果:

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:你的答案对于参与人1 P1和参与人2 P2是对称的。这对于格斗游戏来说很有意义,但你也可以利用它来完善你的逻辑。

2:3拍0拍2拍1拍3。这些情况中唯一不包括的情况是0对1和2对3的组合。换句话说,唯一的胜利表是这样的:0击败2,1击败3,2击败1,3击败0。

3:如果0/1人对位,则平局无命中,但如果2/3人对位,则双方均命中

首先,让我们构建一个单向函数,告诉我们是否赢了:

// returns whether we beat our opponent
public boolean doesBeat(int attacker, int defender) {
  int[] beats = {2, 3, 1, 0};
  return defender == beats[attacker];
}

然后我们可以使用这个函数来组合最终的结果:

// returns the overall fight result
// bit 0 = one hits
// bit 1 = two hits
public int fightMath(int one, int two)
{
  // Check to see whether either has an outright winning combo
  if (doesBeat(one, two))
    return 1;

  if (doesBeat(two, one))
    return 2;

  // If both have 0/1 then its hitless draw but if both have 2/3 then they both hit.
  // We can check this by seeing whether the second bit is set and we need only check
  // one's value as combinations where they don't both have 0/1 or 2/3 have already
  // been dealt with 
  return (one & 2) ? 3 : 0;
}

虽然这可以说比许多答案中提供的查找表更复杂,而且可能更慢,但我相信这是一种更好的方法,因为它实际上封装了代码的逻辑,并向阅读您代码的任何人描述它。我认为这是一个更好的实现。

(这是一段时间以来,我做任何Java,所以抱歉,如果语法错误,希望它仍然是可理解的,如果我有一点错误)

顺便说一下,0-3显然意味着什么;它们不是任意的值,所以给它们命名会有帮助。

您可以创建包含结果的矩阵

int[][] results = {{0, 0, 1, 2}, {0, 0, 2, 1},{2, 1, 3, 3},{2, 1, 3, 3}};

当你想要获得价值时,你就会使用

public int fightMath(int one, int two) {
  return this.results[one][two]; 
}

使用常量或枚举使代码更具可读性 尝试将代码拆分为更多的函数 试着利用问题的对称性

这里是一个建议,但在这里使用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并不擅长表达这类数据类型。