业务描述
让计算机和我们玩个游戏:随机生成一个 1 到 100 的数字,让用户猜测这个数字是几,用户输入自己的猜
测之后,提示“输入的数字太大了”或“输入的数字太小了”,直到用户准确猜到这个数字。
随机数的生成
JavaScript 中提供了一个生成随机数的函数 Math.random()。它能随机产生一个大于 0 且小于 1 的小数,
即产生的数字的区间为(0,1)。
在 chrome 浏览器的控制台使用 REPL 环境测试这个函数,每次都能得到一个随机数
Math.random()生成的是(0,1)区间的随机小数,圆括号表示“开区间”,即取值不包括 0 也不包括 1。那
么怎么得到[a,b]区间内的随机整数呢?方括号表示“闭区间”,即可以取到包括 a 也包括 b 的值。
欲得到[a,b]区间的随机整数,公式为:
parseInt(Math.random() * (b - a + 1)) + a。
要证明这个公式不难,有兴趣的同学可以思考其中的原理。
我们想得到[3,8]区间内的随机整数,只需要将 a=3,b=8 带入公式即可,即
parseInt(Math.random() * 6) + 3。
使用 REPL 环境测试这个表达式,每次都能得到 3 到 8 之间的随机整数
代码实现
程序要求让用户不断输入数字,直到输入正确为止。即用户输入几次才能够输入正确是不确定的。此时
while(true)死循环就派上了用场。当用户输入正确的数字的时候,使用 break 语句来手动结束循环。
案例程序如下:
//随机生成一个[0,100]区间的数字
var n = parseInt(Math.random() * 101) + 0;
//不断重复输入数字、判断这个流程
while(true){
var a = Number(prompt("请输入数字"));
if(a > n){
alert("你输入的数字太大");
}else if(a < n){
alert("你输入的数字太小");
}else if(a == n){
alert("恭喜你!你猜对了");
break;
}
}
基本使用
do-while 循环是一种“后测试循环语句”。它不同于 for 循环和 while 循环每次都是“先测试条件是否满
足,然后执行循环体”,do-while 循环是“先执行循环体,然后测试条件是否满足”。
do-while 循环的语法为:
do{
循环体
}while(循环执行条件)
do-while 循环将循环执行条件写到了循环体的后面,它总会无条件的执行循环体一次,然后再检测循环执
行条件是否为 true,决定是否继续执行循环体。
这就意味着,即使 do-while 的循环执行条件是 false,它也会执行循环体一次,比如:
do{
//这里会执行一次
}while(false)
举例:生成不都为 0 的两个变量
请编写程序,随机生成两个变量 dx 和 dy,它们均在[-4,4]区间随机取值,要求 dx 和 dy 不能同时为 0。
这个题目在一些小游戏中是常用的算法。比如我们想让“超级马里奥”可以随机选择一个方向行走,此时就
要随机生成水平和竖直两个方向的位移增量 dx 和 dy。依靠 dx、dy 的不同正负、不同方向的情况,“马里奥”
就会有不同的移动方向了。“马里奥”总归是要移动的,它不能停留在原地不移动,所以必须要保证 dx 和 dy
不能同时为 0。
我们可以用 Math.random()的[a,b]区间公式,生成符合条件的随机数。但是总有概率生成的两个数字都
是 0,不符合题目要求。
解决办法就是先随机生成两个数字,然后检查是不是两个数字都是 0,如果是,则“返工重来”,重新生成
两个数字
do-while 语句可以发挥作用,因为 do-while 语句是“后测试循环语句”。如同产品“验收”一样,如果
产品“不合格”则必须进行“返工”。
案例程序如下:
var dx , dy;
do{
dx = parseInt(Math.random() * (4 - -4 + 1)) + -4; // 套用公式,生成[-4,4] 随机数
dy = parseInt(Math.random() * (4 - -4 + 1)) + -4; // 套用公式,生成[-4,4] 随机数
}while(dx == 0 && dy == 0);
console.log(dx , dy);
程序运行之后,将能得到两个[-4,4]区间的随机数,并且两个数字肯定不会都是 0。