420武器的爆率,策划脑洞大开是要有多

设计师的无敌脑洞!盘点游戏中那些独特的武器_全球新网游_新浪游戏_新浪网
不再自动弹出
设计师的无敌脑洞!盘点游戏中那些独特的武器
11:55:39& &来源:
  游戏设计师总不吝于在自己作品中塞入各种脑洞,武器自然不例外。除了随处可见的常规型号,一些精心设计的又别出心裁的大杀器又别有一番独特的趣味性。在此我们列出十个有趣又奇怪的作品,想必当初使用它们的时候,你绝对爱不释手。
  10、D.Va的机甲——《守望先锋》
  “她来了,快跑!”这可能是你见到D.Va的第一反应,这意味着这名机甲少女正操作着她的机械武器长驱直入,从机甲中弹出并施放自爆。自然,对手见到此景因立即逃跑,那么假如你就是控制机甲的玩家呢?这场混乱恰是由你引起呢?当冲击波结束,看着游戏提醒弹出一连串消灭敌人带来的分数,这真是再过瘾不过了。
  9、黎明之锤——《战争机器》
  《战争机器》的世界中武器花样繁多,却没有几件能像黎明之锤这般带感。这件武器足够简单好用:首先使用激光制导瞄准敌人,接着一大束激光从上方轨道降落覆盖他们,将后者烧灭殆尽成为碎片。这种大快人心的体验可不是别的武器能比得上的。
  8、野生动物——《孤岛惊魂》
  看着它们走到敌人面前近身肉搏其实挺有意思的,尤其是在远处坐看敌人营地陷入的混乱可以给人带来极大的满足和享受。《孤岛惊魂》里的动物们就有这样的魔力,你可以不费一兵一卒不用任何武器弹药就把他们召唤到敌军的哨站或帐篷里,给敌军带来灭顶之灾。试试策划一场这样的混乱吧,这本身就是一场超有趣的实践。
  7、钻脑枪——《恐龙猎人2》
  《恐龙猎人》中的“钻脑枪”可是名副其实的大杀器,堪称史上最残忍的武器,让你之前费尽心思制造的屠杀看起来像过家家。顾名思义,钻脑枪发射出的子弹将钻入怪物的大脑,紧接着就会发出一串令人毛骨悚然的磨锯声,其中还夹杂着脑汁搅动的怪音。这种枪支面前,脑袋就像鸡蛋一样脆弱,嗡嗡作响加上牙医手术般的钻孔声,宛如来自地狱的摇滚。
  6、刺针枪——《光环》
  大多数情况下最棒的武器是不可以批量创作的,它们往往需要人卯足了劲儿从电玩模型中提取某一个创意元素。《光环》中的刺针枪就是模仿人造冲锋枪设计的一件高冷黑科技产品。你用它开火就会把一大把刺针扎入你敌人的背部,然后噼噼啪啪的声音之后就会出现爆炸。如果你手头有足够多的刺针,它们最终会组合成一个可带来大规模杀伤爆炸。看着刺针射向对手时划过的粉色烈焰是很好玩儿的。
  5、间谍之刃——《军团要塞2》
  许多游戏的武器放大招的时候都有亮瞎眼的特效,这款游戏中的“间谍之刃”就恰如其分的保持了低调。游戏中的间谍专门负责蹑手蹑脚地打入敌方阵营,他们迂回进入,然后找到合适的时机才卸下自己的面具。利刃杀伤力巨大,但是只能肉搏攻击,并要从敌人的背部砍下来效果最好。手刃一个敌人就足以暴露你的间谍身份,可以想象这在游戏进行过程中是多么风险与收益并存的战略部署。
  4、重力枪——《半条命2》
  《半条命》系列名气之响有多方面的原因:一个开放性的故事,默不作声的主角等,但最大的亮点还是别的游戏无可匹敌的重力枪,它将整个游戏世界变成了你的武器,把敌人们变成了布偶猫咪,按下这个武器的能量发动机你就相当于把战场变成了你的游乐场,最好玩的是当游戏最后你的重力机枪升级为超重力机枪的时候,那种坐拥天下的感觉是其他游戏没有的。
  3、胖子核弹——《辐射》系列
  人们普遍认为“胖子核弹”是《辐射》系列的最强武器,这可不是一句溢美之词,它由垃圾堆旁的废弃物拼接而成的,做成了一台发射器。但发射的不再是普通弹药而是核弹头。有何不同?你将会看到巨大蘑菇云升腾而起。如果不试它,你就没有资格说自己在《辐射》里的捡垃圾生涯中混迹过,对吧?
  2、声波枪——《黑街圣徒4》
  电子乐(dubstep)是一种广为接受的音乐类型,至于《黑街圣徒4》里的这款声波枪(dubstep gun),你将从中充分感受到设计者的幽默品味,看起来就像是把舞池上方DJ用的唱盘机整台改成枪一样。它利用电子乐的节奏发出一长串能量波,而波段则决定于你为枪支选择的皮肤颜色。当你开火后,游戏设置的低音部分会自动停止。这之后,所有你周围的一切(包括车辆),会随着音乐节奏摇摆晃动。这个机制不仅效果拔群,而且看起来非常滑稽。这种喜剧效果带来的欢乐不正是我们在游戏中使用这些武器的目的吗?
  1、BFG-9000——《毁灭战士》
  《毁灭战士》里的强力武器BFG9000,英文展开后是Big Fucking Gun,前两个词我不说你也知道,第三个是“枪”。这个武器就是一个金属大块头,武器的轮廓已经足够让人过目不忘,再加上一个响亮的名字,而且攻击性极强(把目力所及的对手杀干净),这使得它成为史上最伟大最受欢迎的FPS武器。作为“毁灭战士”游戏中最强有力的武器,它能把步入它射程范围的任何怪物消灭于无形。因为它能源源不断一轮又一轮地发射绿色血浆状物,让敌人闻风丧胆。
  来源:界面 翻译:高春晓
新浪声明:新浪网登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
中国游戏排行榜(China Game Weight Rank)是由新浪游戏推出的国内最全面、最专业、最公正、最客观的多平台游戏评测排行榜,包含了目前市场上所有的手游、端游、主机游戏、VR游戏、智能电视游戏及H5游戏,力图为中国玩家打造最值得信赖的游戏推荐平台。
评天下游戏、测产品深浅—新浪中国游戏排行榜CGWR!
新浪游戏APP
新浪游戏APP为广大玩家提供最及时、最个性化的聚合订阅游戏资讯,以及业内最丰富、最具价值的游戏礼包资源,首测资格、稀有道具,成为高玩就这么简单。新浪游戏APP论坛力求打造一个属于所有玩家的超大朋友圈,为玩家的生活增资添彩。新浪游戏秉承为玩家提供优质服务为宗旨,不断优化创新,让我们一起创造快乐!
全民手游攻略
全民手游攻略”是新浪游戏为全球手游玩家量身打造的一款手游攻略大全及专业游戏问答社区APP。“全民手游攻略”涵盖Apple Store游戏畅销榜前150名手游,网罗最新手游通关秘,帮助玩家畅玩手游;打造最全手游攻略资料站,帮你用最省钱方式吊打土豪。最火爆专业的游戏问答,让众多大神带你开启不同手游人生,寻找志同道合小伙伴一起并肩作战。
新浪游戏大事记
16年01月14日
16年01月14日
15年12月15日
15年11月19日
15年11月16日
15年01月08日
14年12月27日
14年12月17日
14年03月27日
14年01月09日
13年12月27日
13年12月07日
13年10月11日
用微信扫描二维码
分享至微信朋友圈终于被官方提起的DNF武器装扮问题 各位怎么看_兔玩DNF专区
您的当前位置:
终于被官方提起的DNF武器装扮问题 各位怎么看
最新的杂志社185期-增强与玩家间的沟通以改善样式的提案里提到了克隆修正方案如下:
6. 克隆武器装备修正方案
第一个武器装扮扩张slot
就在大家对时装热议的时候,海军礼包上线了并附带了这个武器装扮克隆礼盒。然而,我认为玩家们真正想要的并不是随意替换现有的极其有限的武器装扮,而是能够自由选择从低级到高级的所有武器的外观&&(几年了才想到你们也太机智了)
这次发售的这个克隆礼盒引起了诸多玩家的不满情绪,我也希望以后能够有机会能实现让玩家自由替换武器外观的功能,并且希望官方能有渠道听取玩家的这类诉求
时装选择还是应当符合大众审美观,尽管现在的的核心体验是副本,但2D像素画的魅力同样也是DNF的最大卖点之一并吸引了无数像素画爱好者。
虽然现在大家的关注重心在游戏开发和最新的魔兽地下城,但时装部分仍然需要团队倾以诚意。如果在游戏开发中厚此薄彼,导致的也是玩家对公司的信心缺失,最终仍然需要付出比以往更多的精力来为此买单。
想起了我4年前的脑洞帖关于武器装扮,脑洞了几个方案 不知道沃特碧们怎么看
和三年前的另一帖
完美装逼版【克隆武器装扮礼盒】脑洞创意
按现有的韩策意思,还是经典的时装--克隆时装替换意思
但是这个方案存在一些问题:
1,切换武器后由于武器时装不变,不方便判断手上拿着的是什么武器
2,只能替换角色已经拥有的武器
3,身上需要带这把外观武器,占一个格子
4,策划每个角色只能赚到一次钱
5,切换武器装扮比较麻烦
重新优化了一下当年的脑洞,沃特碧们感觉哪个更好?
方案一:透明武器装扮
使用方法:先穿透明、再带上你想要的武器,接下来随便怎么换武器都是第一把武器的外观.
优点:韩服策划官方思路,良心收费,一次购买永久使用,随便做个示意图:
缺点:如上所述1,切换武器后由于武器时装不变,不方便判断手上拿着的是什么武器2,只能替换角色已经拥有的武器
3,身上需要带这把外观武器,占一个格子
4,策划每个角色只能赚到一次钱
5,切换武器装扮比较麻烦
DNF资讯随身看!带我走吧主人!
公司地址:北京市石景山鲁谷路74号院中国瑞达大厦6层601 联系方式:010-
京公网安备77号
TUWAN Corporation,All Rights Reserved
北京兔玩在线科技有限公司 版权所有单身口撩投稿:201粉丝:1.7万未经作者授权 禁止转载
看过该视频的还喜欢miniOFF【守护者要塞广场】
【热点聚焦】
【日/周/月常】
【活动安利】
【脑洞专栏】
【优质游戏工具】
【优质玩家攻略】
【玩家团队招募】
【装备/套装/属性】
查看: 14410|回复: 170
【光明大陆 · 辩论赛】传奇装备爆率提升,是该打造图纸呢,还是该购买牌子装备?
【 传奇装备爆率提升,是该打造图纸呢,还是购买牌子装备?】【辩论时间】
~【参与方式】
1、投票;在帖子下方投票(按下“支持”按钮)选择你支持的立场。2、阐述观点;在正方或反方观点下方点击“加入”并回复你的观点(回复格式:游戏昵称+观点说明)。【活动奖励】
1、按照要求(投票+阐述观点)参与该活动的玩家可获得论坛20紫晶积分;
2、投票数最多的一方(按回复量计算)中将会有10名玩家获得【论坛冒险者礼包】(罗尼的魔法石*4,精粹宝箱*2,*,银币(W)*20);【活动说明】1、一定要先选择立场点击“支持”按钮进行投票;
2、后在支持的阵营中,按照“游戏昵称+观点说明”的格式回复内容;
19:54 裁判: 小白
正方观点 (185)
反方观点 (75)
购买牌子装备
按立场筛选:
打造是个坑
填不满的坑。
也没有那么多牌子可以用于刷装备属性吧……二者获取数量不成正比
牌子装备比较稳
还是老老实实的牌子换吧。
打造说是提高到25%几率出紫装 但是实际估计也就2.5%的几率。
刚打造完40武器,坑啊
请问下是谁说的传奇装备爆率提高!告诉我,绝对不打死他!
中了传奇装备的毒……犹豫几天,充了2000银子,心想图个开心嘛,2000去个KTV也基本就没了,玩这么久手游也没这么大方过,也就500到顶了,其实这游戏各方面还凑合,就这传奇装备给我整郁闷了,丟进去银子还不让人愉快的玩耍!说这个传奇装备,想着先整个20叶子换的披风看看,满怀激动的东拼西凑够了鉴定材料,哐当,鉴定个不伦不类的属性,巡林客你就偏偏弄个&&流浪,影鸦+3&&……
打造依旧是概率,还是虚
反正声望里面的不厉害
明天的更新算良心活动了,估计生活技能活了,
打造太看脸,还是先把声望套拿了在慢慢攒,骑驴找马
打造纯坑 20件一个紫 绿传奇蓝传奇
肯定牌子装备。毕竟打造,我脸黑
打造就是要的高风险高回报
游戏昵称:风语者、战歌& & 打造要的心跳
|||||||||||
, All Rights Reserved
杭州网易雷火科技有限公司版权所有 & |
违法和不良信息举报电话: 72224人阅读
[编程语言](132)
[算法相关](20)
[设计模式](13)
最近需要给公司内部编写一个随机生成人员名单的小工具,在解决这个问题的过程中,我认识到这是一个概率相关的问题,即使在过去我曾经设计过类似这样的应用程序,可我并不认为我真正搞清楚了这个问题,所以想在这篇文章中说说我对概率问题的相关思考。首先,我们来考虑这个问题的背景,我们需要定期在内部举行英语交流活动,可是大家的英语水差异悬殊,所以如果按照常规的思路来解决这个问题,即认为每个人被选中的概率是相等的话,实际上对英语不好的人是显得不公平的。其次,作为一个内部活动它需要的是营造一种氛围,让每个人参与到其中,所以它要求英语好的人有一个相对高的优先级,这样能够方便在活动开始前“破冰”,可是同时它需要让英语不好的人能够参与其中,所以这个问题该如何解决呢?这就是我们今天想要讨论的话题!
今天吃什么?
虽然我的确是一个对穿衣吃饭没有太多追求的人,可是作为这尘世间芸芸众生里最为普通的一个人,我们每天不可避免地会遇到这个问题。如同哲学家会从“认识你自己”这样一个基本命题发散出无数哲学问题一样,“今天吃什么”在某种意义上可能是比哲学问题还要重要的问题,尤其是对一个喜欢美食的吃货来讲,“今天吃什么”可能是整个世界里优先级最高的事情。
好了,我们从这个问题出发想要说明什么呢?通常我们解决这个问题最简单粗暴的方式是,罗列出附近所有的餐馆然后从中随机选择一家,现在主流的地图类APP基本上都有这样的功能,在每个餐馆被选中的概率相同的情况下,这种方案是没有什么问题的。可是我们都知道,人类作为这个世界上最复杂的一种动物,怎么会甘心让这个问题如此的简单呢?因为我们在选择的时候存在一个优先级的问题,例如我今天想吃红烧肉而明天想吃水煮鱼,显然因为个体偏好的差异每个餐馆被选中的概率是不相同的,因此在这种情况下,经典的概率理论是无法满足我们的要求的,那么此时该如何解决这个问题呢?
考虑到个人偏好对餐馆是否被选中的影响比较明显,因此实际上不同的餐馆拥有不同的优先级,这里我们假定有A、B、C三家餐馆,以你的个人喜好作为优先级评价标准,其优先级分别为2、3、5,则根据概率知识可知,P(A)=0.2、P(B)=0.3、P(C)=0.5。我们这里采用一种累加的思路来处理,令P(A)=P(A)=0.2、P(B)=P(A)+P(B)=0.5、P(C)=P(B)+P(C)=1,此时我们将P(A)、P(B)、P(C)三个概率值标注在数轴上,根据几何概型的相关理论,我们很容易地可以知道,0~0.2范围内可以表示餐馆A被选中的概率、0.2~0.5可以表示餐馆B被选中的概率,0.5~1可以表示餐馆C被选中的概率,此时我们可以借助各种编程语言提供的随机数功能来生成0~1间的随机数,然后根据随机数落在哪个区间内来处理结果。
我认为这个方案是比较不错的一种思路,在数学里有一种思想称为归一化,我们这里是将概率值从离散状态变为连续状态,而计算机更擅长我们生成一定范围内的随机数,所以这个方案为我们解决这类问题找到了一个不错的契合点,联想到转盘游戏其实是将0~1范围内的数字转换为0~360度范围内的角度,这一切就显得更加有趣啦!
概率与累积概率
在解决了“今天吃什么?”这样一个终极命题后,下面我们来从理论上对这个问题进行解释。第一个问题,什么是概率呢?根据百科全书中的定义,概率是概率论中的一个基本概念,它是度量随机事件发生的可能性的一个量,通常使用0~1间的实数来表示一个随机事件发生的可能性的大小,当其值越接近0时表示该随机事件越不可能发生,当其值月接近1时表示该随机事件越有可能发生。经典的古典概型理论指出,如果一个实验满足同时下列两个条件,则这样的实验就是古典实验:
* 实验只且只有有限个基本结果
* 每个基本结果出现的可能性相同
此时,对古典实验中的事件A,其概率定义为:P(A)=m/n,其中m为事件A包含的基本结果的数目,n为该实验中所有可能出现的基本结果的数目,这种概率定义的方法称为概率的古典定义。人们在重复实验的基础上进一步提出,在一定条件下,重复做n次重复实验,虽然实验次数的增加,如果某个事件的频率逐渐稳定在某一个数值p附近,则认为数值p即为事件A在该条件下发生的概率。这是建立在统计基础上的概率定义。显然我们发现这里存在问题,即古典概型是建立在所有事件发生的可能性相同这样一个基本假设的基础上的,于此同时我们可以注意到,概率是客观的而频率则依赖经验。对于概率甚至数学,人们一度认为它们都是严格的科学,对这种观点,我想引用庞加莱的一段话:
概率仅仅是我们无知程度的度量,据定义,我们不晓得其定律的现象,都是偶然现象。
好了,下面我们来关注一个新的概念,即累积分布函数(CDF,Cumulative Distribution Function),它能够完整描述一个实数随机变量X的概率分布,是概率密度函数(pdf,probability density function)的积分。其数学定义是F(X)=P(X&=x),表示随机变量小于或者等于某个数值的概率。为什么我们需要连续的随机变量呢?因为计算机产生的随机数通常都是指某个范围内的随机变量,而通常意义上的古典概型实际上是一种离散分布的数学模型,显然这两者间需要某种形式上的转换,所以我们需要累积分布函数,并且对连续函数而言,所有小于或者等于某个数值x的概率都可以认为,它等于数值x处的概率,因为我们能够保证累积分布函数严格递增,印象中诸如正态分布、均匀分布、泊松分布都是可以采用这种思路来处理的。好啦,更多理论层面的内容大家有兴趣的话可以自己去探索,这里我们想在这种理论的基础上设计一个基本的抽奖系统。
一个抽奖系统的设计
首先,我们必须指出计算机产生的随机数都是伪随机数,因此我们无法编写出100%随机的程序,而且事实上这种“随机”程度对我们来讲应该是完全足够了,所以在排除了这个因素的影响以后,我们基本上不能再为我们的应用程序寻找任何的借口,在这里我认为重要的一点是,我们能够有一个在理论和实践上都相对可行的方案,我们这里选择以一个简单的抽奖系统的设计为例来探讨这个问题。
随机概率公平吗?
抽奖系统最重要的是什么呢?是公平合理,那么怎样保证每次抽奖对所有用户来讲都是公平的呢?我认为首先要能够指定一个公平合理的规则,因为规则就如同人世间的法律正义、就如同璀璨夜空中的星辰宇宙一样,当它被确定下来以后就会一种永恒的真理。我们现在来考虑这样一个概率问题,假设我们有A、B、C、D四种不同的物品,它们各自被选中的概率分别为10%、20%、30%和40%,我们应该如何解决这个问题呢?通常可以想到的一种方案是,因为这四种物品被选中的概率之和为100%,因此我们将0~100范围内的数划分为[1,11)、[11,31)、[31,61)、[61,101),我们注意到这四个区间都是左闭右开的,因此每个区间的长度和概率完全对应,此时我们产生一个(0,101)间的随机数,然后根据随机数落在那个区间内来判断抽取物品的结果,这种方法称为随机概率,我们来看看它是如何实现的:
static void Main(string[] args)
List&Prize& prizes = new List&Prize&()
new Prize("奖品A",0.1d,1,11),
new Prize("奖品B",0.2d,11,31),
new Prize("奖品C",0.3d,31,61),
new Prize("奖品D",0.4d,61,101)
var seed = Guid.NewGuid().GetHashCode();
Random random = new Random(seed);
int rand = random.Next(1, 101);
var prize = prizes.Where(p =& rand &= p.RangeStart && rand & p.RangeEnd).FirstOrDefault();
Console.WriteLine("随机选取的物品为:" + prize.ID);
这段代码是非常简单的,可我想要问的一个问题是,我们这样的做法到底对不对呢。面对一个概率学的问题,如果要检验我们的算法是否正确,一个最简单的方式是判断其是否符合我们的预期,因为从概率的定义中我们已经可以了解到,概率是一种数学定义中的概念,我们可以通过大量重复试验的客观性来证明概率的确是存在的,并且我们可以合理地解释它为什么这样,可是这样到底对不对,我相信没有人能够给出确定的答案。现在我们来借助计算机通过大量的重复实验来证明我们的方法是否正确,根据频率和概率的关系,我们知道频率应该会在概率的某一个范围内上下波动,但是它整体上会越来越接近于概率。下面的表格给出了我在这个问题上的试验结果:
这里因为博主在尝试做1亿次重复试验时电脑运行时间非常漫长,就像在电影《模仿游戏》中艾伦.图灵制作的计算机器在破解德国加密设备“恩格尼玛”时,常常需要长达数月的运算周期一样,这种类比可能不是非常恰当,因为现代计算机的硬件水平是图灵所处的二战时期难以企及的,可是我们忽然发现一个非常沮丧的事实,我们在这里处理1亿次左右的循环,依然需要一段我们感觉上非常“漫长”的时间,而根据电影中的情节,图灵制作的计算机器需要完成159亿次的运算来尝试各种可能的组合,所以此时此刻我们是应该向这些推动人类进步的杰出人物诚恳地致敬,因为我们今天的一切都是来自这些人在当时看似疯狂的举动,或许人们曾将他们视为疯子而我更喜欢将其视为天才。
结果的确如我们所预期的那样,这里每组试验都是3次平行试验后的平均值,可以看到随着重复次数的增加,试验结果更加趋向我们理论上设计的概率值,因此这种情况下我们认为这个设计是合理的,即这个算法是公平的。可是这个世界让人头疼的一点是,我们每个人都理所当然地认为,只要是别人能得到而我们自己得不到地,就一定是有内幕、是不公平地,可是这个世界本来就是不公平的啊,谁掌握更多的社会资源、谁掌握绝对的话语权,“正义”的天平就会向谁倾斜,我们能做的无非是让自己变得更好,努力避免陷入某种被动的局面。
好了,言归正传,现在我们会发现一个问题,这种方案在奖品种类非常多的情况下,调整概率会是一件非常困难的事情,这就像工程师不喜欢产品经理和游戏策划,其真实原因并非是工程师无法实现特定需求,而是在整个建筑完成规划和设计以后,频繁的需求变更让一座伟大的建筑变成了临时的脚手架,你必须认识到这是工程师经过创作以后的某种产出,你可以不在乎这些无人问津的代码,可是我作为工程师我一定要比任何人都要在乎啊。
可是一个新的问题是,你永远无法为用户提供一种通用的解决方案,一个简单的抽奖在引入各种“自定义”规则以后,就注定不会再成为一个简单的抽奖,因为揣测一个人会说什么,对我这样一个不喜欢说话的人来说简直是种灾难,同样地,用户让计算机来做什么就应该明确地告诉计算机,而不是让工程师用各种各样的if-else来揣测用户想要做什么,我们常常说“优雅接口、肮脏实现”,在某种意义上就是指这种东西在永远浪费工程师的时间,用户愚蠢、用户懒惰,可是他们居然可以凌驾于工程师之上,这是对这个世界最大的恶意。好了,我们现在来动手解决新的问题,当用户需要在抽奖的时候对各种条件进行筛选同时还要考虑优先级和公平性这样一个问题吧!
让一切可复用
首先我们来考虑,如何设计一个可以复用的抽奖系统,在这个问题中我们关注两点,第一,这个抽奖系统可以支持不同类型的“奖品”;第二,这个抽奖系统可以支持不同类型的“抽取”方式。因为在这个问题中,按照某种优先级随机抽取人员或者物品其实应该是一类问题,而抽取我们都知道应该有可放回抽取和不可放回抽取两种,所以我们可以考虑通过泛型和接口来实现这样的需求。我们在这里定义一个IRankable接口,所有的“奖品”都要实现该接口,其定义如下:
interface IRankable
int GetRank();
我们可以发现该接口中只有一个GetRank()方法,这是因为我们这里的概率算法的基础是权重,所以我们只要为不同类型的“奖品”建立其相应的权重模型,就可以实现对不同类型奖品的支持。现在我们需要编写一个随机生成“奖品”的随机生成器,我们应该可以想到通过接口来约束泛型的思路,所以下面我们来实现一个随机生成器RandomGenerator。
首先我们可以想到的一点是,因为这里的泛型类型T需要实现IRankable接口,因此我们可以通过IRankable接口中定义的GetRank()方法来获取不同奖品的权重,在此基础上我们对奖品按照权重进行分组,则我们可以计算出每种权重在整个奖品权重中占到的百分比,我们以此作为每种权重奖品的概率,利用累积概率的思想可以非常容易地获得各种权重奖品对应的概率范围。其代码实现如下:
private void CalculateProbability(IEnumerable&T& source)
this.m_groups = source.GroupBy(e =& e.GetRank());
var totalRank = 0;
m_source.ToList().ForEach((item) =& { totalRank += item.GetRank(); });
m_probs = new Dictionary&int, double&();
foreach (IGrouping&int, T& group in m_groups)
var p = (double)(group.Key * group.Count() / (double)totalRank);
m_probs.Add(group.Key, p);
var totalProb = 0d;
m_totalProbs = new Dictionary&int, double&();
foreach (KeyValuePair&int, double& kv in m_probs)
totalProb += kv.V
m_totalProbs.Add(kv.Key, totalProb);
好了,现在我们就获得了不同权重物品所对应的累积概率,即其概率范围,因此我们可以利用随机生成[0,1)范围内的随机数,然后判断随机数所在哪个概率范围内,我们就可以知道要对哪个权重分组中的奖品进行抽取,而对每个权重分组来说,因为其权重都是一样的,所以这里抽取试验可以认为是符合随机概率的,我们只需要从该分组中随机选取一个奖品返回就可以啦。那么这里该如何查找概率范围内,我们这里选择经典的“二分查找”算法:
返回概率所在的区间索引
private int GetProbablityRange(Dictionary&int, double& totalProbs,
int begin, int end, double value)
if (begin &= end) return
int mid = (begin + end) / 2;
if (totalProbs.ElementAt(mid).Value &= value)
return GetProbablityRange(totalProbs, begin, mid, value);
return GetProbablityRange(totalProbs, mid + 1, end, value);
那么好了,现在我们该怎么从这些奖品中随机抽取一个奖品呢,我们这里提供了随机生成1个奖品和随机生成指定数目个奖品的方法重载,我们以前者为例来看看它的实现过程:
随机抽取一个奖品
public T Generate()
var seed = Guid.NewGuid().GetHashCode();
var random = new Random(seed);
double rand = random.NextDouble();
T result = default(T);
int index = GetProbablityRange(m_totalProbs, 0, m_totalProbs.Count - 1, rand);
switch (m_option)
case GenerateOption.CanReplace:
result = GenerateCanReplace(index, random);
case GenerateOption.NoReplace:
result = GetnerateNoReplace(index, random);
在这里我设计了两种不同的抽取方式,即可放回抽取和不可放回抽取,两者的区别在于前者奖品池中奖品的数目保持不变,而后者奖品池中奖品的数目会发生变化,而更本质的区别在于前者奖品概率保持不变,而后者概率会发生变化。后者在每次抽取完以后需要将抽中的奖品从奖品池中取出,重新计算概率后方能进行下一轮抽取,所以这里我们直接给出这两两种抽取方法的代码实现,这里需要考虑的一个问题是,在抽取指定数目个“奖品”的时候我们通常不希望出现重复的元素,前者需要我们判断已抽取的奖品列表中是否存在指定元素,而后者因为抽取的奖品会被取出,所以不需要考虑这种情况的处理。
可放回抽取
&/summary&
private T GenerateCanReplace(int index, Random random)
int rank = m_totalProbs.ElementAt(index).K
var group = m_groups.Where(e =& e.Key == rank).FirstOrDefault();
if (group == null)
group = m_groups.ElementAt(random.Next(0, m_groups.Count()));
return group.ElementAt(random.Next(0, group.ToList().Count));
不可放回抽取
private T GetnerateNoReplace(int index, Random random)
int rank = m_totalProbs.ElementAt(index).K
var group = m_groups.Where(e =& e.Key == rank).FirstOrDefault();
if (group == null)
group = m_groups.ElementAt(random.Next(0, m_groups.Count()));
T result = group.ElementAt(random.Next(0, group.ToList().Count));
var list = m_source.ToList();
list.Remove(result);
m_source =
CalculateProbability(m_source);
在此基础上实现指定数目的奖品就会变得非常简单啦,因为我们只需要重复调用这个方法就可以啦,那么现在我们该如何使用这个随机生成器呢?一起来看一段示例代码:
List&Contract& contracts = new List&Contract&();
contracts.Add(new Contract() { Name = "People0", Level = "Senior", Priority = 1 });
contracts.Add(new Contract() { Name = "People1", Level = "Senior", Priority = 1 });
contracts.Add(new Contract() { Name = "People2", Level = "SSE", Priority = 10 });
contracts.Add(new Contract() { Name = "People3", Level = "SSE", Priority = 1 });
contracts.Add(new Contract() { Name = "People4", Level = "SSE", Priority = 1 });
contracts.Add(new Contract() { Name = "People5", Level = "SE", Priority = 1 });
contracts.Add(new Contract() { Name = "People6", Level = "SE", Priority = 1 });
contracts.Add(new Contract() { Name = "People7", Level = "SE", Priority = 1 });
contracts.Add(new Contract() { Name = "People8", Level = "SE", Priority = 1 });
contracts.Add(new Contract() { Name = "People9", Level = "SE", Priority = 1 });
contracts.Add(new Contract() { Name = "People10", Level = "Senior", Priority = 1 });
contracts.Add(new Contract() { Name = "People11", Level = "Senior", Priority = 1 });
contracts.Add(new Contract() { Name = "People12", Level = "SSE", Priority = 1 });
contracts.Add(new Contract() { Name = "People13", Level = "SSE", Priority = 1 });
contracts.Add(new Contract() { Name = "People14", Level = "SSE", Priority = 1 });
contracts.Add(new Contract() { Name = "People15", Level = "SE", Priority = 1 });
contracts.Add(new Contract() { Name = "People16", Level = "SE", Priority = 1 });
contracts.Add(new Contract() { Name = "People17", Level = "SE", Priority = 1 });
contracts.Add(new Contract() { Name = "People18", Level = "SE", Priority = 1 });
contracts.Add(new Contract() { Name = "People19", Level = "SE", Priority = 1 });
RandomGenerator&Contract& generator =
new RandomGenerator&Contract&(contracts,GenerateOption.NoReplace);
var list = generator.Generate(10);
foreach (var contract in list)
Console.WriteLine(contract.Name);}
在这里Contract实现了IRankable接口,每个Contract的权重由Level和Priority两个属性来计算,示例中我们一次从集合中随机抽取了10个Contract,而我们的算法能够保证它们都是不重复的,这个程序可以满足各种各样的抽取规则,比如按照Contract的口语、职位等不同的维度进行概率模型的建立即可,只要它实现了IRankable接口就可以使用这篇文章中的方法来随机抽取,这其实是一个业余时间的小项目啦,可我还是想让自己认真地考虑下这个问题,所以我花时间写了这篇文章,我对它的期望并没有太高,我喜欢将这些想法写下来而已。
或许有些时候我们对一个事情的态度,对事情最终的走向起不了决定性的作用,尤其是在我们没有掌握话语权的时候。可我在考虑这个方案的时候,是明显地意识到程序永远无法满足人类的脑洞的需要,所以当我们在做一件事情的时候,就应该有意识地让自己想到它可能会有扩展性上的需求,我认为这是我们在做项目开发过程中需要去关注的一个点,如何让你的代码具备扩展性和可维护性,虽然有时候你想得太多会造成过度设计,可是如果你在项目前期做出了一个糟糕的规划,到了后期遭遇项目需求变更的时候就会非常痛苦,可不幸的是我在最近同时遭遇了这两种情况,或许这就是我想要强迫自己写完这篇文章的原因吧,这篇文章足足花了我两周的时间,我的拖延症啊什么时候能好啊!
关注个人公众号,博客更新早知道!}

我要回帖

更多关于 脑洞大开 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信