[Java] Utilisation de "var | var"

a marqué ce sujet comme résolu.

Bonjour !

Je suis en train de lire un livre sur la programmation d’un jeu en Java, et il y à le code suivant :

InventorySlot.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class InventorySlot extends Stack {

    [...]

    private int _filterItemType;

    public InventorySlot(){
        _filterItemType = 0;

        [...]
    }

    public InventorySlot(int filterItemType){
        this();
        _filterItemType = filterItemType;
    }
}

InventoryItem.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class InventoryItem extends Image {

    [...]

    public enum ItemUseType{
        ITEM_RESTORE_HEALTH(1),
        ITEM_RESTORE_MP(2),
        ITEM_DAMAGE(4),
        WEAPON_ONEHAND(8),
        WEAPON_TWOHAND(16),
        WAND_ONEHAND(32),
        WAND_TWOHAND(64),
        ARMOR_SHIELD(128),
        ARMOR_HELMET(256),
        ARMOR_CHEST(512),
        ARMOR_FEET(1024);

        private int _itemUseType;

        ItemUseType(int itemUseType){
            this._itemUseType = itemUseType;
        }

        public int getValue(){
            return _itemUseType;
        }
    }
}

InventoryUI.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public class InventoryUI extends Window {

    public InventoryUI(){

        [...]

        InventorySlot headSlot = new InventorySlot(
                ItemUseType.ARMOR_HELMET.getValue()
        );

        InventorySlot leftArmSlot = new InventorySlot(
                ItemUseType.WEAPON_ONEHAND.getValue() |
                ItemUseType.WEAPON_TWOHAND.getValue() |
                ItemUseType.ARMOR_SHIELD.getValue() |
                ItemUseType.WAND_ONEHAND.getValue() |
                ItemUseType.WAND_TWOHAND.getValue())
        );

        [...]
    }
}

Et je me demandais à quoi sert le | lors de la création d’un nouveau InventorySlot (ligne 12, 13, 14 et 15 du fichier InventoryUI.java).

Qu’est ce que cela fait ?

Du coup, quelle valeur aura la variable filterItemType dans le fichier InventorySlot.java ?

Merci !

+0 -0

Je pense que c’est le ou logique, je me rappelle plus du nom de ce type de variable mais en fait tu peux savoir grâce à une seule variable qu’est ce que le personnage a en main, et si je ne me trompe pas chaque type d’arme met un bit à 1 du coup tu peux les differentier.

+0 -0

Je ne comprends pas trop…

Ca veut dire que la variable filterItemType aura plusieurs valeurs ?

Du coup, si je met ce code :

1
2
3
4
5
6
7
if (filterItemType == ItemUseType.WEAPON_ONEHAND.getValue()) {
    System.out.println("1) Vrai");
}

if (filterItemType == ItemUseType.WEAPON_TWOHAND.getValue()) {
    System.out.println("2) Vrai");
}

Cela m’affichera ceci dans la console ?

1
2
1) Vrai
2) Vrai
+0 -0

Pas plutôt un ou bit-à-bit pour créer un masque ? Comme dans la grosse majorité des langages.

ItemUseType.WEAPON_ONEHAND.getValue() | ItemUseType.WEAPON_TWOHAND.getValue() | ItemUseType.ARMOR_SHIELD.getValue() | ItemUseType.WAND_ONEHAND.getValue() | ItemUseType.WAND_TWOHAND.getValue() = 8 | 16 | 32 | 64 | 128 = 248

Cette valeur n’apporte rien. Ca permet surtout ensuite de savoir si l’objet a telle "option". Type :

1
2
3
if (0 != (filterItemType & ItemUseType.WEAPON_TWOHAND.getValue())) {
    System.out.println("Dispose de WEAPON_TWOHAND");
}
+2 -0

En complément, je mets tout de même la réponse que j’avais commencé à écrire avant que vibrice


