
運用切西瓜法和柵欄法實作微信搶紅包功能
- ?前言
- ??一、需求分析 - 分紅包問題
- 🆙二、實作版本
- 1. 版本一:切西瓜法
- 2. 版本二:柵欄法
- ??三、在線Online
- 🆗四、結束語
- 🆚往期推薦
?前言
在現實生活中,非常常見的一個場景莫過于搶紅包,節假日長輩發紅包,生日時友人發祝福紅包,結婚時親朋好友發喜事紅包……無一場景不貫穿著我們生活中的方方面面,
但是呢,很多時候有可能一個紅包里面一兩百塊錢,而我們最后搶了幾毛錢,還真是沒有對比就沒有傷害……(欲哭無淚)
那在下面的文章中呢,我們將來實作一個微信紅包相關的分紅包功能,一起來了解叭~
??一、需求分析 - 分紅包問題
假設我們現在要進行發一個紅包,這個紅包的金額為 100 元,紅包數量是 10 個,那么我們要怎么樣分配,才能不失公平性呢?

那么接下來,我們由淺入深的來實作分紅包功能,
🆙二、實作版本
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塊錢,而其他就有可能出現分不下去的問題,所以,我們應該來處理這個問題,
那在上面的這個演算法中呢,俗稱切西瓜演算法,

我們每次都把這個金額分成兩部分,那么它總是會有大的一部分和小的一部分,那么這時候呢,我們挑選大的那部分再進行切分,切分完,我們就有三部分了,
繼續,我們從這三部分中把最大的那部分再繼續進行切分,以此類推,這樣的話,我們就會一直有的分,而不會出現沒得分的情況,
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>';
}
另外一種演算法呢,我們可以把它稱為是柵欄演算法,

假設說現在有 100 塊錢,那么我們可以把它看成是一個竹子,那如果你要把它分為 10 份的話,你要在中間的段里面去切 9 刀,那這9刀要切在什么位置呢,都是隨機的,如果要在 100 塊錢里面切 9 刀的話,那它是有 9999 種方案去切,也就是說,它有多少分錢,那么他就有 多少份錢 - 1 種的方式去切,
最后,我們來看一下效果,如下圖所示:

??三、在線Online
以上兩 個版本的在線地址:
- 版本一:切西瓜法
- 版本二:柵欄法
🆗四、結束語
在上面的文章中,我們首先談論了分紅包問題的隨機性,同時,用了切西瓜法和柵欄法來實作了分紅包功能,不知道大家對分紅包問題是否有了進一步了解呢?
如果您覺得這篇文章有幫助到您的的話不妨點贊支持一下喲~~😉
🆚往期推薦
👉緊跟月影大佬的步伐,一起來學習如何寫好JS(上)
👉緊跟月影大佬的步伐,一起來學習如何寫好JS(下)
👉每天都在紅綠燈前面梭行,不如自己來實作個紅綠燈?
👉冪等問題 vs 如何判斷是否是4的冪
👉如何給撲克洗牌才能更公平?
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/305255.html
標籤:其他
