bt365软件下载

切西瓜法实现微信抢红包功能

切西瓜法实现微信抢红包功能

✅前言

在现实生活中,非常常见的一个场景莫过于抢红包。节假日长辈发红包,生日时友人发祝福红包,结婚时亲朋好友发喜事红包……无一场景不贯穿着我们生活中的方方面面。

但是呢,很多时候有可能一个红包里面一两百块钱,而我们最后抢了几毛钱,还真是没有对比就没有伤害……(欲哭无泪)

那在下面的文章中呢,我们将来实现一个微信红包相关的分红包功能。一起来了解叭~

☑️一、需求分析 - 分红包问题

假设我们现在要进行发一个红包,这个红包的金额为 100 元,红包数量是 10 个。那么我们要怎么样分配,才能不失公平性呢?

那么接下来,我们由浅入深的来实现分红包功能。

🆙二、实现版本

1. 版本一:切西瓜法

先附上代码:

HTML 代码:

红包生成器

CSS 代码:

#setting button {

margin-top: 10px;

}

#result {

padding: 0;

}

#result li {

list-style: none;

}

JS 代码:

function generate(amount, count){

let ret = [amount];

while(count > 1){

//挑选出最大一块进行切分

let cake = Math.max(...ret),

idx = ret.indexOf(cake),

part = 1 + Math.floor((cake / 2) * Math.random()),

rest = cake - part;

ret.splice(idx, 1, part, rest);

count--;

}

return ret;

}

const amountEl = document.getElementById('amount');

const countEl = document.getElementById('count');

const generateBtn = document.getElementById('generateBtn');

const resultEl = document.getElementById('result');

generateBtn.onclick = function(){

let amount = Math.round(parseFloat(amountEl.value) * 100);

let count = parseInt(countEl.value);

let output = [];

if(isNaN(amount) || isNaN(count)

|| amount <= 0 || count <= 0){

output.push('输入格式不正确!');

}else if(amount < count){

output.push('钱不够分')

}else{

output.push(...generate(amount, count));

output = output.map(m => (m / 100).toFixed(2));

}

resultEl.innerHTML = '

  • ' +

    output.join('

  • ') +

    '

  • ';

    }

    一般来说,如果我们直接采取随机的方式来分红包,那边有很大的可能会造成第一个直接99块钱,而其他就有可能出现分不下去的问题。所以,我们应该来处理这个问题。

    那在上面的这个算法中呢,俗称切西瓜算法。

    我们每次都把这个金额分成两部分,那么它总是会有大的一部分和小的一部分,那么这时候呢,我们挑选大的那部分再进行切分,切分完,我们就有三部分了。

    继续,我们从这三部分中把最大的那部分再继续进行切分,以此类推。这样的话,我们就会一直有的分,而不会出现没得分的情况。

    2. 版本二:栅栏法

    先附上代码:

    HTML 代码:

    红包生成器

    CSS 代码:

    #setting button {

    margin-top: 10px;

    }

    #result {

    padding: 0;

    }

    #result li {

    list-style: none;

    }

    JS 代码:

    function * draw(cards){

    const c = [...cards];

    for(let i = c.length; i > 0; i--) {

    const pIdx = Math.floor(Math.random() * i);

    [c[pIdx], c[i - 1]] = [c[i - 1], c[pIdx]];

    yield c[i - 1];

    }

    }

    function generate(amount, count){

    if(count <= 1) return [amount];

    const cards = Array(amount - 1).fill(0).map((_, i) => i + 1);

    const pick = draw(cards);

    const result = [];

    for(let i = 0; i < count; i++) {

    result.push(pick.next().value);

    }

    result.sort((a, b) => a - b);

    for(let i = count - 1; i > 0; i--) {

    result[i] = result[i] - result[i - 1];

    }

    return result;

    }

    const amountEl = document.getElementById('amount');

    const countEl = document.getElementById('count');

    const generateBtn = document.getElementById('generateBtn');

    const resultEl = document.getElementById('result');

    generateBtn.onclick = function(){

    let amount = Math.round(parseFloat(amountEl.value) * 100);

    let count = parseInt(countEl.value);

    let output = [];

    if(isNaN(amount) || isNaN(count)

    || amount <= 0 || count <= 0){

    output.push('输入格式不正确!');

    }else if(amount < count){

    output.push('钱不够分')

    }else{

    output.push(...generate(amount, count));

    output = output.map(m => (m / 100).toFixed(2));

    }

    resultEl.innerHTML = '

  • ' +

    output.join('

  • ') +

    '

  • ';

    }

    另外一种算法呢,我们可以把它称为是栅栏算法。

    假设说现在有 100 块钱,那么我们可以把它看成是一个竹子。那如果你要把它分为 10 份的话,你要在中间的段里面去切 9 刀,那这9刀要切在什么位置呢,都是随机的。如果要在 100 块钱里面切 9 刀的话,那它是有 9999 种方案去切。也就是说,它有多少分钱,那么他就有 多少份钱 - 1 种的方式去切。

    最后,我们来看一下效果。如下图所示:

    ✳️三、在线Online

    以上两 个版本的在线地址:

    版本一:切西瓜法

    版本二:栅栏法

    🆗四、结束语

    在上面的文章中,我们首先谈论了分红包问题的随机性,同时,用了切西瓜法和栅栏法来实现了分红包功能。不知道大家对分红包问题是否有了进一步了解呢?

    如果您觉得这篇文章有帮助到您的的话不妨点赞支持一下哟~~😉

    🆚往期推荐

    👉紧跟月影大佬的步伐,一起来学习如何写好JS(上)

    👉紧跟月影大佬的步伐,一起来学习如何写好JS(下)

    👉每天都在红绿灯前面梭行,不如自己来实现个红绿灯?

    👉幂等问题 vs 如何判断是否是4的幂

    👉如何给扑克洗牌才能更公平?

    相关推荐