Est-ce que tu es familier avec le codage binaire (numérotation en base 2, etc). Le ou binaire est un opérateur dit bit à bit, c’est à dire qu’il va travailler au niveau des bits de ta variable et pas sa valeur global.

Un ou unaire va, pour chaques bits de tes opérandes, faire un ou logique. Un ou logique, c’est le fait que si l’un des deux bits est à 1, alors le bit résultat est à 1.

Donc, $100 | 101 = 101$, car $1|1 = 1$, $0|0 = 0$ et $0|1 = 1$.

Tu remarqueras que dans ton enum, toutes les valeurs sont des puissances de deux ; ce n’est pas un hasard : une puissance de 2, c’est un entier codé avec un seul bit à 1. Donc toutes tes valeurs d’énums sont de la forme $0..010..0$

En faisant un ou binaire d’une valeur avec un membre de ton enum, tu sais que tu vas mettre à 1 le bit de ta valeur. En faisant plus tard un et binaire, tu pourras vérifier si oui ou non il est activé.

+0 -0

Edit: grillé.

Le | est l’opérateur OR binaire. Pour reprendre ton exemple avec ta variable leftArmSlot :

1
2
3
4
5
6
7
ItemUseType.WEAPON_ONEHAND.getValue() = 00001000
ItemUseType.WEAPON_TWOHAND.getValue() = 00010000
ItemUseType.ARMOR_SHIELD.getValue()   = 10000000
ItemUseType.WAND_ONEHAND.getValue()   = 00100000
ItemUseType.WAND_TWOHAND.getValue()   = 01000000
__________________________________________________
filterItemType                        = 11111000

Maintenant, pour tester quels flags tu as utilisé, on utilise l’opérateur AND:

1
2
3
if ((filterItemType & ItemUserType.WEAPON_ONEHAND.getValue()) == ItemUserType.WEAPON_ONEHAND.getValue()) {
    // do something
}

Une autre manière de faire (peut être plus claire) serait d’utiliser un EnumSet.

+5 -0

if ((filterItemType & ItemUserType.WEAPON_ONEHAND.getValue()) == ItemUserType.WEAPON_ONEHAND.getValue())

Pas besoin de tester explicitement l’égalité, il suffit de vérifier que le résultat est != 0, donc True.

nohar

Nope, si tu fais ça en Java tu va te prendre un erreur de compilation « Incompatible types : required boolean, found int ».

PS : j’ai l’impression que le livre est un peu vieux, et/ou tente d’optimiser prématurément. Pour faire ce genre de chose, un EnumSet me semble probablement plus clair, comme ça a déjà été dit.

Merci pour les explications, c’est très clair ! :)

Donc avec un "EnumSet", le code serais le suivant :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class InventorySlot extends Stack {

    [...]

    private EnumSet<ItemUseType> _filterItemType;

    public InventorySlot(){
        _filterItemType = null;

        [...]
    }

    public InventorySlot(EnumSet<ItemUseType> filterItemType){
        this();
        _filterItemType = filterItemType;
    }
}

// ########################################

public class InventoryItem extends Image {

    [...]

    public enum ItemUseType{
        ITEM_RESTORE_HEALTH,
        ITEM_RESTORE_MP,
        ITEM_DAMAGE,

        [...]
    }
}

// #########################################

public class InventoryUI extends Window {

    public InventoryUI(){

        [...]

        InventorySlot leftArmSlot = new InventorySlot(
               EnumSet.of(ItemUseType.WEAPON_ONEHAND.getValue(),
                ItemUseType.WEAPON_TWOHAND.getValue(),
                ItemUseType.ARMOR_SHIELD.getValue(),
                ItemUseType.WAND_ONEHAND.getValue(),
                ItemUseType.WAND_TWOHAND.getValue()
        ));

        [...]
    }
}

C’est bien ça ?

En tout cas, merci à tous pour vos réponses ! :)

Edit : Ou sinon, j’utilise un ArrayList, et je vérifie que la case dans lequel je dépose l’item possède, dans son ArrayList, une des valeurs de l’enum "ItemUseType".

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte