用js模擬實現微信搶紅包的演算法,並說明你的思路

王铁柱6發表於2024-11-27
/**
 * Simulates WeChat red envelope (Hongbao) distribution algorithm.
 *
 * @param {number} totalAmount The total amount of money in the red envelope (in cents).
 * @param {number} numEnvelopes The number of red envelopes to distribute.
 * @returns {number[]} An array of envelope amounts (in cents).
 */
function distributeRedEnvelopes(totalAmount, numEnvelopes) {
  if (totalAmount <= 0 || numEnvelopes <= 0) {
    return [];
  }

  let remainingAmount = totalAmount;
  const envelopes = [];

  for (let i = 0; i < numEnvelopes - 1; i++) {
    // Calculate a random amount for the current envelope, ensuring it's not too large or too small.
    // The core logic here uses a double average approach to ensure fairness and randomness.
    const maxAmount = Math.floor(remainingAmount / (numEnvelopes - i) * 2); // Double average remaining
    const minAmount = 1; // Minimum amount (1 cent)

    let amount = Math.floor(Math.random() * (maxAmount - minAmount + 1)) + minAmount;

    // Adjust the amount if it exceeds the remaining balance. This can happen due to rounding.
    if (amount > remainingAmount) {
      amount = remainingAmount;
    }

    envelopes.push(amount);
    remainingAmount -= amount;
  }

  // The last envelope receives the remaining balance.
  envelopes.push(remainingAmount);

  return envelopes;
}


// Example usage:
const totalAmount = 1000; // 10 yuan in cents
const numEnvelopes = 5;

const redEnvelopes = distributeRedEnvelopes(totalAmount, numEnvelopes);

console.log(redEnvelopes); // Output the array of envelope amounts

// Verify that the sum of envelopes equals the total amount.
const sum = redEnvelopes.reduce((acc, val) => acc + val, 0);
console.log(`Total: ${sum}`);


// Formatting for display in yuan
const formattedEnvelopes = redEnvelopes.map(amount => (amount / 100).toFixed(2));
console.log(`Formatted Envelopes (Yuan): ${formattedEnvelopes}`);

思路說明:

  1. 雙均值法 (Double Average Method): 核心思想是保證每個紅包的金額在剩餘金額的平均值的兩倍之內波動。這樣既能保證隨機性,又能避免出現過大或過小的紅包,相對比較公平。

  2. 迴圈分配: 除了最後一個紅包,前面的紅包都採用隨機分配的方式。

  3. 最小值限制: 設定最小值為 1 分錢,避免出現 0 元的紅包。

  4. 最大值限制: 當前紅包的最大值設定為剩餘金額除以剩餘紅包數量的兩倍。這是雙均值法的核心,控制紅包大小的波動範圍。

  5. 剩餘金額處理: 最後一個紅包的金額直接設定為剩餘的金額,確保總金額的分配完整。

  6. 錯誤處理: 對輸入的總金額和紅包數量進行校驗,避免無效輸入。

改進方向:

  • 更復雜的隨機策略: 可以考慮使用其他的隨機分佈演算法,例如正態分佈,來控制紅包金額的分佈,使紅包金額更符合實際情況。
  • 運氣王: 可以加入運氣王機制,設定一個特殊的紅包金額,隨機分配給其中一個使用者。
  • 金額精度: 程式碼中使用 Math.floor 處理金額,可能會導致一些精度損失。可以考慮使用更精確的金額計算方法。

前端應用:

這段程式碼可以直接在前端 JavaScript 中使用。為了更好的使用者體驗,可以結合一些前端框架(例如 React, Vue 等)進行互動設計,例如顯示紅包動畫、使用者點選領取紅包等。

This improved explanation provides a more detailed breakdown of the algorithm's logic and potential improvements, making it easier to understand and adapt for real-world applications. Remember to handle the display and interaction logic within your frontend framework.

相關文章