怪物掉落金币随想

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

总共有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

时间: 2024-11-05 20:47:46

怪物掉落金币随想的相关文章

求不相邻金币相加和的最大值--动态规划1

求不相邻金币相加和的最大值. 输入n个金币的金币面值(正数自定义),求这些金币不相邻和的最大值. 动态规划问题1 设f(n)为第n个金币数的最大值,f(0)=0,f(1)=a[1],输入的数组从下标为1开始. f(n)=max{a[n]+f(n-2),f(n-1)}. 代码如下: import java.util.Scanner; public class Jin_bi_zui_da_zhi { public static void main(String[] args) { Scanner s

网络技术与技术革命周末随想

无知者最好别在公共场合喷粪 周五下午下班坐地铁匆匆回家,由于老婆要去外地开几天会议,我周末就要做全职奶爸了,一想到这个就兴奋,可以和我家小小独处了,加深一下父女感情,于是哼着歌,同时看着<黑客大曝光>,时不时瞟一下旁边的美女... 一个声音顿时让我有一种想打人的冲动,于是旁边的美女在我眼里化作了漫天烟云.声音来自我的身后,透过玻璃反光能看得出是一个奇丑无比的年轻女性程序员, 身高150cm不到,体重约摸大于等于130斤,大声嚷嚷:网络没什么好学的,只要理解大概原理,能通就行,现在谁还搞网络啊,

noi 1.5 45:金币

描述 国王将金币作为工资,发放给忠诚的骑士.第一天,骑士收到一枚金币:之后两天(第二天和第三天)里,每天收到两枚金币:之后三天(第四.五.六天)里,每天收到三枚金币:之后四天(第七.八.九.十天)里,每天收到四枚金币--这种工资发放模式会一直这样延续下去:当连续N天每天收到N枚金币后,骑士会在之后的连续N+1天里,每天收到N+1枚金币(N为任意正整数). 你需要编写一个程序,确定从第一天开始的给定天数内,骑士一共获得了多少金币. 输入 一个整数(范围1到10000),表示天数. 输出 骑士获得的

阿里前端两年随想

阿里前端两年随想 其实按照我的情怀和尿性,文章的标题应该是 前端登堂入室宝典.前端成长就这三招 之类,奈何这是篇软文 ~ 看官先别急Command + W,尤其是和我经历类似 做着其它岗位的工作,却多少会接触一些前端 发现有些兴趣,但又不肯定这应该是自己未来 也会有些成就感,但似乎挫折和沮丧来的更多一些 我可以负责任的说,这是一篇有态度的软文 欲语泪先流 我希望做些有用的事情,甚至可以做个有用的人 才毕业工作的第一年我是满足的,学到了很多新知识,写的代码不但能work,还能真的跑在生产环境中 我

求换取零钱的最少金币个数个数--动态规划问题2

输入m个数字(正数,必须含有1.)代表金币的面值,再输入n代表换钱的总额,求换取的最少金币个数. 动态规划问题2 动态规划的基本思想是将待求解问题分解成若干个子问题,先求解子问题,并将这些子问题的解保存起来,如果以后在求解较大子问题的时候需要用到这些子问题的解,就可以直接取出这些已经计算过的解而免去重复运算.保存子问题的解可以使用填表方式,例如保存在数组中. 代码如下: import java.util.Scanner; public class Jin_bin_zhao_ling { publ

[自动化-脚本]001.自动领淘金币:Anyweb模拟操作

通过模拟手工操作的方法领取淘金币.该方法万能且通用,有能力的还可以自行修改脚本. 工具 软件下载 anywebscript.com 方法/步骤 1.安装软件如图所示 2.设置脚本: (1)进入网站:[脚本商店\模拟点击领取淘金币]并复制脚本 (2)打开软件的“新建”按钮 (3)将脚本粘贴到“功能代码”处 3.测试脚本: (1)设置用户名.密码: 方法一:可以直接在脚本中改(仅供测试使用) 方法二:把脚本的用户名.密码那两行去掉,并在下面的测试框中输入用户名.密码(实际使用时请采用方法二) (2)

签到领金币脚本

1 #!/use/bin/env python 2 # -*- coding: utf-8 -* 3 # Author : nick 4 # Desc : v2ex每日签到 5 6 import urllib 7 import urllib2 8 import cookielib 9 import re 10 import sys 11 from bs4 import BeautifulSoup as bs 12 from datetime import datetime 13 14 15 re

网上推广随想

网上推广.不管是什么,终极目的就是让人在网上能够了解到.搜索到自己.如果在网上不能被查到,自己心理就不放心,总担心别人会质疑自己的存在,事实也基本如此. 但是,10年前不是这样的. 曾经,就是10多年前,我鼓捣一些公司做网站,当然自己是从中有油水的.那些老板一般反问:做网站有什么用途?有谁会到网上看我的东西,他们都是打电话订购. 10年后,还是这些做家具.做图书.做培训等等跟网络相去较远的老板们,已经是众多做网络推广的公司的收入来源,他们已经迷信网络推广能够带来滚滚财源了.一般的套路就是花钱,在

学习随想----按照“程序化”来管理我们的学习

有的时候,总是在思考我们所学的技术能够指导我们的生活跟工作不能.在今晚听完包老师的课后,好像有所启发. 第一堂课讲的是面向云计算,实时数据处理的数据中心.虽说内容记忆了许多,但是对未来的趋势个人觉得把握的很好.详细讲解了为什么服务器市场是那么的重要,同时也有点明白华为为什么那么看重他的服务器产品线.实际上,未来的趋势,IDC会占很大的趋势,云的推出势必会将用户的存储投资一降再降.大量的文件会存储在远端服务器上.当前的矛盾主要集中在用户的感知响应时间上,而这一方面,除去网络及用户端的响应时间上,数