How do I get random item based on percentage?

Nick R 66 Reputation points


I'm working on a card pack project, where I have 3 packs, Bronze, Silver and Gold.

User buys bronze pack, will only get bronze cards.
User buys silver pack, most of the time it'll be bronze cards, with silver cards popping up 1 out of 50 times, give or take and maybe a gold card 1 out of 1000.
User buys gold pack, mostly bronze cards, a little more silver cards with the possibility of getting a gold card is higher.

Any info on how I would code this would be greatly appreciated.

Thank you!

A set of technologies in the .NET Framework for building web applications and XML web services.
4,244 questions
0 comments No comments
{count} votes

3 answers

Sort by: Most helpful
  1. Michael Taylor 49,251 Reputation points

    Here's the start of an algorithm but you'll have to test it and make adjustments. We'll assume that you're using a good random # generator that truly generates arbitrary values.

    Let's assume that we're building for the silver pack and that you said 1 in 50 are silver and 1 in 1000 are gold. Normalize to 1000 so 20 in 1000 are silver, 1 in 1000 are gold and the remaining are bronze. Generate a random number between 1 and 1000. You can partition your cards up as much as you want but somehow you'll need to decide where the 20 silver and 1 gold card sit in the 1-1000 range. Suppose, for example, that you specify that the gold card is at 1000 and the silver are 1-20. If the random # is in either range then you use that value. However I think you'll find that 1 in 1000 is extremely rare even on the best days.

    There are quite a few variants you can use to adjust the behavior to your liking such as pre-selecting the cards and randomizing from there or using some custom rules such as a gold pack always having at least 1 gold card.

    1 person found this answer helpful.
    0 comments No comments

  2. Bruce ( 58,041 Reputation points

    simple brand picker:

        static Random brandRand = new Random();  
    	public static string GetBrand()  
    		var value = brandRand.NextDouble();  
    		if (value <= 1.0/1000.0)  
    			return "Gold";  
    		else if (value <= 1.0/50.0)  
    			return "Silver";  
    		return "Bronze";  
    1 person found this answer helpful.
    0 comments No comments

  3. Nick R 66 Reputation points

    So let's say I want to grab 4 cards at random from bronze, all cards will of course be bronze when I buy the bronze pack. If I buy a silver pack, any or all 4 can be silver, but still have bronze cards, based on percentage. If I buy a gold pack, any of the 4 will be gold, some silver and mostly bronze.

    My code as I have as follows. It will need some modification, for sure.

    var random = new Random();  
    var items = (await _cardService.GetAllItemsAsync()).Where(c => c.Level == pack.Level);  
    var userPack = new UserPack  
       Item1Id = items.OrderBy(c => random.Next()).FirstOrDefault().Id,  
       Item2Id = items.OrderBy(c => random.Next()).FirstOrDefault().Id,  
       Item3Id = items.OrderBy(c => random.Next()).FirstOrDefault().Id,  
       Item4Id = items.OrderBy(c => random.Next()).FirstOrDefault().Id  

    pack.Level would be equal to Bronze, Silver or Gold.

    I hope this clears up some of what I'm trying to accomplish.