Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (491)
Games in Android Showcase (112)
games submitted by our members
Games in WIP (556)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Best Way to Code Random Percentage of Something  (Read 810 times)
0 Members and 1 Guest are viewing this topic.
Offline xslaught

Junior Newbie





« Posted 2013-04-09 09:01:01 »

I'm trying to figure out the best way to code the random occurance of something based on percent without hard coding if-else for each percentage since it will be dynamic.
Ex:

Item 1 drops 20% of the time
Item 2 drops 60% of the time
Item 3 drops 20% of the time

I'm storing the itemID and percentage as HashMaps
// itemID, percentage
HashMap<Integer, Integer>

But is there a better way to store these pairs? I could create a new class with only 2 variables called Pair. Would a Pair class be more efficient than a HashMap for storing multiple itemID and percentage?

I somehow have to go through each item in the HashMap and get the percentages, then add all them up (20 + 60 + 20) to get 100.
I then have to do some random number generation to get a number then check which item will drop. To do this I may have to order check from lowest percentage to highest, but if 2 percentages are the same (20 + 20), then I'm not sure how to pick which one should be dropped.
Offline DziNeIT

Senior Newbie


Exp: 3 years



« Reply #1 - Posted 2013-04-09 09:30:05 »

You would use a java.util.Random object. Define one somewhere, and use it like this (assuming your HashMap is of item IDs to percentages, if not you might need to change it a bit):

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
boolean dropped = false;
int highest = -1;
int highAmt = -1;
// Lets loop through all the items, because you said you didn't want it hardcoded
for (Entry<Integer, Integer> entry : drops.entrySet()) { // Where drops is the HashMap you spoke of. HashMaps are extremely fast, don't worry about that
   if (entry.getValue() > highAmt) {
        highest = entry.getKey();
    }
    // Note <, not <=, because nextInt(100) will generate a number from 0-99, not 1-100.
   if (random.nextInt(100) < entry.getValue()) { // Will happen every (entry.getValue() / 100) times
       world.dropItemById(x, y, z, entry.getKey()); // Or however you do this
       dropped = true; // Set this to true for usage a bit later
       break; // Remove this if you want the chance of multiple drops
   }
}
if (!dropped) {
    world.dropItemById(x, y, z, highest); // Slightly crude way of ensuring something is dropped. If we don't drop something, drop whatever has the highest percentage. If you want the possibility of no drop remove this
}
Online StrideColossus
« Reply #2 - Posted 2013-04-09 09:46:24 »

I'm trying to figure out the best way to code the random occurance of something based on percent without hard coding if-else for each percentage since it will be dynamic.
Ex:

Item 1 drops 20% of the time
Item 2 drops 60% of the time
Item 3 drops 20% of the time

I'm storing the itemID and percentage as HashMaps
// itemID, percentage
HashMap<Integer, Integer>

But is there a better way to store these pairs? I could create a new class with only 2 variables called Pair. Would a Pair class be more efficient than a HashMap for storing multiple itemID and percentage?

I assume you're implementing some sort of loot table.  I've previously used something along the lines of the following:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
public class LootTable {
   private final Map<Integer, Object> table = new LinkedHashMap<Integer, Object>();
   
   public void add( int range, Object item ) {
      table.put( range, item );
   }
   
   public Object get( int value ) {
      int range = 0;
      for( Entry<Integer, String> entry : table.entrySet() ) {
         range += entry.getKey();
         if( value < range ) return entry.getValue();
      }
      return null;
   }
}


The LinkedHashMap orders the entries by insertion order.  The code is pretty crude (just boshed it out from memory), you'd probably want to add some checks to ensure that the percentiles total 100.

You mention efficiency - did you mean speed or storage space or both?  Personally I wouldn't worry in either case, I assume this would not be a performance-critical part of your code (correct me if I make the wrong assumption) so just design whatever is the easiest to maintain.

Also is there any reason why you were using item IDs instead of the items themselves (I used Object in the above)?

Quote
I somehow have to go through each item in the HashMap and get the percentages, then add all them up (20 + 60 + 20) to get 100.
I then have to do some random number generation to get a number then check which item will drop. To do this I may have to order check from lowest percentage to highest, but if 2 percentages are the same (20 + 20), then I'm not sure how to pick which one should be dropped.

The insertion order technique means you don't need to worry about ranges of the same value.

An alternative is to just use a simple Map and insert multiple entries to emulate percentile ranges.
e.g. in your example you would add items 1 and 3 once, but item 2 three times, and just used a random value in the range 0 to size-of-table (5) to select one out.

Hope this helps.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Online Roquen
« Reply #3 - Posted 2013-04-09 10:53:40 »

Think weights (not percentages) and cumulative.  Builder sorts, sums the weights, divides each by the sum, then each item is the total of this value.  One float and binary search.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Nickropheliac (15 views)
2014-08-31 22:59:12

TehJavaDev (23 views)
2014-08-28 18:26:30

CopyableCougar4 (32 views)
2014-08-22 19:31:30

atombrot (41 views)
2014-08-19 09:29:53

Tekkerue (40 views)
2014-08-16 06:45:27

Tekkerue (35 views)
2014-08-16 06:22:17

Tekkerue (25 views)
2014-08-16 06:20:21

Tekkerue (37 views)
2014-08-16 06:12:11

Rayexar (72 views)
2014-08-11 02:49:23

BurntPizza (49 views)
2014-08-09 21:09:32
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!