找回密码
 点一下
查看: 5654|回复: 12

随机数的讲解与运用

[复制链接]
发表于 2008-8-6 13:40:53 | 显示全部楼层 |阅读模式
前言
本人能力有限,所以所讲解的例子全部为trigger,并不涉及JASS编写
一.理论
首先,魔兽内的随机数为伪随机。不要被字面上迷惑了,就像JASS为解释性语言,不是基础性语言,可是我们还是可是使用JASS编写函数。所以,伪随机还是随机,只不过我们无法改变其中本质。
那么伪随机是个什么存在呢?使用WE测试过随机数的朋友们都知道要先关闭WE参数里的固定随机种子,即SEED。这就是这里的关键,随机种子是和随机数列联系在一起的。假如我们不选中固定随机种子,每次加载地图的时候都会随机一个数值做为随机种子。那么实际当中用到这个随机种子的时候它还是固定的,所以称这个由随机种子为参量的随机为”伪随机“。
综上所述我们就可以得出结论:随机数是由随机种子根据一定的计算方法计算出来的数值。所以,只要计算方法一定,随机种子一定,那么产生的随机数就不会变。 这个结论可以根据固定随机种子显示随机数的方法得到验证。
下面给出zhuzhu写的一个固定随机种子产生随机数的函数
[jass]
globals
         integer seed=224//这是固定了的随机种子数值,对于32位数字,这已经够大了~!
endglobals
//下面是和标准WE一样的线性同余算法(目前主流伪随机算法)
function GetRandomInt takes integer bot,integer top returns integer
         set seed=(seed*1103515245)+12345
         set seed=seed/65536
         set seed=seed-seed/(top-bot+1)+bot
         return seed
endfunction
[/jass]
那么我们实际中用到的是什么呢?不是随机种子也不是上面的算法,而是这个伪随机产生的随机数序列。这个数列的大小和我们在触发里设置的随机数最小值和最大值有关。
现在忘掉上面的理论,我们来说些实际点的东西。


二.运用
首先我们要明确一个概念,随机就像现实生活中的偶然事件,突发事件,应该是不可预知的,而计算机是无法做出偶然事件的。我们这里讲的随机数实际上是由周期性函数得出的,只是把周期性函数的系数调整后,得出的周期非常大,模拟得出偶然结果。所以我们讨论的重点应该放在怎样得出更像随机结果的相对必然结果上。

1.trigger中随机数运用
[trigger]
随机数
事件
       时间 - 每 1.00 秒触发事件
条件
动作
       设置 N = (随机整数,最小值:1 最大值:10)
[/trigger]
这样的触发对随机要求一般的朋友已经可以满足了。理论上这个触发里1—10之间每个数出现的概率为10%,可能是由于数序比较小的原因,我们实际游戏当中会发现个别数字出现的几率貌似高一些,有一种分布不均的感觉。

2.随机数取模
[trigger]
随机数取模
事件
       时间 - 每 1.00 秒触发事件
条件
动作
       设置 N = ((随机整数,最小值:1 最大值:100)mod 10)
[/trigger]
取得随机数后取模,一定程度上能够解决随机数分布不均的情况。
我们先讲解一下mod,mod称为模运算,其实就是数学中常用的取余运算。下面给大家回顾一下小学数学知识,我们用例子来说明。
10%3=3......1                                 10=3×3+1
8%4=2........0       转换为逆运算      8=4×2+0
15%4=3......3                                  15=4×3+3
实际上取模和取余的运算时一样的,于是我们给出取模运算的定义:x对y取模等于 x 减去 y 乘上 x与y的商的下界,公式为 x mod y=x-y×(x/y) 。
注意事项:
1.在取模操作中,左操作数应该大于右操作数,否则取模结果为左操作数。
2.在取模操作中,余数的正负符号完全取决于左操作数,和左操作数的正负号一致。
3.小数取余,用左边的操作数连续减去右边的操作数,直到结果小于右边的操作数,此结果为余。即对商截去小数位后的运算。

3.多次使用随机数
实际应用中,往往需要一些特殊的随机数,我们可以多次使用随机数来得出最终的随机数。
方法有很多种,有利有弊,大家看一下做到心中有数,合适自己的才是最好的。

例1:
[trigger]
随机数取随机数
事件
       时间 - 每 1.00 秒触发事件
条件
动作
       设置 X = (随机整数,最小值:1 最大值:10)
       设置 Y = (随机整数,最小值:90 最大值:100)
       设置 N = (随机整数,最小值:X 最大值:Y)
[/trigger]
这里的随机有明显的分布不均,1~10与90~100之间数字出现的概率相对较低,11~89之间的数字出现概率相对高。
不过用来做攻击力倒很合适,1~10为失误,90~100为暴击,11~89为正常攻击力范围。

例2:
[trigger]
条件判断取随机数
事件
       时间 - 每 1.00 秒触发事件
条件
动作
       设置 X = (英雄 的力量值(不包括 加成))
       如果多有条件成立则做动作1,否则做动作2
             If - 条件
                  X 大于或等于 20
             Then - 动作
                  设置 N= (随机整数,最小值:5 最大值:10)
             Else - 动作
                  设置 N= (随机整数,最小值:1 最大值:5)
[/trigger]
这个是把英雄的属性改为幸运值的一种做法,根据不断改变的英雄属性使得幸运点数在稳步提升后依然随机。这里用的条件判断有很大的发展空间,可以使用AND或OR把多个判断条件联系在一起。

例3:
[trigger]
随机数做概率
事件1
       地图初始化
