手写实现抢红包

261 阅读3分钟

问题

面试官:抢红包,定义一个类,传递红包大小和人数,定义一个roll方法,每人最少分0.01,当roll调用次数大于人数的时候报错,roll返回每个人红包大小

解决步骤

  1. constructor 构造函数:

    • 接受 moneycount 作为参数,表示红包的总金额和总人数。
    • 在构造函数中,首先进行检查,确保总金额足够分配给所有人。如果总金额不足以保证每人至少分到 0.01 元,就会抛出错误。
    • 将传入的 moneycount 和一个初始的 rolls(已抢红包的次数)保存为类的成员变量。
  2. roll 方法:

    • 当调用 roll 方法时,首先检查是否已经抢完了所有的红包。如果已经抢完,就会抛出错误。
    • 增加 rolls 计数表示已抢红包的人数。
    • 当所有人都已经抢到红包的情况下,将剩余的金额返回给最后一个人。
    • 计算每人分到的最小金额 minAmount,然后根据剩余的总金额和剩余人数计算每人分到的最大金额 maxAmount
    • 生成一个随机比例因子,将其乘以 maxAmount - minAmount,再加上 minAmount,得到每人分到的随机金额。
    • 将分配的金额从总金额中减去,以更新剩余总金额。
    • 使用 toFixed(2) 将随机金额保留两位小数,以确保输出的金额格式正确。
  3. 创建一个 RedPacket 实例,并进行 5 次循环,每次抢红包,输出每个人的红包大小。

// 抢红包,定义一个类,传递红包大小和人数,定义一个roll方法,每人最少分0.01,当roll调用次数大于人数的时候报错,roll返回每个人红包大小
class RedPacket {
  constructor(money, count) {
    if (money < count * 0.01) {
      throw new Error("总金额并不足够所有人使用");
    }

    this.money = money; // 总金额
    this.count = count; // 总人数
    this.rolls = 0;
  }

  roll() {
    if (this.rolls >= this.count) {
      throw new Error("来晚了,红包已经被抢完了!");
    }

    this.rolls++;
    // 在所有人都已经抢到红包的情况下,将剩余的金额返回给最后一个人。
    if (this.rolls === this.count) {
      return this.money.toFixed(2);
    }
    // 每个人分到的最小金额,根据题目要求为 0.01
    const minAmount = 0.01;
    // 是每个人分到的最大金额,它根据剩余的总金额以及剩余的人数来计算。
    const maxAmount =
      (this.money - (this.count - this.rolls) * minAmount) /
      (this.count - this.rolls);
    // 使用 Math.random() 生成一个随机的比例因子,它的范围在 0 到 1 之间。
    // 将这个随机的比例因子乘以最大金额和最小金额的差值,然后加上最小金额,得到一个在最小金额和最大金额之间的随机金额。
    const amount = Math.random() * (maxAmount - minAmount) + minAmount;
    // 将分配的金额从总金额中减去,以更新剩余总金额。
    this.money -= amount;
    // 使用 toFixed(2) 将金额保留两位小数,以确保输出的金额格式正确。
    return amount.toFixed(2);
  }
}

// 创建一个红包,总金额为 10,总人数为 5
const redPacket = new RedPacket(10, 5); // 创建一个红包,总金额为 10,总人数为 5

// 循环5次,每次抢红包,输出每个人的红包大小
for (let i = 0; i < 5; i++) {
  console.log(`Person ${i + 1} gets ${redPacket.roll()} yuan`);
}