다른 사람들은 이미 초기 아이디어 인 행렬 방법을 제안했지만 if 문을 통합하는 것 외에도 제공된 인수가 예상 범위에 있는지 확인하고 내부 반환 (일부 코딩)을 사용하여 일부 내용을 피할 수 있습니다 내가 한 함수에 대해 한 번의 종료 지점을 시행하는 것으로 보았지만 여러 리턴이 화살표 코딩을 피하는 데 매우 유용하며 Java에서 예외가 발생함에 따라 어쨌든 그러한 규칙을 엄격하게 시행하는 데는 아무런 의미가 없습니다. 메소드 내에서 발생하는 잡히지 않은 예외는 어쨌든 가능한 종료점이므로). 중첩 스위치 문은 가능하지만 여기에서 확인하는 작은 값 범위의 경우 문이 더 작고 성능 차이가 많이 발생하지 않는지 확인합니다.
public int fightMath(int one, int two) {
if (one > 3 || one < 0 || two > 3 || two < 0) {
throw new IllegalArgumentException("Result is undefined for arguments outside the range [0, 3]");
}
if (one <= 1) {
if (two <= 1) return 0;
if (two - one == 2) return 1;
return 2; // two can only be 3 here, no need for an explicit conditional
}
// one >= 2
if (two >= 2) return 3;
if (two == 1) return 1;
return 2; // two can only be 0 here
}
그렇지 않으면 입력-> 결과 매핑의 일부가 불규칙하기 때문에 읽기가 어렵습니다. 나는 그 단순성과 매트릭스가 시각적으로 의미있게 이해되도록 매트릭스를 선호하는 방법 때문에 매트릭스 스타일을 선호합니다.
int[][] results = {{0, 0, 1, 2},
{0, 0, 2, 1},
{2, 1, 3, 3},
{2, 1, 3, 3}};
업데이트 : 차단 / 타격에 대한 언급을 감안할 때 입력 및 결과에 대해 적절한 / 속성 보유 열거 유형을 사용하고 차단을 설명하기 위해 결과를 약간 수정하는 기능에 대한 근본적인 변화가 있습니다. 읽을 수있는 기능.
enum MoveType {
ATTACK,
BLOCK;
}
enum MoveHeight {
HIGH,
LOW;
}
enum Move {
// Enum members can have properties/attributes/data members of their own
ATTACK_HIGH(MoveType.ATTACK, MoveHeight.HIGH),
ATTACK_LOW(MoveType.ATTACK, MoveHeight.LOW),
BLOCK_HIGH(MoveType.BLOCK, MoveHeight.HIGH),
BLOCK_LOW(MoveType.BLOCK, MoveHeight.LOW);
public final MoveType type;
public final MoveHeight height;
private Move(MoveType type, MoveHeight height) {
this.type = type;
this.height = height;
}
/** Makes the attack checks later on simpler. */
public boolean isAttack() {
return this.type == MoveType.ATTACK;
}
}
enum LandedHit {
NEITHER,
PLAYER_ONE,
PLAYER_TWO,
BOTH;
}
LandedHit fightMath(Move one, Move two) {
// One is an attack, the other is a block
if (one.type != two.type) {
// attack at some height gets blocked by block at same height
if (one.height == two.height) return LandedHit.NEITHER;
// Either player 1 attacked or player 2 attacked; whoever did
// lands a hit
if (one.isAttack()) return LandedHit.PLAYER_ONE;
return LandedHit.PLAYER_TWO;
}
// both attack
if (one.isAttack()) return LandedHit.BOTH;
// both block
return LandedHit.NEITHER;
}
더 높은 높이의 블록 / 공격을 추가하고 싶다면 열거 형 만 추가하면 함수 자체를 변경할 필요조차 없습니다. 추가 유형의 이동을 추가하려면 아마도 기능을 수정해야합니다. 또한, EnumSet
들 예를 들어 주요 열거의 속성으로 추가 열거 형을 사용하는 것보다 더 확장 할 수 있습니다 EnumSet<Move> attacks = EnumSet.of(Move.ATTACK_HIGH, Move.ATTACK_LOW, ...);
후 attacks.contains(move)
가 아니라 move.type == MoveType.ATTACK
사용하지만, EnumSet
의 아마 직접 동등한 검사보다 약간 느립니다.
성공적인 블록이 카운터를 초래하는 경우를 들어, 대체 할 수 if (one.height == two.height) return LandedHit.NEITHER;
와 함께
if (one.height == two.height) {
// Successful block results in a counter against the attacker
if (one.isAttack()) return LandedHit.PLAYER_TWO;
return LandedHit.PLAYER_ONE;
}
또한 일부 if
문을 삼항 연산자 ( boolean_expression ? result_if_true : result_if_false
)로 대체 하면 코드가 더 간결 return one.isAttack() ? LandedHit.PLAYER_TWO : LandedHit.PLAYER_ONE;
해지지 만 (예 : 앞의 블록에있는 코드가 될 수 있음 ) 읽기 어려운 원 라이너로 이어질 수 있습니다. ' 더 복잡한 분기에 권장하지 않습니다.