条件
动作
       设置 wupinp[0]=猪头
       设置 wupinp[1]=猪头
       设置 wupinp[2]=猪头
       设置 wupinp[3]=猪头
       设置 wupinp[4]=猪头
       --------这里的wupin[]变量为物品类型数组--------
[/trigger]
[trigger]
随机数做概率
  事件2
        单位 - 任意单位  死亡
  条件
        ((死亡单位)的类型) 等于  猪
        (随机整数,最小值:1 最大值:100)小于或等于 5
  动作
        设置 N =(随机整数,最小值:0 最大值:4)
        --------上面的最小最大值对应物品类型数组索引的最小最大值--------
        物品 - 创建 wupin[N] 在((死亡单位)的位置)
[/trigger]
这是很经典用随机数做杀怪掉宝概率的例子。这里指定了死亡单位的类型,要想做全局的,只要把这句条件删了就可以了。百分率的具体数值只要改变小于或等于后的数值。


嗯嗯。。。应该有些收获吧!全文到这里就结束了!

评分

参与人数 1威望 +63 收起 理由
kook + 63 原创

查看全部评分

发表于 2008-8-6 15:09:06 | 显示全部楼层

小瞳瞳写教程口牙
支持下

不过为啥是猪头
回复

使用道具 举报

发表于 2008-8-6 17:34:29 | 显示全部楼层
没收获啊 都仔细看了一篇
帮我解释下zhuzhu的那段函数啊 当初他发的时候我就看不懂啦
回复

使用道具 举报

发表于 2008-8-6 18:57:09 | 显示全部楼层
GetRandomInt(a,b)
在we内部的随机算法很可能就是
先 获取一个很大的随机数N, 然后返回 N%(b-a+1)+a

所以GetRandomInt(0,99) mod 10 和GetRandomInt(0,9)结果就是一样的
回复

使用道具 举报

发表于 2008-8-6 19:42:03 | 显示全部楼层
zhuzhu那个线性同余貌似以前小学期的计算机上机实验还做过。。
那个生成函数的主要特征是在任选范围内的一个初始种子后,随机序列以不重复的65535次遍历循环后,回到初始种子。还有那啥随机数的连续上升也是一定,当时记得还有计算协方差矩阵啥的,反正也是固定的。
这么说来魔兽用到的随机算法可能也是这种嘛,只不过是32位的0~2^32
[codes=jass]call SetRandomSeed(123)
call debugmsg(I2S(GetRandomInt(0,x)))[/codes]
试试x取10^i次方,在10^i在2^32以内时如何?

说道做随机数并有正态分布规则的话(俗称的中间大两头小),最简单的莫过直接相加了,根据大叔(误)原理,相叠个数越多约接近正态分布
取0~100的随机数的话,可以用10个0~10的随机数相加这样。

至于需要有设定好的方差的话,我记得有一篇正态随机函数的,找找看http://www.islga.org/bbs/read.php?tid=3077
这个。。看不懂http://bbs.game.mop.com/viewthread.php?tid=343218
回复

使用道具 举报

发表于 2008-8-7 02:09:42 | 显示全部楼层
[codes=jass]
globals
                 integer seed=224//这是固定了的随机种子数值,对于32位数字,这已经够大了~!
endglobals
//下面是和标准WE一样的线性同余算法(目前主流伪随机算法)
function GetRandomInt takes integer bot,integer top returns integer
                 set seed=(seed*1103515245)+12345
                 set seed=seed/65536
                 set seed=seed-seed/(top-bot+1)+bot
                 return seed
endfunction
[/codes]

这个我想是LZ抄错了吧, 首先这个函数的返回结果不是bot到top的随机数,其次seed不应该和top,bot值有关, 不然,其他人可以利用有限的几个bot和top值,就可以达到控制随机数的目的





[codes=jass]
globals
                 integer seed=224//这是固定了的随机种子数值,对于32位数字,这已经够大了~!
endglobals
//下面是和标准WE一样的线性同余算法(目前主流伪随机算法)
function GetRandomInt takes integer bot,integer top returns integer
                 set seed=(seed*1103515245)+12345
                 set seed=seed/65536
                 return seed-seed/(top-bot+1)*(top-bot+1)+bot
endfunction
[/codes]
回复

使用道具 举报

发表于 2008-8-7 08:56:06 | 显示全部楼层
看了
call SetRandomSeed(123)
call debugmsg(I2S(GetRandomInt(0,x)))
以后我就懂了-_-本来还在想那个GetRandomInt的结果都不是定值
我们小学没计算机课让我们上啊-_-目前上的计算机课也没教过这个呀
回复

使用道具 举报

发表于 2008-8-11 10:18:03 | 显示全部楼层
[trigger]
C I00
    事件
        单位 - 任意单位 死亡
    条件
        ((触发单位) 的类型) 等于 (一个等级 -1  的随机中立生物类型)
    动作
            物品 - 创建 (等级 -1 的随机物品类型) 在 ((触发单位) 的位置)
        

[/trigger]
回复

使用道具 举报

发表于 2008-8-12 01:18:03 | 显示全部楼层
收获大大地
有收获就要顶一哈
回复

使用道具 举报

发表于 2008-8-12 20:04:37 | 显示全部楼层
猪头。。。
回复

使用道具 举报

恶声恶气 该用户已被删除
发表于 2008-8-13 01:43:41 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

发表于 2008-8-13 09:47:57 | 显示全部楼层
小红。。。
回复

使用道具 举报

发表于 2008-8-21 03:21:07 | 显示全部楼层
研究下` 记得以前貌似看过类似的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-11-23 17:40 , Processed in 0.106783 second(s), 23 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表