Or en Java - Évitez les bugs et l'overflow en modélisant bien

Denis Ribeiro .

12 avril 2026

Erreur Address Sanitizer : dépassement de tampon sur le tas. Le code C++ tente d'écrire au-delà des limites allouées.

Gérer l’or en Java paraît simple tant qu’il ne s’agit que d’afficher un compteur. Dès qu’on ajoute des récompenses, des achats, des coffres ou une économie qui doit tenir dans la durée, le modèle de données devient décisif. Ici, je parle de l’or comme ressource, monnaie ou récompense dans un jeu ou une simulation, pas de l’opérateur logique. Je vais montrer comment représenter cette ressource proprement, quand utiliser un `enum`, quand préférer une classe, et comment éviter les bugs de solde négatif ou d’overflow.

Les choix qui évitent les bugs dans une économie d’or en Java

  • Un enum sert à nommer un type d’or ou de ressource, pas à compter un solde.
  • Pour un montant qui évolue, je privilégie une classe dédiée ou au minimum un `long`.
  • Le seuil de sécurité passe vite à 2 147 483 647 avec `int`; au-delà, l’overflow devient réel.
  • Si le jeu gère plusieurs ressources, `EnumMap` est souvent plus propre qu’une carte à clés texte.
  • Les règles métier doivent vivre dans le modèle, pas dans l’interface.

Comprendre ce que représente vraiment cette ressource

Dans un jeu, l’or peut jouer plusieurs rôles : monnaie d’achat, score, récompense de combat, matériau d’amélioration ou simple variable de progression. Je commence toujours par séparer deux questions : est-ce un type ou une quantité ? Si la réponse change selon le moment du jeu, ce n’est pas le même objet métier. Un type se modélise comme une catégorie stable ; un solde évolue, se cumule, se dépense et doit être protégé contre les valeurs incohérentes.

Autrement dit, je ne traite pas de la même façon un coffre qui contient de l’or, une boutique qui en consomme et une interface qui affiche le total. C’est cette séparation qui évite ensuite les classes fourre-tout et les chaînes de caractères magiques. La décision de modélisation ouvre directement la question du bon outil Java, ce qui mène au choix entre `enum`, classe et simple compteur.

Choisir entre `enum`, classe et compteur numérique

Je vois souvent trois approches, et elles ne répondent pas au même besoin. La bonne solution dépend surtout du fait que l’or soit une catégorie fixe ou une valeur mutable.

Approche Quand l’utiliser Avantages Limites
Compteur simple `int` ou `long` Solde unique, logique très simple, prototype rapide Très lisible, peu de code, facile à afficher Aucune validation métier, `int` sature vite
`enum` Type de ressource, catégorie, rareté, tier fermé Typage fort, évite les fautes de frappe, très clair Ne gère pas les quantités qui bougent
Classe métier Solde avec règles, achats, gains, plafonds, historique Encapsulation, validation, extensible Un peu plus de code, donc plus de structure

Si vous gérez plusieurs ressources, `EnumMap` est souvent plus propre qu’une `Map`. On évite les fautes de frappe, on gagne en lisibilité et on garde des clés vraiment typées. Une fois ce tri fait, on peut écrire la partie qui compte vraiment : le solde et ses règles.

Construire un solde d’or robuste

Quand l’or circule, je préfère encapsuler le total dans une classe dédiée. L’idée est simple : la classe protège l’état, valide les entrées et centralise les règles de dépense.

public final class GoldWallet {
    private long balance;

    public GoldWallet(long initialBalance) {
        if (initialBalance < 0) {
            throw new IllegalArgumentException("Le solde initial ne peut pas être négatif.");
        }
        this.balance = initialBalance;
    }

    public long getBalance() {
        return balance;
    }

    public void earn(long amount) {
        if (amount < 0) {
            throw new IllegalArgumentException("Le gain doit être positif.");
        }
        balance = Math.addExact(balance, amount);
    }

    public boolean spend(long amount) {
        if (amount < 0) {
            throw new IllegalArgumentException("La dépense doit être positive.");
        }
        if (amount > balance) {
            return false;
        }
        balance -= amount;
        return true;
    }
}

Je choisis `long` plutôt que `int` dès que l’économie peut grossir, parce que la limite de `int` est vite atteinte dans un jeu idle, une boucle de récompenses ou un simulateur économique. `Math.addExact` est utile ici : il fait échouer le calcul au lieu de laisser un débordement silencieux. Si votre jeu est multijoueur ou synchronisé réseau, cette logique doit idéalement vivre côté serveur, pas dans le client.

Avec cette base, les achats et les récompenses deviennent prévisibles. La question suivante est alors plus ciblée : quand un `enum` reste-t-il pertinent sans surcharger le design ?

Utiliser un `enum` quand l’or n’est qu’un type parmi d’autres

Un `enum` est utile si vous ne comptez pas des pièces, mais des types de ressources ou des tiers. En Java, c’est une très bonne réponse quand l’ensemble des valeurs est connu à la compilation et ne doit pas être étendu à la volée.

public enum ResourceType {
    GOLD("Or", 1),
    WOOD("Bois", 1),
    IRON("Fer", 3);

    private final String label;
    private final int baseValue;

    ResourceType(String label, int baseValue) {
        this.label = label;
        this.baseValue = baseValue;
    }

    public String getLabel() {
        return label;
    }

    public int getBaseValue() {
        return baseValue;
    }
}

Dans ce cas, un `EnumMap` est souvent plus propre qu’une `Map` : on évite les fautes de frappe, on gagne en lisibilité et on garde des clés vraiment typées. Mais il ne faut pas se tromper de combat : un `enum` décrit la nature de la ressource, pas son stock. Si l’or peut passer de 0 à 10 000 puis redescendre après un achat, la quantité doit rester ailleurs.

C’est exactement ce mauvais mélange qui crée les systèmes fragiles, ce qui nous amène aux erreurs les plus fréquentes.

Éviter les erreurs qui cassent l’économie du jeu

  • Confondre type et quantité : un `enum` pour dire “or” oui, un `enum` pour stocker 347 pièces non.
  • Utiliser `int` par réflexe : au-delà de 2 147 483 647, vous exposez le jeu à un overflow discret.
  • Autoriser les valeurs négatives : un solde ne devrait jamais devenir négatif par accident ; si une dette existe, elle mérite un modèle explicite.
  • Dupliquer la logique dans l’interface : le bouton “Acheter” ne doit pas décider seul si l’opération est valide.
  • Stocker des montants sous forme de texte : cela complique les calculs, la persistance et les tests.

Je teste toujours au moins trois cas : gain normal, dépense refusée faute de solde, et valeur extrême qui vérifie l’absence de débordement. Ce trio révèle vite les failles qui ne se voient pas dans une démo courte. Une fois ces garde-fous posés, on peut assembler un exemple complet sans alourdir la structure.

Assembler un exemple complet de récompense et d’achat

Pour un jeu simple, je sépare souvent trois responsabilités : la classe qui porte le solde, le service qui distribue les gains et l’écran qui affiche le résultat. Cette organisation reste légère, mais elle évite de mélanger aléatoire, règles métier et rendu.

import java.util.concurrent.ThreadLocalRandom;

public final class RewardService {

    public long chestReward() {
        return ThreadLocalRandom.current().nextLong(10, 31);
    }

    public void grantChestReward(GoldWallet wallet) {
        wallet.earn(chestReward());
    }

    public boolean buyItem(GoldWallet wallet, long cost) {
        return wallet.spend(cost);
    }
}

Utilisé ainsi, le flux est lisible :

GoldWallet wallet = new GoldWallet(100);
RewardService rewards = new RewardService();

rewards.grantChestReward(wallet);
boolean bought = rewards.buyItem(wallet, 75);

