Thanks to visit codestin.com
Credit goes to github.com

Skip to content

一个简单的概率抽奖小程序 #23

@kevinyan815

Description

@kevinyan815

不多解释,直接看代码~~

const lotteryBase = 10000

type LotteryPrize struct {
	Id                   int64   // 奖品ID
	Name            string  // 奖品名
	Rate              float64 // 中奖概率
        Type              int8 //    自行配置,比如实物奖、虚拟奖、谢谢惠顾之类的
	probability    int64   // 概率数 * lotteryBase 未导出, 只有内部程序需要使用它
	StockNum    int64   // 库存数
}


func GetLotteryPrize(lotteryPrizes []*LotteryPrize) (prize *LotteryPrize, err error) {
	var allProbability int64 //所有奖品的概率数总和
	var totalStockNum int64  // 所有奖品总库存
	// 奖品按照概率数从小到大排序
	sort.SliceStable(lotteryPrizes, func(i, j int) bool {
		return lotteryPrizes[i].probability < lotteryPrizes[j].probability
	})
        //  也可以把奖品Slice打成乱序的,更公平些
        //  RandSlice(lotteryPrizes)

	for _, prize := range lotteryPrizes {
		prize.probability = int64(prize.Rate * lotteryBase)
		allProbability += prize.probability
		totalStockNum += prize.StockNum
	}

	if totalStockNum == 0 || allProbability > lotteryBase {
		err = errors.New("奖品配置错误!")
		return nil, err
	}

	for _, prize := range lotteryPrizes {
		rand.Seed(time.Now().UnixNano())
		// 生成随机数
		lotteryNum := rand.Int63n(allProbability) + 1
		// 如果lotteryNum在奖品的probability内且奖品有库存则抽中金品
		if lotteryNum <= prize.probability && prize.StockNum >= 1 {
			return prize, nil
		}
		// 如果未抽中,缩减概率总数(allProbability - prize.probability)
		//  这样 筛选到最终,总会有一个数满足要求。
                //  不想每次都给用户发奖的话就把谢谢惠顾也设置成奖品,概率调成最大
		allProbability -= prize.probability
	}
	return
}


func RandSlice(slice interface{}) {
	rv := reflect.ValueOf(slice)
	if rv.Type().Kind() != reflect.Slice {
		return
	}

	length := rv.Len()
	if length < 2 {
		return
	}

	swap := reflect.Swapper(slice)
	rand.Seed(time.Now().Unix())
	for i := length - 1; i >= 0; i-- {
		j := rand.Intn(length)
		swap(i, j)
	}
	return
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions