최대 값을 초과하지 않고 어떻게 변수를 증가시킬 수 있습니까?


89

저는 학교를위한 간단한 비디오 게임 프로그램을 작업 중이며 해당 메서드가 호출되면 플레이어가 15 체력 포인트를 얻는 메서드를 만들었습니다. 나는 건강을 최대 100으로 유지해야하고이 시점에서 제한된 프로그래밍 능력으로 나는 이와 같은 일을하고있다.

public void getHealed(){
    if(health <= 85)
        health += 15;
    else if(health == 86)
        health += 14;
    else if(health == 87)
    health += 13; 
}// this would continue so that I would never go over 100

나는 내 구문이 완벽하지 않다는 것을 이해하지만 내 질문은 더 나은 방법이 될 수 있다는 것입니다.

이를 포화 산술 이라고 합니다.


7
참고로이 방법에 대해 다른 이름을 선택하겠습니다. Java 표준 (및 내가 아는 대부분의 다른 언어)에 따라 "get"으로 시작하는 메서드 이름은 값을 반환해야하며 아무것도 변경하지 않아야합니다. 마찬가지로 "set"로 시작하는 메서드 이름은 값을 변경해야하며 일반적으로 아무것도 반환하지 않습니다.
Darrel Hoffman 2013 년

답변:


226

그냥 할 것입니다. 기본적으로 최소 100 (최대 체력)과 추가 점수 15 점 사이의 체력이 필요합니다. 사용자의 건강이 100을 초과하지 않도록합니다.

public void getHealed() {
    health = Math.min(health + 15, 100);
}

히트 포인트가 0 아래로 떨어지지 않도록 유사한 함수를 사용할 수 있습니다 Math.max..

public void takeDamage(int damage) {
    if(damage > 0) {
        health = Math.max(health - damage, 0);
    }
}

71

건강에 15 만 더하면됩니다.

health += 15;
if(health > 100){
    health = 100;
}

그러나 bland가 언급했듯이 때때로 멀티 스레딩 (한 번에 여러 코드 블록 실행)을 사용하면 어떤 시점 에서든 상태가 100을 넘으면 문제가 발생할 수 있으며 상태 속성을 여러 번 변경하는 것도 좋지 않을 수 있습니다. 이 경우 다른 답변에서 언급했듯이 이렇게 할 수 있습니다.

if(health + 15 > 100) {
    health = 100;
} else {
    health += 15;
}

9
절대로 넘어가도록 허용해서는 안되며, 이는 캐릭터의 체력이 정의 된 최대 체력 (100) 이하로 가정되는 경쟁 조건과 같은 새로운 문제를 일으킬 수 있습니다. 이 수준의 프로젝트에서는 가능성이 낮지 만 초기에 모범 사례를 시행해야합니다.
bland

6
@bland이 접근 방식을 사용하는 경우 이러한 경쟁 조건을 피하는 방법은 임시 변수를 사용하여 새 건강 값을 저장 한 다음 필요한 경우 동기화를 통해 한 위치에이 새로운 건강 값으로 건강을 설정하는 것입니다.

13
@bland : 경쟁 조건은 멀티 스레딩 일 때만 관련됩니다. 그리고 그가 다중 스레딩을 수행하고 있다면 (나는 매우 의심 스럽습니다) 에 대한 모든 액세스를 잠 그거나 하나의 스레드에서만 액세스 health되는지 확인하는 것 health입니다. "건강이 100을 넘도록 허용해서는 안된다" 라는 제약 은 현실적이지 않습니다.
BlueRaja-Danny Pflughoeft 2013 년

@ BlueRaja-DannyPflughoeft 나는이 프로젝트에서 가능성이 낮다고 말했습니다. 일반적으로 잠금은 항상 사용되는 것은 아니며 최대 값이있는 경우 게임 또는 기타 엄격하게 준수해야합니다. 예 : 이벤트가 속성의 변경과 연결되어 있고 백분율을 사용하는 경우 이제 처리를 크게 왜곡하고 두 번 호출 한 것입니다. 나는 여기에서 일반적으로 유지하고 OP 학습을 보장하려고 노력하고 있습니다.이 답변은 작동하지만 학생에게 너무 좁고 구체적이라고 생각합니다. 큰 그림을 생각하지 않도록 강요 할 것입니다.
bland

@Bob 나는이 간단한 일에는 불필요하다고 생각합니다.
Math chiller

45

int위의 각각에 대해 별도의 케이스가 필요하지 않습니다 85. 하나만 else있으면 건강이 이미 86이상이면으로 직접 설정하십시오 100.

if(health <= 85)
    health += 15;
else
    health = 100;

25
나에게 너무 많은 매직 넘버 (100 개 허용을 고려하더라도)-15에서 16으로 변경할 때 85를 조정해야합니다. 85를 최소한 100 - 15(또는 100 -HEALED_HEALTH)으로 변경하면 개선되지 않습니까?
Maciej Piechotka 2013 년

37

나는이 일을 관용적, 객체 지향 방법은을 가지고 생각 setHealthCharacter클래스입니다. 해당 메서드의 구현은 다음과 같습니다.

public void setHealth(int newValue) {
    health = Math.max(0, Math.min(100, newValue))
}

이렇게하면 설정에 관계없이 체력이 0 미만 또는 100 이상으로 떨어지지 않습니다.


귀하의 getHealed()구현은 그냥이 될 수 있습니다 :

public void getHealed() {
    setHealth(getHealth() + 15);
}

방법 Character을 갖는 것이 의미가 있는지 여부 getHealed()는 독자에게 맡겨진 연습입니다. :)


5
+1 : 이것은 객체 지향 방식으로이를 수행하는 좋은 방법입니다! 내가 제안 할 수있는 유일한 것은 (그리고 이것은 아마도 독자에게 맡겨 질 것입니다 ) 각각 당신의 메소드를 호출하는 두 개의 메소드 ( heal(int hp)damage(int hp))를 갖는 setHealth(int newValue)것입니다.
Chris Forrence 2013 년

18
라이브러리 함수 호출에있어 문제점은 무엇입니까? 명명 된 함수로서 조건부 논리보다 의도를 더 명확하게 표현합니다.
erickson

2
또한 많은 라이브러리 함수 (그리고 아마도 이러한 함수)가 실제로 내장되어 있으며 호출을 전혀 수행하지 않습니다.
크리스

2
@Matteo 잘못된 대답-라이브러리 함수가 내부적으로 똑같은 일을 할 가능성이 큽니다. 그렇다면 왜 자신을 반복하고 코드를 오염 시키나요? 라이브러리 함수를 사용하지 않는 것은 DRY의 기본 원칙을 따르지 않습니다.
NickG

2
@Matteo 이것은 if. 이것은 자신이 발에 총을 쏘는 것을 방지하기위한 것입니다. 너무 장황한 경우 정적 가져 오기를 사용하십시오. 그러면 다음과 같이 표시됩니다. health = max(0, min(100, newValue)) 그래도 읽을 수없는 경우 다음과 같이 이름이 지정된 메서드로 추출합니다 clamp.health = clamp(0, 100, newValue)
Daniel Kaplan

14

나는 더 재사용 가능한 코드 조각을 제공 할 것입니다. 가장 작은 것은 아니지만 어떤 양으로도 사용할 수 있으므로 여전히 말할 가치가 있습니다.

health += amountToHeal;
if (health >= 100) 
{ 
    health = 100;
}

게임에 통계를 추가하려면 100을 maxHealth 변수로 변경할 수도 있으므로 전체 방법은 다음과 같을 수 있습니다.

private int maxHealth = 100;
public void heal(int amountToHeal)
{
    health += amountToHeal;
    if (health >= maxHealth) 
    { 
        health = maxHealth;
    }
}

편집하다

추가 정보

플레이어가 손상을 입었을 때도 똑같이 할 수 있지만 어쨌든 0이되기 때문에 minHealth가 필요하지 않습니다. 이렇게하면 동일한 코드로 모든 양을 손상시키고 치유 할 수 있습니다.


1
minHealth:) ... D & D, 예를 들어 말을, 음수가 될 수도
JYelton

1
여기에 가장 좋은 답변이 있습니다.
Glitch Desire 2013 년

@JYelton, 그래 당신은 if 문에서 (health <= 0)라고 말할 것입니다. 당신은 당신이 원하는대로 그것을 처리 할 수 ​​있습니다. 만약 당신이 그들이 생명을 가지기를 원한다면 당신은 당신이 lifeCount에서 1을 빼거나 그들이 잃는다면 그것을 처리 할 수 ​​있습니다. 당신이 원한다면 그들이 가진 -HP의 양으로 새로운 삶을 시작하게 할 수도 있습니다. 이 코드를 거의 모든 곳에 붙여 넣을 수 있으며 작업을 잘 수행 할 수 있습니다. 그것이이 답변의 요점이었습니다.
5tar-Kaster

10
health = health < 85 ? health + 15 : 100;

4

