Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[js] 第155天 用js模拟实现微信抢红包的算法,并说明你的思路 #1219

Open
haizhilin2013 opened this issue Sep 17, 2019 · 6 comments
Labels
js JavaScript

Comments

@haizhilin2013
Copy link
Collaborator

第155天 用js模拟实现微信抢红包的算法,并说明你的思路

@haizhilin2013 haizhilin2013 added the js JavaScript label Sep 17, 2019
@Guanrui1
Copy link

开个监听器,找到红包消息对应的特征,进而可以监听红包消息,然后在这个回调函数里面写入打开红包的代码,当然,单纯的js肯定实现不了,需要调用别的语言和api接口

@forever-z-133
Copy link

普惠红包

除了最后一人,其他每个人随机范围为 (0, 20),也相当于每人平均 10 块吧。
可以再打乱一次顺序来避免最后一人问题。

function grabMoney(total, maxTimes) {
  //  结果数组   剩余次数           剩余金额
  var res = [], times = maxTimes, rest = total;
  while (--times > 1) {
    var r = random(0, rest / times * 2);
    var _r = r.toFixed(2).replace('.', ''); // 处理双精度运算问题
    var _rest = rest.toFixed(2).replace('.', '');
    rest = (_rest - _r) / 100;
    r = parseFloat(r.toFixed(2));
    res.push(r);
  }
  res.push(rest);
  return res;
}

耗时红包

每人随机范围为 (0, 25),超出总价就重新排,低于总价则平摊。
由于有除法,余数计算误差大,所以系统会贪掉一丢丢。

function grabMoney(total, maxTimes) {
  var res = new Array(maxTimes);
  var grabed = 0;
  for (var i=0; i<res.length; i++) {
    var r = random(0, total / 4);
    r = parseFloat(r.toFixed(2));
    grabed += r;
    if (grabed > total) return grabMoney(total, maxTimes);
    res[i] = r;
  }
  if (grabed < total) {
    var average = (total - grabed) / total;
    res = res.map(function(item) {
      return item + average;
    });
  }
  return res;
}

@xxf1996
Copy link

xxf1996 commented Sep 20, 2019

/**
 * 抢红包算法
 * @param {*} money 红包金额数
 * @param {*} people 红包人数
 */
function drawLucky (money, people) {
  let remainMoney = money
  let remainPeople = people

  return {
    // 每一次抢到的红包金额
    draw () {
      let per = remainMoney / remainPeople
      let curMoney = 0
      if (remainPeople === 1) {
        curMoney = Math.round(remainMoney * 100) / 100 // 使数字保留两位小数
        remainPeople--
      } else if (remainPeople > 1) {
        curMoney = Math.round(per * (Math.random() * 1.6 + 0.2) * 100) / 100 // 使数字保留两位小数【随机分配剩余金额,份数为(0.2, 1.8)之间】
        remainPeople--
      }
      remainMoney -= curMoney
      return curMoney
    }
  }
}

let test = drawLucky(100, 20)
let amount = 0
for (let i = 0; i < 20; i++) {
  let cur = test.draw()
  amount += cur
  console.log(cur)
}
console.log(amount)

感觉真实情况下还要知道实时剩余人数和金额,考虑到网络情况,有点难;

@xiaotianxia
Copy link

@Ziyu-Chen
Copy link

I decided to use closure to solve this problem.
When creating red pockets, users will be asked to provide three arguments.
The first argument is the total amount of money they want to put into the red pockets.
The second argument is the number of red pockets.
The third argument indicates whether the amount of money in each red pocket is determined randomly.
When createRedPockets is called, an array of red pockets (positive numbers) will be created and a function is returned.
The function returns a red pocket when there are still red pockets (positive numbers) left in the array. Otherwise, it returns 0.

const createRedPockets = (total, num = 1, random = false) => { let redPockets; if (random) { let weights = []; for (let i = 0; i < num; i++) { weights.push(Math.random() + 1); } const sum = weights.reduce((a, b) => a + b); weights = weights.map(weight => weight / sum); redPockets = weights.map(weight => weight * total); } else { redPockets = Array(num).fill(total / num); } return () => { if (!redPockets.length) return 0; return redPockets.pop(); }; };

@xiaoqiangz
Copy link

function getRandomMoney(remainMoney,remainSize){
let moneyList=[];
const min=0.01;
let max,money;
while (remainSize>1){
max=remainMoney/remainSize*2;
money=Math.random()max;
money=money<0.01 ? 0.01 : money;
money=Math.round(money
100)/100;
moneyList.push(money);
remainSize--;
remainMoney-=money;
}

moneyList.push(Math.round(remainMoney*100)/100);
return moneyList;
}
const maxMoney=100; //红包总金额
const maxSize=20; //红包个数
console.log(getRandomMoney(maxMoney,maxSize))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
js JavaScript
Projects
None yet
Development

No branches or pull requests

7 participants