简体   繁体   中英

Java get a random value from 3 different enums

I am implementing a simple version of the Cluedo game. There are 3 types of cards in the game, Character, Weapon and Room. Since one card is nothing more than a String (ie no functionality or information other than the name is stored in a card), I chose not to have a Card interface and each type extends Card. Rather I had three enums in my game which are:

public enum Character {Scarlett, Mustard, White, Green, Peacock, Plum;}
public enum Weapon {Candlestick, Dagger, LeadPipe, Revolver, Rope, Spanner;}
public enum Room {Kitchen, Ballroom, Conservatory, BilliardRoom, Library, Study, Hall;}

However there is one case where three types of cards are put together and dealt evenly to each player of the game. For example, one player may have a hand of 2 Characters, 2 Weapons and 1 Room, another player may have 3 Rooms and 2 Characters, so long the total number of cards are even it doesn't matter what type that is.

And that's why I wonder if there is a way to randomly choose one single value from all three enums in Java?

Or I shouldn't do this three enums thing in the first place? (Badly designed)

A simple way is to collect all the enum members into a single Object[] , then take a random element from it.

Note that an enum can also implement an interface, so you can even have some shared API across all the enums. Typically you'll find yourself writing a lot of switch statements on the value of the enum; those can mostly be replaced by dynamic dispatch against such interface methods. Further note that each enum member can provide its own method implementation.

I think you should keep it like it is, but then put them all in the same list:

List<Enum> enums = new ArrayList<>();
enums.addAll(Arrays.asList(Character.values()));
enums.addAll(Arrays.asList(Weapon.values()));
enums.addAll(Arrays.asList(Room.values()));

And then you take random values of that list. More closely resembles what you do in real life.

You can write something like this:

public enum Character {Scarlett, Mustard, White, Green, Peacock, Plum;}
public enum Weapon {Candlestick, Dagger, LeadPipe, Revolver, Rope, Spanner;}
public enum Room {Kitchen, Ballroom, Conservatory, BilliardRoom, Library, Study, Hall;}

private static final Random RANDOM = new Random(); // random number generator - declared static, because we need only one for whole program
private static final int TOTAL_CARDS = Character.values().length + Weapon.values().length + Room.values().length; // sum up all enum lenghts - in this case, it will be 6 + 6 + 7 = 19

private Enum<?> getRandomCard() {
    int randomNumber = RANDOM.nextInt(TOTAL_CARDS); // we "roll a dice" to get some random number. Let's assume that we get "15"
    if (randomNumber < Character.values().length) { // is 15 less then 6? No, so we skip this part
        return Character.values()[randomNumber];
    }
    randomNumber -= Character.values().length; // randomNumber  = 15 - 6 = 9
    if (randomNumber < Weapon.values().length) { // is 9 < 6 ? No, so we skip this
        return Weapon.values()[randomNumber];
    }
    randomNumber -= Weapon.values().length; // randomNumber = 9 - 6 = 3
    if (randomNumber < Room.values().length) { // Is 3 < 7 ? Yes!
        // so it means that our "dice" has chosen a Room with array index 3
        // We call Room.values() to get all room types as an array and then we pick one with index 3
        return Room.values()[randomNumber];
    }
    return null; // should never happen
}

If you don't understand any part of this, please let me know - I'll add some comments.

However, I believe that solution proposed by Oskar Kjellin is far more elegant then this one :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM