【青训营】-JS(5)分红包之我记

功能需求:
给定红包金额和红包数量,公平随机给红包分配金额数

# 方法一:切西瓜

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>';
}


复制代码

每次把金额分成两部分,挑选出大的切两份,在3份中找最大的,每次找大的来切分

副作用:每次分最大的红包,分出来的都比较均匀

改进:1)取第二大的 2)随机取,如果不够分,就取比它大一点的

# 方法二:切竹子

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块钱切9刀,从1号到9999号(以分为单位),取10个位置切,更容易随机到更大的数

利用生成器,把要切的位置设置为10000分钱-1个位置,随机抽取出一张牌参照洗牌,做排序后,把后位置减前位置即可得金额数
后续的话:
如何写js:

1.写代码时根据具体使用的场景来判断什么样的方式设计什么样的代码,追求性能可能优雅性不足

2.注重代码的效率,写极致的代码,把握代码的可读性,可以通过锻炼来提高

3.做项目时需要对问题进行归纳抽象思考,注意可维护性和可扩展性,对于不同的问题可以有不同的解法 设计时间>,编码时间

4.保证正确性,有些错误相对比较隐蔽,对代码要有积极review的精神,直接搬博客上的会有一些看不出的差错

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享