golang 隨機概率的權重抽獎實現


package main

import (
    "encoding/json"
    "fmt"
    "math"
    "math/rand"
    "sort"
    "time"
)

type Prize struct {
    PlayerId int64
    Weight   int
}

func main() {
    //設置獎項名稱、權重等數組
    var prizes = make([]*Prize, 0)
    for i := 0; i < 4; i++ {
        prize := &Prize{
            PlayerId: int64(i) + 10000,
            Weight:   (5 - i) * 10,
        }
        prizes = append(prizes, prize)
    }
    for _, v := range prizes {
        fmt.Println(v.PlayerId, v.Weight)
    }

    RandomDraw(prizes)
}

// 權重隨機抽獎
func RandomDraw(prizes []*Prize) int64 {
    //權重累加求和
    var weightSum int
    for _, v := range prizes {
        weightSum += v.Weight
    }

    //生成一個權重隨機數,介於0-weightSum之間
    rand.Seed(time.Now().UnixNano())
    randomNum := rand.Intn(weightSum)

    //權重數組重組並排序
    randomNumTmp := &Prize{PlayerId: -1, Weight: randomNum}
    concatWeightArr := make([]*Prize, 0)
    aa, _ := json.Marshal(prizes)
    _ = json.Unmarshal(aa, &concatWeightArr)
    fmt.Println("concatWeightArr:", concatWeightArr)
    concatWeightArr = append(concatWeightArr, randomNumTmp) //將隨機數加入權重數組

    //將包含隨機數的新權重數組按從小到大(升序)排序
    sort.Slice(concatWeightArr, func(i, j int) bool {
        return concatWeightArr[i].Weight < concatWeightArr[j].Weight
    })
    sort.Slice(prizes, func(i, j int) bool {
        return prizes[i].Weight < prizes[j].Weight
    })

    for _, v := range prizes {
        fmt.Println(*v)
    }

    //索引權重隨機數的數組下標
    var randomNumIndex = -1 //索引隨機數在新權重數組中的位置
    for p, v := range concatWeightArr {
        if v.Weight == randomNum {
            randomNumIndex = p
        }
    }
    randomNumIndexTmp := math.Min(float64(randomNumIndex), float64(len(prizes)-1)) //權重隨機數的下標不得超過獎項數組的長度-1,重新計算隨機數在獎項數組中的索引位置
    randomNumIndex = int(randomNumIndexTmp)

    //取出對應獎項
    res := prizes[randomNumIndex] //從獎項數組中取出本次抽獎結果
    fmt.Println("本次抽獎結果:", res.PlayerId)
    return res.PlayerId
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM