当前位置:首页 > JavaScript

js实现一个权重抽奖

2026-03-02 00:56:55JavaScript

js实现一个权重抽奖

权重抽奖实现方法

权重抽奖的核心是根据不同奖项的权重值计算概率,并通过随机数选择对应的奖项。以下是基于JavaScript的实现方法:

js实现一个权重抽奖

方法一:使用累积概率区间

function weightedDraw(prizes) {
  // 计算总权重
  const totalWeight = prizes.reduce((sum, prize) => sum + prize.weight, 0);

  // 生成随机数
  const random = Math.random() * totalWeight;

  // 遍历奖品计算累积权重
  let currentWeight = 0;
  for (const prize of prizes) {
    currentWeight += prize.weight;
    if (random <= currentWeight) {
      return prize;
    }
  }

  // 默认返回最后一个
  return prizes[prizes.length - 1];
}

// 使用示例
const prizes = [
  { name: "一等奖", weight: 1 },
  { name: "二等奖", weight: 3 },
  { name: "三等奖", weight: 6 }
];
const result = weightedDraw(prizes);
console.log(result.name);

方法二:预计算概率表(适合高频调用)

class WeightedRandom {
  constructor(items) {
    this.total = items.reduce((sum, item) => sum + item.weight, 0);
    this.table = items.map(item => ({
      value: item.value,
      threshold: item.weight / this.total
    }));
    // 计算累积概率
    let accum = 0;
    this.table = this.table.map(item => {
      accum += item.threshold;
      return { ...item, accum };
    });
  }

  draw() {
    const random = Math.random();
    return this.table.find(item => random <= item.accum)?.value;
  }
}

// 使用示例
const wr = new WeightedRandom([
  { value: "黄金", weight: 10 },
  { value: "白银", weight: 30 },
  { value: "青铜", weight: 60 }
]);
console.log(wr.draw());

方法三:ES6优化版本

const weightedRandom = (items) => {
  const total = items.reduce((acc, { weight }) => acc + weight, 0);
  const rand = Math.random() * total;
  let sum = 0;

  return items.find(({ weight }) => (sum += weight) >= rand)?.item;
};

// 使用示例
const items = [
  { item: "iPhone", weight: 5 },
  { item: "iPad", weight: 15 },
  { item: "优惠券", weight: 80 }
];
console.log(weightedRandom(items));

关键点说明

  • 权重值可以是任意正数,不需要总和为1或100
  • 权重越大被抽中的概率越高
  • 算法时间复杂度为O(n),对于大量选项可考虑二分查找优化
  • 随机数生成使用Math.random(),如需更安全随机数可使用crypto.getRandomValues()

实际应用扩展

对于需要展示概率分布的场景,可先计算各奖项的实际概率:

function calculateProbabilities(prizes) {
  const total = prizes.reduce((sum, p) => sum + p.weight, 0);
  return prizes.map(p => ({
    ...p,
    probability: (p.weight / total * 100).toFixed(2) + '%'
  }));
}

以上实现可根据具体需求调整,如添加重复抽奖限制、奖品库存控制等功能。

标签: 权重js
分享给朋友:

相关文章

js实现乘

js实现乘

JavaScript 实现乘法运算 在 JavaScript 中实现乘法运算可以通过多种方式完成,包括基本运算符、函数封装以及高级算法(如大数乘法)。以下是几种常见方法: 使用基本乘法运算符 Jav…

js实现拷贝

js实现拷贝

实现文本拷贝 使用 document.execCommand 方法(已废弃但兼容性较好): function copyText(text) { const textarea = document…

js实现报表

js实现报表

使用JavaScript实现报表 在JavaScript中实现报表功能可以通过多种方式完成,常见的方法包括使用原生JavaScript、第三方库(如Chart.js、D3.js)或结合后端数据渲染。以…

js实现游标

js实现游标

使用JavaScript实现游标 在JavaScript中,可以通过操作DOM元素的cursor样式属性来实现自定义游标效果。以下是几种常见的实现方法: 修改默认鼠标指针样式 通过CSS的curso…

js实现vue路由

js实现vue路由

Vue 路由的基本实现 在 Vue.js 中实现路由功能通常使用 Vue Router 库。Vue Router 是 Vue.js 官方的路由管理器,用于构建单页面应用(SPA)。 安装 Vue R…

js实现正交

js实现正交

正交的概念 正交在数学和计算机科学中通常指两个向量垂直或线性无关。在编程中,正交性常被用于设计模块化、低耦合的系统。 向量正交判断 判断两个向量是否正交可以通过点积是否为0来实现: fun…