Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
kevinyan815 opened this issue Nov 14, 2020 · 0 comments
Open

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

kevinyan815 opened this issue Nov 14, 2020 · 0 comments

Comments

@kevinyan815
Copy link
Owner

kevinyan815 commented Nov 14, 2020

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

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
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant