游戏命中判定:圆桌算法和程序实现
游戏命中判定:圆桌算法和程序实现游戏中常常要做一个动作的命中判定,比如攻击的命中判定,结果一般为未命中、普通命中,致命命中,命中格挡等(当然复杂起来远不只这些)。一般的,程序上(或策划上)采用的是优先级概率算法或者圆桌算法。 优先级概率的算法是:先判定是否未命中,如果命中是否闪躲,如果未闪躲是否招架,最后才是普通攻击(有省略)。也就是说按优先级(顺序)进行概率计算和判断。
圆桌算法是将这些属性(命中普通攻击、未命中、招架、命中致命攻击)放在一起,构成一个圆桌。如20%未命中,5%致命攻击,30%招架,剩余45%为普通攻击。
从上面的描述来看,圆桌算法输入的参数是一个代表概率的数组,或者,更广泛地说是一组系数。我们完全没有必要将参数固定为合起来为100%的概率值(虽然这么做同样可行)。因为当我们知道一组系数的时候,我们也同时知道了每个系数在这一组数据中所占的比例。如我们可以使用10,20,30来做参数,显然,10所占的比例是10/(10+20+30)为1/6,同样的,20占2/6,30占3/6。所以这扩展了程序员和策划的自由度。而圆桌算法的输出则是一个代表圆桌某一个部分的索引。例如0表示10的部分,1表示20的部分,2表示30的部分。这里要注意的是,这些系数显然必须是一个正数,负值的系数是没有意义的。 算法的流程是:随机生成一个数字,判断这个数在哪个区间中,然后输出这个区间的编号即可。当然,我们可以生成一个介于0到1的数字,然后判定分布于哪个概率区间即可。在文章的最后将给出具体C#代码。 继续,我们讨论关于圆桌算法牺牲属性的问题(吃完普通攻击吃致命一击的问题)。这个问题的描述是(http://baike.baidu.com/view/1927517.htm): 对于例子: 目标的躲闪几率……20% 目标的招架几率……5% 战士的致命一击率……30% 当闪躲增加50%时按照刚才的圆桌理论算法结果为: 躲闪几率70% 招架几率5% 致命一击几率25%(30%-5%) 出现普通攻击的几率0 % 随着属性的增加,例如当躲闪提高到90%,招架提高到15%的时候,会出现如下的属性: 出现躲闪字样的几率90% 出现招架字样的几率10%(15%-5%) 出现致命一击的几率0% 出现普通攻击的几率0% 这一次,作出牺牲的是普通攻击,致命一击还有招架,其中致命一击已经完全被牺牲掉,这对于结果的公平性是很大的负面影响。 但是,可以有另外一种计算方法,而不用牺牲个别属性,这就是本文提出的方法。 同样的例子(我们用X代表属性,第二列的数字表示概率或者说系数):
如果X1提高到70%, 那么其他属性自然而然地降低。为什么都要降低呢?很合理的,而原来的几率是相对于整个圆桌而言的,当整个圆桌因为一个属性的几率增大时,其他属性就会按比 例的缩小,这样才能体现公平性了。因为前面的方法不合理的地方就是在于先牺牲了一种属性。这里有一点要说的是,将一个属性的几率提高到100%以上是没有意义的,因为100%就意味着必然发生。 那么将X1几率提高到70%后其他应该怎么变化呢?上面已经提到——按比例。在该例子中,原来X2几率为5%,X3为30%,剩余X4为45%,除去X1后, X2占剩余的5%/(1-20%)=5/80 X3占30/80 X4占45/80 当X1几率提高到70%,剩余30%供其他属性分享。因此结果是:
合起来依然是100%。于是在数值上的合理性就可以验证了。(代码依旧在文章的最后。)
但是在实际上,新问题会不断出现,主要表现在调整的先后顺序上,即先提高X1到70%,再提高X2到70%,和先提高X2到70%再提高X1到70%,得到的结果完全不同,程序计算结果如下:
表1
表2
这组数据表明,调整的先后顺序会影响计算的结果。我们不妨想象在真实的游戏中,玩家开启闪躲技能,将闪躲提高到了70%,那么玩家希望的就是不被命中。然后开启招架技能,将招架提高到了70%,这时玩家希望的是同时拥有70%的闪躲和70%的招架。也就是说如果被命中(30%),尽量出现招架。但是表1表明此时闪躲的概率降低了,不满足玩家期望的效果。
这个问题本质上是优先级问题,圆桌上的所有属性应当是同优先级的。我们可以将命中判定分为2个部分,对于存在优先级的属性采用优先级概率算法,对于同优先级的采用圆桌算法。这样会形成如下图的结构:
实际中可以先做命中和非命中的圆桌运算,然后做其他优先级相同的属性的圆桌运算,输出最终的命中类型。当然如果还有属性中的优先级需要存在,我们可以再做一轮圆桌计算。
从这样的分析来看,圆桌算法的程序实现上不存在这样的问题。所以圆桌算法类应该有以下几个功能:
1、通过输入的参数输出结果。2、通过输入参数能够调整一个系数。
具体代码见链接地址(链接地址)
|