도우미 클래스에서 정적 메서드를 만들 것입니다. 이렇게하면 일부 경계에 맞아야하는 모든 값에 대해 코드를 반복하는 대신 하나의 다목적 방법을 사용할 수 있습니다. 최소값과 최대 값을 정의하는 두 개의 값과 해당 범위 내에서 고정되는 세 번째 값을 허용합니다.

class HelperClass
{
    // Some other methods

    public static int clamp( int min, int max, int value )
    {
        if( value > max )
            return max;
        else if( value < min )
            return min;
        else
            return value;
    }
}

귀하의 경우에는 어딘가에 최소 및 최대 건강을 선언합니다.

final int HealthMin = 0;
final int HealthMax = 100;

그런 다음 최소, 최대 및 조정 된 체력을 전달하는 함수를 호출합니다.

health = HelperClass.clamp( HealthMin, HealthMax, health + 15 );

3

나는 이것이 학교 프로젝트라는 것을 알고 있지만 나중에 게임을 확장하고 치유력을 업그레이드하려면 다음과 같이 함수를 작성하십시오.

public void getHealed(healthPWR) {
    health = Math.min(health + healthPWR, 100);
}

함수를 호출합니다.

getHealed(15);
getHealed(25);

...기타...

또한 함수에 국한되지 않은 변수를 생성하여 최대 HP를 생성 할 수 있습니다. 사용중인 언어를 모르기 때문에 구문이 잘못되었을 수 있으므로 예제를 표시하지 않겠습니다.


2

어쩌면 이거?

public void getHealed()
{
  if (health <= 85)
  {
    health += 15;
  } else
  {
    health = 100;
  }
}

2

건방하고 코드를 한 줄에 맞추고 싶다면 삼항 연산자를 사용할 수 있습니다 .

health += (health <= 85) ? 15 : (100 - health);

어떤 사람들은 가독성이 나쁘기 때문에이 구문에 눈살을 찌푸 릴 것입니다!


4
내가 찾아 health = (health <= 85)?(health+15):100(당신이 정말로 삼항 연산자를 사용하려는 경우) 더 읽기
마테오

1

나는 이것이 할 것이라고 믿는다

if (health >= 85) health = 100;
else health += 15;

설명:

  • 치유 간격이 15 이하이면 체력이 100이됩니다.

  • 그렇지 않으면 간격이 15보다 크면 건강에 15가 추가됩니다.

예를 들어 체력이 83이면 100이 아닌 98이됩니다.


요청자의 질문을 해결하기 위해 이것이 어떻게 작동하는지 확장 할 수 있습니까?
롬 요 미

치유의 간격이 15 이하이면 체력이 100이되고, 차이가 15보다 크면 체력에 15가 추가됩니다. 예를 들어 건강은 83이되고 100이되지는 않습니다. 특정 문제가 있으면 알려주세요. 의견을 보내 주셔서 감사합니다.
MarmiK

&& health < 100조건은 불필요하다. 100이면 100으로 설정되며 변경되지 않습니다. 그것을 얻을 수 있다면 당신이 필요 했어 유일한 이유는 어떻게 든> (100)이며, 우리는 치유가 100 아래로 당신을 줄이기 위해 싶지 않아
대럴 호프만

나는 게임이 여분의 건강을 제공하지 않는 권리 경우에 당신이 생각 @DarrelHoffman 100 + 당신은 바로, 나는 :) 내 대답을 수정하면 감사 한있다
MarmiK

1

스레드 안전을 원하면 동기화 된 블록을 사용하는 대신이 방법을 사용합니다.

원자 compareAndSet은 오버 헤드없이 동기화 된 것과 동일한 결과를 얻습니다.

AtomicInteger health = new AtomicInteger();

public void addHealth(int value)
{
    int original = 0;
    int newValue = 0;
    do
    {
        original = health.get();
        newValue = Math.min(100, original + value);
    }
    while (!health.compareAndSet(original, newValue));
}

1

모듈러스 연산자를 사용하는 가장 간단한 방법입니다.

건강 = (건강 + 50) % 100;

건강은 절대 100을 초과하지 않습니다.


하지만 health100 일 때이 작업을 수행하면 체력 50으로 끝납니다.
Parziphal

0
   private int health;
    public void Heal()
    {
        if (health > 85)
            health = 100;
        else
            health += 15;
    }
    public void Damage()
    {
        if (health < 15)
            health = 0;
        else
            health -= 15;
    }

함수를 만들려면 최소한 15 개를 매개 변수로 만들어야합니다. :)
Jordan

@Jordan : 코드를 작성하는 상황에 따라 다릅니다. :-)
내 겨드랑이 키스
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.