【青训营】- 切西瓜法实现微信抢红包功能

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

1.png

✅前言


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

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

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


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


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

2.png

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


🆙二、实现版本


1. 版本一:切西瓜法


先附上代码:

HTML 代码:

<h2>红包生成器</h2>
<div id="setting">
  <div><label>红包金额:<input id="amount" value=100.00></input></label></div>
  <div><label>红包数量:<input id="count" value="10"></input></label></div>
  <div><button id="generateBtn">随机生成</button></div>
</div>
<ul id="result">
</ul>
复制代码

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 = '<li>' + 
                        output.join('</li><li>') +
                       '</li>';
}
复制代码

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

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

3.png

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

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


2. 版本二:栅栏法


先附上代码:

HTML 代码:

<h2>红包生成器</h2>
<div id="setting">
  <div><label>红包金额:<input id="amount" value=100.00></input></label></div>
  <div><label>红包数量:<input id="count" value="10"></input></label></div>
  <div><button id="generateBtn">随机生成</button></div>
</div>
<ul id="result">
</ul>
复制代码

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 = '<li>' + 
                        output.join('</li><li>') +
                       '</li>';
}
复制代码

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

4.png

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

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

1.png


✳️三、在线Online


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


🆗四、结束语


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

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


相关文章
|
3月前
|
小程序
微信小程序如何实现进入小程序自动连WiFi功能
微信小程序如何实现进入小程序自动连WiFi功能
131 0
|
3月前
|
小程序 JavaScript
微信小程序图片预览功能?
微信小程序图片预览功能?
|
1天前
|
小程序 前端开发 API
Ant Design Mini 问题之在微信小程序中,由于不支持slot特性,Ant Design Mini的什么组件功能受到了限制,如何解决
Ant Design Mini 问题之在微信小程序中,由于不支持slot特性,Ant Design Mini的什么组件功能受到了限制,如何解决
|
19天前
|
开发框架 移动开发 前端开发
在微信框架模块中,基于Vue&Element前端的后台管理功能介绍
在微信框架模块中,基于Vue&Element前端的后台管理功能介绍
|
1月前
|
缓存 容器
Flutter实现仿微信群头像功能
Flutter实现仿微信群头像功能
29 0
|
3月前
|
PHP
PHP公众号开发给用户发微信消息提醒功能
该内容是一个关于如何在时间紧迫的情况下,通过微信客服消息接口实现用户资金到账或成员变动时发送微信通知的项目总结。
41 2
|
2月前
|
小程序
微信小程序实现上传视频 / 上传图片功能以及整合上传视频 / 上传图片功能(超详细)
微信小程序实现上传视频 / 上传图片功能以及整合上传视频 / 上传图片功能(超详细)
|
2月前
|
小程序
微信小程序实现上传视频 / 上传图片功能以及整合上传视频 / 上传图片功能(超详细)
微信小程序实现上传视频 / 上传图片功能以及整合上传视频 / 上传图片功能(超详细)
|
3月前
|
小程序
微信小程序用户登陆和获取用户信息功能实现
微信小程序用户登陆和获取用户信息功能实现
61 0
|
3月前
|
小程序
uniapp 实现当前页面分享至微信好友或朋友圈功能(带参数和无参数)
uniapp 实现当前页面分享至微信好友或朋友圈功能(带参数和无参数)
241 0

热门文章

最新文章