2

I have defined a Map in my class storing like position ---> rule, say:

1--->police
2--->teacher
3--->police
4--->student

What I hope is that every time a player join my game, I can randomly read a pair from that map and get his/her position-->rule, and then when another joins, get ANOTHER(unique) pair. Is there any good way to acheive that?

What I can figure out is that :

  1. Convert the map into a entities set
  2. Convert the set into a list
  3. Collections.shuffle(list);

But I don't think this is a good idea.

PS:

  1. The key is not integer in the future, but now, it is.
  2. Every player must own the unque pair.
  3. I don't want to change my map, which will be still used.
JaskeyLam
  • 15,405
  • 21
  • 114
  • 149

5 Answers5

3

In the case of consecutive integer keys as in your example, you can simply get a random key :

Random random = new Random();
map.get(random.nextInt(map.size()+1)); // this doesn't ensure uniqueness

If the key is not an integer, you can store the keys in a List :

Random random = new Random();
List<Key> keyList = new ArrayList<Key>();
keyList.addAll (map.keySet());
int index = random.nextInt(keyList.size());
key = keyList.get (index);
keyList.remove (index); // this ensures eniqueness by removing the used keys
value = map.get(key);
Eran
  • 387,369
  • 54
  • 702
  • 768
  • Now, it is integer key, but it probaply not in the future. And also, I don't want the modify my map since the status is needed. Do you have another good idea? – JaskeyLam Jul 19 '14 at 11:11
  • See my answer if you're looking for something which does not depend on the key implementation. – Eddie Curtis Jul 19 '14 at 11:11
  • Thank you! One problem is random.nextInt(map.size()), in my case map.size()=4. But why we continue use map.size() to be param of the nextInt? As I see, map.get(key) will not change the map.size()--, and also, I don't want to change my map. – JaskeyLam Jul 19 '14 at 11:21
  • @Jaskey I forgot to change it to keyList.size(), though it equals map.size() anyway. – Eran Jul 19 '14 at 11:25
  • Eran , I still not under stand, I want every player to have the a unique pair, why "map.get(random.nextInt(map.size()+1))" or "keyList.get (random.nextInt(keyList.size())); " can do so? For the second case, it can if I remove a key object from the keylist after that, but for the first case, I don't think I can do that. Again, I can't modify my Map since these status will be used. – JaskeyLam Jul 19 '14 at 11:32
  • @Jaskey I see, I missed that part of your question. Yes, you can achieve what you want by removing the used keys. I'll edit my answer. – Eran Jul 19 '14 at 11:34
2

Firstly, I would store the keys in a SortedMap. Then, use Random.nextInt(int) to pick a random key. Then do SortedMap.subMap(int, int) to get the entry in the position you need.

Eddie Curtis
  • 1,207
  • 8
  • 20
  • Thank you for your answer. This may be a good way. But how can I to generate a random int in a fast way. I mean, if the first player gets in and return the random value of 1, and the next one can never get the value of 1, and then if the second one gets value 2, third gets 3. When it goes to the 4, it will be much harder to get a random number of 4 without repeation in a while loop,and I have to store every number which have been picked. – JaskeyLam Jul 19 '14 at 11:17
  • So does each player need to have a unique type? If so just remove from the map and as long as you are doing Random.nextInt(map.size()) you will always get a unique value out of the map until it is empty. – Eddie Curtis Jul 19 '14 at 11:19
  • I can't modify the map until it destory. So ,do you think I have to copy that map into a new one and do so? – JaskeyLam Jul 19 '14 at 11:22
0

I think I would use a queue just as LinkedList. With this method you just create your random rule as you need for the maximum number of players allowed (or you can even monitor the count of the queue and add to it as needed) Once you have a nice random LinkedList<Roles> you can simply just assign any new incoming players the top of the queue newPlayer = queue.remove()

Robert Snyder
  • 2,399
  • 4
  • 33
  • 65
0

It seems to me that the easiest way to do this is to track available values in a List.

Map<Object,Rule> ruleMap=new HashMap<Object,Rule>();
//Add entries 
List<Object> availableRules=new ArrayList<Object>(ruleMap.keySet());

When a player joins, randomly select an entry from the List and then remove it.

int index=Random.nextInt(availableRules.size()-1);
//First get the key with availableRules.get(index), then get the value.
Rule r=ruleMap.get(availableRules.get(index));
//Remove the item so it can not be selected again.
availableRules.remove(index);

Note that this does not edit the Map, the List is separate from the map.

Also in List<Object> and Map<Object,Rule> Object should be replaced with whatever type you are using, currently int.

Zwander
  • 382
  • 2
  • 12
0

For each game:

  1. Generate an ordered array of keys.
  2. Random shuffle the array of keys as described in this question: Random shuffling of an array
  3. Index through the shuffled array of keys as needed.
  4. Hueristicly determine what to do if the shuffled array is exhausted.
Community
  • 1
  • 1
ben rudgers
  • 3,647
  • 2
  • 20
  • 32