zoukankan      html  css  js  c++  java
  • 怪物掉落金币随想

    想必大家在过年的时候玩微信抢红包非常高兴,今天项目中碰到一个问题:

    总共有2000金币,需要随机掉落到N个怪物身上,每只怪掉率的金币不的少于 2000/(2 * N), N 可以被2000 整除。

    遇到这个问题后,我想到了过年时大家都玩的很高兴的微信红包,当时我想到了微信红包这种随机算法是如何实现的,其中有没有顺序漏洞存在,这样通过领取的时机让自己利益最大化。因为很多微信红包在群里发的时候,都是整个群所有成员全体发,这样的话每个人都会都到一个红包,是不是我最后一个领,得到的最多?后来这个问题就搁浅了,没在去想,这两天项目中遇到了同样的问题,大概思考了一下,写出了游戏中怪随机掉落的算法。

    def get_reward_arr(coin_sum, n):
        det_coin = coin_sum / n
        coin_arr = [det_coin for i in range(n)]
        max_lose_coin = det_coin / 2 - 1
    
        for i in range(n):
            lose_coin = random.randint(0, max_lose_coin)
            win_index = random.randint(0, n - 1)
            coin_arr[i] -= lose_coin
            coin_arr[win_index] += lose_coin
    
        return coin_arr

    程序首先将金币分成N等份,然后从每份中拿出最多一半的金币,在随机出一个获得金币的index,将此金币加到获得金币的index。

    上面是我想到的一种方式,还有一种常见的方式:

    def get_reward_arr(coin_sum, n):
        rand_arr = [random.randint(n / 2, n) for i in range(n)]
        rand_sum = reduce(lambda x, y: x + y, rand_arr)
    
        coin_arr = [(rand_arr[i] * coin_sum) / rand_sum for i in range(n)]
    
        return coin_arr

    这种方式是先随机出一组数组,然后每次通过随机出占用比来得到获得的金币数。

    结果有一天看到一篇博客里有谈到微信红包的实现方式,为了节省空间,他们利用了随机种子一定,则随机数就一定的原理,每次只记录总钱数,第几次获取,随机种子,总共分多少人。数据结构大概是:money, n, times, seed。这里不讨论具体微信如何处理浮点数,如何处理锁的问题,只探讨随机实现方式:

    def get_reward_coin(coin_sum, n, seed, times):
        random.seed(seed)
        rand_num = 0
        rand_sum = 0
    
        for i in range(n):
            ret = random.randint(n / 2, n)
            rand_sum += ret
            if i == times:
                rand_num = ret
    
        return (rand_num * coin_sum) / rand_sum

    通过cpu的时间来节省内存空间,非常聪明的做法。

    上面的算法并没有考虑浮点数的问题,如果项目中涉及到浮点数问题,对于不同的项目有不同的解决方案。

    所有的测试代码可以通过访问这里。参考到的文章可以访问后端技术 by Tim Yang

  • 相关阅读:
    温习:ASP.NET页面生命周期
    浅析大型网站的架构
    ASP.Net2.0小技巧 保持滚动条的位置 焦点移动到某个控件 $符号轻松的使用FindControl
    hiberfil.sys msocache,cpce&天极网,终结析沟,viewstate,cache,scroll不变,换行,cs下换行,为空,marshalbyrefobject,gettype,主题,getlegth(0),is
    Crontab中使用>&的问题
    到底什么是MiddleWare(中间件),请用plain English描述
    Dell D630安装SATA AHCI驱动的方法
    What Is Bootloader And How To Unlock Bootloader On Android Phones
    SCSI和RAID的相关知识
    Defy GPRS设置
  • 原文地址:https://www.cnblogs.com/fengju/p/6174286.html
Copyright © 2011-2022 走看看