简体   繁体   中英

How can I guarantee pick a weighted element?

can somebody help me, I am trying to make a simple javascript game that let's the user pick a random element according to it's weight. The problem is, it's hard for me to get the lowest weighted element in the array so, I realize that why not do a max number of pick and after that reaching the max number you'll be guaranteed to get the lowest weighted element. (I' so sorry for my english, as it's not my first language). Also I'm a beginner in javascript. >///<

Here's the code:

var firstPrize = 
[
        "200k Yen Cash",
        "High End Computer Set"
]; //first prize with 0.5% chance of getting picked

var secondPrize = 
[
        "Xbox",
        "PS5",
        "Nintendo Switch"
]; //second prize with 25.3% chance of getting picked

var thirdPrize = 
[
        "10k Yen Cash",
        "10k Yen Amazon Voucher",
        "Airpods",
        "Customized Keyboard",
        "1-Yr Nitro Boost",
        "Shoes"
]; //third prize with 74.2% chance of getting picked

var randFirstPrize = firstPrize[Math.floor(Math.random() * firstPrize.length)]; // random pick

var randSecondPrize = secondPrize[Math.floor(Math.random() * secondPrize.length)]; // random pick

var randThirdPrize = thirdPrize[Math.floor(Math.random() * thirdPrize.length)]; // random pick

const prizes = 
[
        randFirstPrize,
        randSecondPrize,
        randThirdPrize
]; // prizes as variables

const weights =
[
        0.5,
        25.3,
        74.2
]; //prize percent chance

function userPrize(prizes, weights) {
    var i;
  
    for (i = 0; i < weights.length; i++)
    weights[i] += weights[i - 1] || 0;
    
    var random = Math.random() * weights[weights.length - 1];
    
    for (i = 0; i < weights.length; i++)
        if (weights[i] > random)
            break;
    
    return prizes[i];
}; //pick random weighted elements

console.log(userPrize(prizes, weights));

Expected Output will mostly be thirdPrize as the weight is higher than the other prizes. So my goal is, when a player reaches 150 pick/accumulation then he will be guaranteed to pick firstPrize . Hope I explained my question well.

I assume the code you posted currently work as intended and you want to add the function that "when a player reaches 150 pick/accumulation then he will be guaranteed to pick randFirstPrize".

To do that, you will need a variable to keep track of how many times they picked:

let pickTimes = 0;

And you need to add it every time a user pick:

    // ...
    pickTimes++;
    return prizes[i];

Now, obviously you can check the pickTimes variable every time you choose a random prize. It's up to you how you process it but this is one suggestion:

    var random = Math.random() * weights[weights.length - 1];
    
    if (pickTimes == 150) {
        random = 100; // So your weight for first prize always meets the first prize condition
        pickTimes = 0; // You may want to reset the pick times so 150 times later users can still get guaranteed first prize.
    }

Ps after a more thorough reading, I do not understand your code of picking weight. I may be wrong but you should understand the principle of how to apply it from the logic I explained above after fixing your code if there is a problem.

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