网看有看到微信红包的分配算法,二倍均值法,就简单的实现了一个简单的版本
二倍均值法
设:人数:remainCount 剩余金额:remainMoney 红包随机金额范围为[1, remainMoney/remainCount*2] 最后一个红包金额为remainMoney
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
func main() {
// 声明初始化cache
cache := Cache{}
// 设置红包
remainCnt, remainMoney := setPacket()
// 元---> 分
remainMoney = remainMoney * 100
for {
// 输入姓名
rName := Input()
// 判读是否已抢
if val, ok := cache.Get(rName); ok {
fmt.Printf("你已抢到了%.2f元\n", float32(val)/100)
continue
}
// 分配红包
rMoney := randPacket(remainCnt, remainMoney)
fmt.Printf("恭喜你%s,抢到了%.2f元\n", rName, float32(rMoney)/100)
// 数据存储
cache.Set(rName, rMoney)
if remainCnt == 1 {
fmt.Println("红包被抢完了")
break
}
remainCnt--
remainMoney -= rMoney
}
}
// cache
type Cache map[string]int
// get
func (c Cache) Get(key string) (int, bool) {
if val, ok := c[key]; ok {
return val, ok
}
return 0, false
}
// set
func (c Cache) Set(key string, val int) {
c[key] = val
}
func setPacket() (count, money int) {
args := os.Args[1:]
sName := ""
if len(args) == 0 {
fmt.Printf("请输入发红包人姓名:")
fmt.Scanln(&sName)
fmt.Printf("请输入红包人数:")
fmt.Scanln(&count)
fmt.Printf("请输入红包金额(元):")
fmt.Scanln(&money)
} else {
sName = args[0]
count, _ = strconv.Atoi(args[1])
money, _ = strconv.Atoi(args[2])
}
fmt.Printf("%s发送了%d元红包, 开始抢红包。。。\n", sName, money)
fmt.Println("================华丽的分割线========================")
return count, money
}
func Input() string {
var name string
fmt.Printf("输入姓名抢红包:")
fmt.Scanln(&name)
return name
}
func randPacket(remainCnt, remainMoney int) int {
if remainCnt == 1 {
return remainMoney
}
rand.Seed(time.Now().UnixNano())
min := 1
max := remainMoney / remainCnt * 2
money := min + rand.Intn(max-min)
return money
}
第一个问题:注意分配的单位是按分进行计算,这样保证随机在整数范围内随机 第二个问题:数据存储,这里简单的使用了map做数据的存储,这是一种内存性存储,程序运行完就释放了,那么怎么将数据持久化储存呢?我们常用的方案是DB或本地文件。在后续的文章中,将对数据持久化作为一个专题进行展开,并实现一个简单的本地DB进行数据的存储。第三个问题:这一版主要为了展示红包的分配算法,没有实现网络通信,在第二版中,将在此基础上进行扩展,实现网络通信,先基于socket实现网路通信。