web-dev-qa-db-fra.com

Comment puis-je incrémenter une variable sans dépasser une valeur maximale?

Je travaille sur un programme de jeu vidéo simple pour l'école et j'ai créé une méthode où le joueur obtient 15 points de vie si cette méthode est appelée. Je dois maintenir la santé à un maximum de 100 et avec ma capacité de programmation limitée à ce stade, je fais quelque chose comme ça.

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

Je comprends que ma syntaxe n'est pas parfaite mais ma question est, quelle peut être une meilleure façon de le faire, car je dois aussi faire une chose similaire avec les points de dégâts et ne pas descendre en dessous de 0.

Cela s'appelle arithmétique de saturation .

89
Steven Eck

Je ferais juste ça. Cela prend fondamentalement le minimum entre 100 (la santé max) et ce que la santé serait avec 15 points supplémentaires. Il garantit que la santé de l'utilisateur ne dépasse pas 100.

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

Pour vous assurer que les repères ne tombent pas en dessous de zéro, vous pouvez utiliser une fonction similaire: Math.max.

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

il suffit d'ajouter 15 à la santé, donc:

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

Cependant, comme l'a noté fade, parfois avec plusieurs threads (plusieurs blocs de code s'exécutant à la fois) ayant la santé dépasser 100 à n'importe quel point peut causer des problèmes, et changer la propriété de santé plusieurs fois peut également sois méchant. Dans ce cas, vous pouvez le faire, comme mentionné dans d'autres réponses.

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

Vous n'avez pas besoin d'un cas distinct pour chaque int au-dessus de 85. Il suffit d'en avoir un else, de sorte que si la santé est déjà 86 ou supérieur, puis définissez-le directement sur 100.

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

Je pense qu'une façon idiomatique et orientée objet de faire cela est d'avoir un setHealth sur la classe Character. L'implémentation de cette méthode ressemblera à ceci:

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

Cela empêche la santé de descendre en dessous de 0 ou supérieure à 100, quel que soit le paramètre que vous définissez.


Votre implémentation de getHealed() peut simplement être la suivante:

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

Qu'il soit logique que la méthode Character ait une méthode getHealed() est un exercice laissé au lecteur :)

37
Daniel Kaplan

Je vais juste offrir une tranche de code plus réutilisable, ce n'est pas la plus petite mais vous pouvez l'utiliser avec n'importe quelle quantité, donc ça vaut la peine d'être dit

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

Vous pouvez également changer le 100 en variable maxHealth si vous souhaitez ajouter des statistiques au jeu que vous créez, de sorte que la méthode entière pourrait ressembler à ceci

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

MODIFIER

Pour plus d'informations

Vous pouvez faire de même lorsque le joueur est endommagé, mais vous n'aurez pas besoin d'un minHealth car ce serait de toute façon 0. En procédant de cette façon, vous seriez en mesure d'endommager et de guérir n'importe quel montant avec le même code.

14
5tar-Kaster
health = health < 85 ? health + 15 : 100;
10
Aroo

Je ferais une méthode statique dans une classe d'assistance. De cette façon, plutôt que de répéter du code pour chaque valeur qui doit tenir dans certaines limites, vous pouvez avoir une méthode polyvalente. Il accepterait deux valeurs définissant le min et le max, et une troisième valeur à maintenir dans cette plage.

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;
    }
}

Pour votre cas, vous déclareriez votre santé minimale et maximale quelque part.

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

Appelez ensuite la fonction en transmettant votre santé minimale, maximale et ajustée.

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

Je sais que c'est un projet d'école, mais si vous souhaitez étendre votre jeu plus tard et pouvoir améliorer votre pouvoir de guérison, écrivez la fonction comme suit:

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

et appelez la fonction:

getHealed(15);
getHealed(25);

...etc...

De plus, vous pouvez créer votre HP max en créant une variable qui n'est pas locale à la fonction. Étant donné que je ne sais pas quelle langue vous utilisez, je ne montrerai pas d'exemple car il pourrait avoir la mauvaise syntaxe.

3
BlackBeltScripting

Peut être ça?

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

Si vous voulez être effronté et adapter votre code sur une seule ligne, vous pouvez utiliser un opérateur ternaire :

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

Notez que certaines personnes vont désapprouver cette syntaxe en raison (sans doute) d'une mauvaise lisibilité!

2
Oleksiy

La manière la plus simple d'utiliser l'opérateur module.

santé = (santé + 50)% 100;

la santé ne sera jamais égale ou supérieure à 100.

1
bond

Je crois que cela fera l'affaire

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

Explication:

  • Si l'écart pour la guérison est de 15 ou moins, la santé deviendra 100.

  • Sinon, si l'écart est supérieur à 15, cela ajoutera 15 à la santé.

Ainsi par exemple: si la santé est de 83, elle deviendra 98 mais pas 100.

1
MarmiK

Si je voulais être thread-safe, je le ferais de cette façon plutôt que d'utiliser un bloc synchronisé.

L'atomic compareAndSet atteint le même résultat que synchronisé sans la surcharge.

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
Robert Sutton
   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;
    }
0
kiss my armpit