Ce schéma est simple, mais il couvre déjà beaucoup de cas réels : récompense aléatoire, dépense contrôlée et solde persistable en base avec un type numérique compatible `BIGINT`. Si le projet grandit, on peut ajouter des événements, des logs de transactions ou des plafonds sans casser le cœur du modèle. La vraie discipline consiste maintenant à choisir ce qui mérite d’être généralisé et ce qui doit rester volontairement simple.

Ce que je recommande pour garder un système lisible en 2026

Si je devais livrer une version propre sans sur-ingénierie, je ferais trois choix : `long` pour le solde, `enum` pour les catégories fermées, et une classe métier pour toutes les opérations qui modifient l’or. Ce trio couvre la majorité des jeux et des simulateurs sans complexifier inutilement le code.

  • Conservez la règle de solde dans la classe métier, pas dans le bouton ou l’écran.
  • Si plusieurs ressources existent, regroupez-les avec `EnumMap` plutôt qu’avec des clés texte.
  • Validez chaque entrée avant de modifier le solde, y compris les bonus et les remboursements.
  • Pensez à la persistance dès le départ : un `BIGINT` en base évite les mauvaises surprises.
  • Ajoutez des tests sur les frontières : 0, montant exact, montant trop élevé, valeur proche de la limite.

Au fond, la meilleure modélisation de l’or n’est pas la plus sophistiquée, c’est celle qui rend les règles du jeu évidentes à relire six mois plus tard. C’est ce qui permet d’ajouter des coffres, des boutiques ou une économie plus riche sans transformer le code en bricolage permanent.

Questions fréquentes

Un `int` atteint rapidement sa limite (2 147 483 647) dans une économie de jeu. Utiliser un `long` ou une classe dédiée prévient les overflows discrets et garantit une gestion robuste des montants élevés.
Un `enum` est idéal pour définir des types de ressources (ex: GOLD, WOOD, IRON) ou des catégories fixes. Il ne doit pas être utilisé pour stocker des quantités variables d'or, car il ne gère pas les soldes évolutifs.
Encapsulez la logique de dépense et de gain dans une classe métier (ex: `GoldWallet`). Cette classe peut valider les montants, empêcher les soldes négatifs et centraliser les règles d'affaires, rendant le système plus sûr.
Pour gérer plusieurs ressources, utilisez un `EnumMap`. Cela offre un typage fort, évite les erreurs de frappe courantes avec les `Map` et améliore la lisibilité du code.
Oui, testez toujours les cas limites : gain normal, dépense refusée (solde insuffisant), et valeurs extrêmes pour vérifier l'absence de débordement (`long` avec `Math.addExact`). Cela révèle les failles cachées.

Évaluer l'article

Moyenne: 0.0 / 5 · 0 évaluations

Tags

or en java gestion or java modélisation or jeu java
Autor Denis Ribeiro
Denis Ribeiro
Je m'appelle Denis Ribeiro et je suis passionné par les technologies, en particulier dans les domaines du web, de l'intelligence artificielle, des réseaux et de la sécurité. Fort de plusieurs années d'expérience en tant qu'analyste de l'industrie, j'ai eu l'occasion d'explorer en profondeur ces sujets, en me concentrant sur les évolutions et les tendances qui façonnent notre monde numérique. Mon expertise me permet d'analyser des données complexes et de les présenter de manière accessible, afin que chacun puisse comprendre les enjeux technologiques actuels. Je m'efforce d'apporter une perspective objective et factuelle à mes écrits, en vérifiant rigoureusement les informations pour garantir leur fiabilité. Je suis engagé à fournir à mes lecteurs des contenus précis, à jour et impartiaux, car je crois fermement que l'accès à une information de qualité est essentiel pour naviguer dans l'univers technologique en constante évolution. Mon objectif est de contribuer à une meilleure compréhension des défis et des opportunités que présente le monde numérique.

Commentaires (0)

Ajouter un commentaire