c语言写随机出现一个圆,如何生成一个随机的圆形

最近在工作中遇到这么一个问题:

在游戏场景中有一个怪物生成点,这个生长点产生的怪物均匀分布在半径为R的圆形内,这个随机算法应该如何生成?看起来很简单,随手写了一个:

#defineRAND((float)rand()/RAND_MAX)voidget_random_pos(floatcenter_x,floatcenter_y,floatradius,float&x,float&y){floatu=RAND*radius;floatv=RAND*2*PI;x=center_x+u*cos(v);y=center_y+u*sin(v);}

但写的过程中,直觉告诉我,这么写肯定是有问题的,试想,如果以北京为例,如果所有居住在北京的人都报出自己家和天安门的距离,那么这些数据肯定不是均匀分布的,因为居住在五环附近的人数肯定要大于居住在二环附近的人数,于是用Mathamatica实验一下:

086881f1c4c74d7fbbd0b03adc46f278.gif

果然,这么写是不对的,网上查了一下,这个问题还真是有人研究过,说应该把所获得的随机数开平方一下,实验一下:

14eed60e00169542166270b49053c161.gif

但是,这个开平方背后的数学原理究竟是什么呢?抽空翻了下概率书,原来,其中的道理并不复杂,这里涉及到概率里的一个基本概念,累计分布函数(Cumulative distribution function),简称CFD,它的定义如下:

设有一个随机变量\(X\),它的取值范围是从负无穷到正无穷,如果把它的值小于\(x\)的概率表达为一个函数\(F(x)\),那么这个函数就称为\(X\)的累计分布函数

\begin{equation}

F(x)=P(X\leq x)

\end{equation}

以最为常见的均匀分布概率为例,设均匀分布的随机变量\(X\)的取值范围是\([a,b]\),那么它的累计分布函数以及函数图像是

\begin{equation}

F(x)=\begin{cases}

0 & {x < a} \\

\frac{x-a}{b-a} & {a\leq x < b}\\

1 & {b\leq x}

\end{cases}

\end{equation}

6f4698f3430f74bd141ab74260b4a0c5.gif

对于一个累计分布函数,符合以下规律

\(\begin{equation} 0\le F(x)\le 1 \end{equation}\)

\(F(x)\)单调递增

\(\begin{equation} \lim\limits_{x \to -\infty}{ F(x)=0} , \lim\limits_{x \to +\infty}{ F(x)=1} , \end{equation}\)

回到我们的问题中,假设怪物产生的范围的半径为\(R\),随机产生一只怪物时,它和中心的距离是一个随机变量\(X\),显然,对于怪物均匀分布的情况,\(X\)落在半径为\(x\)的圆内的概率,等于半径为\(x\)小圆和半径为\(X\)的大圆的面积之比

2b09d602ccb9a27855ee16fd6dc73fc3.png

也就是说

\begin{equation}

F(x)=P(X\leq x)=x^2/R^2

\end{equation}

现在我们手头上只有均匀概率的随机数产生器,要想产生这么个随机数需要用到一个很巧妙的运算,就是反函数。设随机变量\(u\)是一个均匀分布在[0,1]之间的随机数,另一个随机变量\(X=F^{-1}(u)\),现在我们需要证明\(X\)的累计分布函数是\(F(x)\)

证明如下

\begin{equation}\begin{split}

P(X\le x) & = P(F^{-1}(u)\le x) \\

& = P(u\le F(x)) \\

& = F(x)

\end{split}\end{equation}

初看起来有点复杂,其实在下面的图上可以很直观的理解这个过程:

792d7a940ea210ba1c94e5a113d83980.png

这是利用了\(F(x)\)是单调递增函数的特性,在我们的问题中,\(F(x)\)的反函数可以表达为

\begin{equation}F^{-1}(u)=R\sqrt{u}\end{equation}

所以最终的算法可以写成

#defineRAND((float)rand()/RAND_MAX)voidget_random_pos(floatcenter_x,floatcenter_y,floatradius,float&x,float&y){floatu=sqrt(RAND)*radius;floatv=RAND*2*PI;x=center_x+u*cos(v);y=center_y+u*sin(v);}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值