JavaScript - 请你说一说对随机数的理解

难度级别:初级及以上                                 提问概率:40% 


在前端开发中,随机数的应用场景非常多,而且也是一个常见的考点。例如网页登录的验证码,看似只有4个随机数字加字母的组合,其实这也是随机数的范畴;例如在抽奖算法中,可以用随机数确定用户中奖的概率;常见的游戏开发中,可以利用随机数在一定范围内,造成玩家砍一刀的伤害值,从而增强游戏的趣味性;例如一些网站在上线之初,用户量不大,可以累加随机数产生一些模拟访问数据,使数据看上去略显真实等等。这一章我们将通过一些场景,深入理解随机数在前端开发中的使用。

1 解决get请求被缓存的问题

get请求通常用于获取静态资源,如Javascript脚本、CSS脚本、图片等,并且这些资源改动并不像获取数据接口那样频繁。因此,浏览器和代理服务器会自动缓存这些资源,以便在将来的请求中重用它们,从而提高网站的性能和响应时间。

当浏览器发出GET请求时,它会检查本地缓存以查找相应的资源。如果资源已经存在于缓存中,则浏览器将直接从缓存中获取资源,而不必向服务器发出新的请求。这可以减少网络流量和服务器负载,提高网站的性能和响应时间。

这就造成了我们新开发的Javascript静态资源升级后,用户很长时间获取不到新资源,导致不能使用新的功能,或是旧的问题无法及时得到解决。此时想到的办法就是为静态资源的url附加随机数,例如http://www.test.com/a.js?v=new Date().getTime()。但这种使用方式有明显的弊端,用户每次刷新页面,就会生成新的时间戳,从而导致失去了浏览器缓存的意义。目前比较常用的改良方式是webpack打包生成hash值,当对应的项目文件修改后,才会生成新的hash静态资源,没有修改的文件则不生成新的静态资源。这种方案既解决了get请求被缓存的问题,又是合理利用浏览器缓存的典型案例。

2 随机抽奖问题

例如有这样一个随机抽奖活动,中一等奖的概率是万分之一,而且为了表明活动的真实性,必须要有中奖者。

在本案例中,首先可以用Math.random()来生成随机数,因为Math.random()生成的是从0到1的随机小数,可以将生成的随机小数乘以10000,并且去掉多余的小数位,如果最终得到的数值是9999,则此用户中奖。代码如下

Javascript代码:
<script>
let num = (Math.random() * 10000).toFixed(0);
if (num == 9999) {
console.log('您已中一等奖');
} else {
console.log('谢谢参与');
}
</script>

这段代码看似没有问题,实则隐患很大。Math.random()方法返回一个0到1之间的伪随机数,这个数的生成是基于算法的,不是真正意义上的随机数,所以一旦调用次数达到一定量级后,是非常有可能会重复的。而在本案例中,要求中奖概率是万分之一,那么一旦出现重复的随机数就会造成多名用户中奖的情况;而既然是随机数,也会有出现次数为0的情况,那么就会造成无中奖用户的情况,使抽奖活动变得没有意义。

为解决这两种可能出现的隐患情况,可以从用户量上下手。例如将抽奖用户以万名分堆,采用Math.random()随机数算法,当出现一等奖用户后,其他用户即便抽中一等奖也不能算作中奖;而如果前9999名用户都抽中一等奖,则直接将第一万名用户视为中奖。

3 砍一刀随机伤害值

在对战游戏中,我们往往看见游戏中的人物砍出一刀所造成的伤害值并不是永恒不变的,而是明显带有随机值效果。当然,这个随机值并不是说第一刀造成1点伤害值,第二刀突然又造成9999点的伤害值这样的随机。而是根据人物当前的攻击值和对方的防御值计算出,当前人物理想状态下砍一刀可以造成多少伤害。例如当前理想状态下伤害值应该是500,为了增强游戏的趣味性,可以在每次砍出一刀时,做出480到520范围内的随机伤害值,同时会有百分之一的概率打出“miss”(就是没打中)效果。代码如下

Javascript代码:
<script>
let harmNum = 500;
function harm(num) {
if (Math.floor(Math.random() * 100) === 0) {
console.log('未打中');
return 'miss';
}
let baseVal = num - 20;
let lastVal = baseVal + Math.floor(Math.random() * 40);
console.log(lastVal);
return `造成伤害值${lastVal}`;
}
harm(harmNum);
</script>

4 生成随机坐标

例如在模拟下雨动画中,雨滴从空中出现,倾斜降落到地面。这个时候在空中出现的坐标就不能是同一个,为了模拟真实的场景,需要结合屏幕宽高和Math.random()随机数算法生成初始化坐标。利用window.innerWidth 和 window.innerHeight 属性分别获取当前浏览器窗口的宽度和高度。然后使用 Math.random()方法生成0到当前窗口宽度和高度之间的随机整数作为坐标的 x 和 y 值,最终将坐标值结合CSS属性,将雨滴初始化定位到屏幕中。获取随机坐标值代码如下

Javascript代码:
<script>
// 生成0到当前窗口宽度之间的随机整数
const x = Math.floor(Math.random() * window.innerWidth);
// 生成0到当前窗口高度之间的随机整数 
const y = Math.floor(Math.random() * window.innerHeight);
</script>

刷题思考

    这道题属于知识归纳类的考点题目,这也是很多面试官很喜欢的一种出题方式,这种题说简单也简单,因为随机数在日常工作中随处可见,但如果对于工作经验较少,想要依靠刷题来面试的初级开发人员,就比较难了。所以我们在刷题的时候,也要养成知识聚合归纳的习惯,同时这也是培养自己前端知识体系的一种好办法。


类似考点

    这道题主要是以随机数为切入点展开的,那么面试官很可能还会问这些问题,例如请你说一说如何生成不会重复的8位随机数?例如让你实现一个大转盘抽奖的游戏,你该如何做到每次转动结束的结果指向不同的位置?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

经海路大白狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值