第四课:循环,让电脑重复做事
预计时长:60~90 分钟 本课关键词:重复、计数、直到......为止
一、课程目标
学完这节课,你能够:
- 说出循环是什么,以及为什么需要它
- 用
for循环让电脑按次数重复做事,比如 3 行代码打印 1~100 - 用
while循环让电脑一直做,直到满足条件才停 - 用
break让循环提前结束 - 用
Math.random()让电脑随机出一个数字 - 完成小项目:升级版猜数字游戏。电脑随机出题,你可以一直猜到对为止,最后统计猜了几次
本课时间安排(参考)
| 环节 | 时间 |
|---|---|
| 复习上课 | 10 分钟 |
| for 循环 | 20 分钟 |
| while 循环 + break | 15 分钟 |
| 随机数 | 10 分钟 |
| 小项目:猜数字升级版 | 20 分钟 |
| 常见错误 + 总结 | 10 分钟 |
二、复习上课
先做 4 道小题,不用写代码,心里想答案就行。
第 1 题:下面代码弹出什么?
js
let money = prompt("你有多少钱?"); // 输入 5000
alert(money + 1000);
点击看答案
弹出 50001000。因为 prompt 得到的永远是文字 ,文字 + 数字 = 拼接。 正确写法:let money = Number(prompt("你有多少钱?"));
第 2 题 := 和 === 有什么区别?
点击看答案
= 是放 ,把东西放进盒子。=== 是问 ,问两边是否相等,得到 true 或 false。
第 3 题:下面代码,输入 95 分会显示什么?
js
let score = 95;
if (score >= 60) {
console.log("及格");
} else if (score >= 90) {
console.log("优秀");
}
点击看答案
显示 及格。if 是从上往下 判断的,第一个条件满足就不再往下看了。正确做法是把 >= 90 写在前面。
第 4 题:上节课的猜数字游戏有什么不好玩的地方?
点击看答案
- 答案永远是 7,玩一次就知道了
- 只能猜一次,猜错就结束了
这两个问题,今天全部解决。
三、新知识
准备工作
- 在你的学习文件夹里新建文件
lesson4.html - 输入
!再按Tab,生成网页模板 - 在
<body></body>里写上<script></script>,今天的代码都写在<script>里面 - 右键 → Open with Live Server 打开网页,再按
F12打开 Console
第 1 部分:为什么需要循环?
生活比喻:罚抄 100 遍
小时候老师罚你抄"我以后上课不说话"100 遍。如果让电脑来抄,按我们之前学的知识,只能这么写:
js
console.log("我以后上课不说话");
console.log("我以后上课不说话");
console.log("我以后上课不说话");
// ......还要再写 97 行
这太蠢了。如果要抄 1 万遍呢?
循环就是告诉电脑:
"这件事,你给我重复做 100 遍。"
电脑最不怕的就是重复。做 1 万遍它也不累、不抱怨、不出错。
第 2 部分:for 循环,按次数重复
生活比喻:跑操场
体育老师说"跑 10 圈"。你脑子里会这样想:
- 从第 1 圈开始
- 还没跑到第 10 圈吗? 没到就继续跑
- 跑完一圈,圈数加 1
for 循环就是把这三件事写在一行里。
最简单的例子:打印 1 到 100
js
for (let i = 1; i <= 100; i++) {
console.log(i);
}
保存,刷新,看 Console:1、2、3......一直到 100,全都出来了。3 行代码,干了 100 行的活。
拆开看:小括号里的三部分
css
for ( let i = 1 ; i <= 100 ; i++ ) {
①起点 ②条件 ③每次怎么变
要重复做的事
}
| 部分 | 代码 | 意思 | 跑操场比喻 |
|---|---|---|---|
| ① 起点 | let i = 1 |
准备一个计数盒子 i,放进 1 |
从第 1 圈开始 |
| ② 条件 | i <= 100 |
每次开始前问一下:还满足吗? | 还没跑满吗? |
| ③ 变化 | i++ |
每做完一次,i 加 1 |
跑完一圈,记一圈 |
| 大括号里 | console.log(i) |
真正要重复做的事 | 跑一圈 |
注意 :小括号里的三部分用的是分号
;,不是逗号!
i++ 是什么?
i++ 是一个简写,意思就是:
js
i = i + 1; // 把 i 里的数取出来,加 1,再放回 i
程序员太懒,觉得 i = i + 1 太长,就发明了 i++。两种写法效果一样。
为什么叫
i?这是程序员的习惯,来自英文 index(编号)。你叫它count、quan都可以,但大家都写i,你看别人代码时会经常见到。
电脑是怎么一步步执行的?
我们把 100 改成 3,看得更清楚:
js
for (let i = 1; i <= 3; i++) {
console.log("第" + i + "圈");
}
| 步骤 | i 的值 | 问:i <= 3 ? | 做什么 |
|---|---|---|---|
| 1 | 1 | true ✅ | 打印"第1圈",然后 i 变成 2 |
| 2 | 2 | true ✅ | 打印"第2圈",然后 i 变成 3 |
| 3 | 3 | true ✅ | 打印"第3圈",然后 i 变成 4 |
| 4 | 4 | false ❌ | 停! 离开循环 |
关键理解 :条件为
true就继续,为false就停下。这和上节课学的if一样,都是靠布尔值做决定。
动手改一改
试着修改代码,观察结果。
① 罚抄 100 遍
js
for (let i = 1; i <= 100; i++) {
console.log("第" + i + "遍:我以后上课不说话");
}
② 倒着数:火箭发射
js
for (let i = 10; i >= 1; i--) {
console.log(i);
}
console.log("发射!🚀");
- 起点改成 10
- 条件改成
i >= 1(还没数到 1 以下就继续) i--就是i = i - 1,每次减 1
③ 只打印偶数:每次跳 2 步
js
for (let i = 2; i <= 20; i = i + 2) {
console.log(i);
}
结果是 2、4、6......20。i = i + 2 让每次加 2,就像上楼梯一步跨两级。
循环里放 if:挑出想要的
循环和条件判断可以组合使用。比如打印 1~30 里所有 3 的倍数:
js
for (let i = 1; i <= 30; i++) {
if (i % 3 === 0) {
console.log(i + " 是3的倍数");
}
}
复习:
%是"求余数"。i % 3 === 0的意思是"i 除以 3 没有余数",也就是能被 3 整除。
经典例子:1 加到 100 等于多少?
传说数学家高斯小时候,老师让全班算 1+2+3+...+100,他很快就算出来了。现在我们让电脑算:
js
let sum = 0; // 准备一个空存钱罐,里面是 0
for (let i = 1; i <= 100; i++) {
sum = sum + i; // 每次把 i 扔进存钱罐
}
console.log("1加到100等于:" + sum);
结果:5050
存钱罐比喻:
| 第几次 | 扔进去 | 罐里一共 |
|---|---|---|
| 开始 | --- | 0 |
| 1 | 1 | 1 |
| 2 | 2 | 3 |
| 3 | 3 | 6 |
| ... | ... | ... |
| 100 | 100 | 5050 |
重要 :
let sum = 0必须写在循环外面、前面。如果写在循环里面,每圈都会把存钱罐清空。这是新手最常犯的错误之一。
第 3 部分:while 循环,直到......为止
生活比喻:吃饭
你吃饭的时候不会想"我要吃 23 口",而是:
只要还没饱,就继续吃。
你事先不知道要重复几次 ,只知道什么时候停。这种情况就用 while。
语法
js
while (条件) {
要重复做的事
}
意思是:只要 条件是 true,就一直重复做大括号里的事。
while是英文"当......的时候"。读起来就像:"当 条件成立 的时候,一直做......"
例子:存钱买手机
一部手机 3000 元,你每个月能存 450 元,几个月能买到?
js
let money = 0; // 现在有 0 元
let month = 0; // 已经过了 0 个月
while (money < 3000) {
month = month + 1;
money = money + 450;
console.log("第" + month + "个月,存了" + money + "元");
}
console.log("一共需要 " + month + " 个月!");
结果:
第1个月,存了450元
第2个月,存了900元
......
第7个月,存了3150元
一共需要 7 个月!
我们没有告诉电脑"重复 7 次",它自己算出来了。这就是 while 的本事。
⚠️ 重要警告:死循环
如果条件永远是 true ,循环就永远不会停,这叫"死循环"。
js
// ❌ 千万别运行这段代码!
let money = 0;
while (money < 3000) {
console.log("还在存钱......");
// 忘了写 money = money + 450
}
money 永远是 0,0 < 3000 永远是 true,电脑会一直执行下去,网页卡死。
如果不小心死循环了怎么办?
- 不要慌,电脑不会坏
- 直接关掉这个浏览器标签页(如果关不掉,用任务管理器结束浏览器)
- 回到 VS Code 修改代码,保存后重新打开
防死循环口诀 :写
while时先问自己,大括号里有没有让条件慢慢变成 false 的代码?
for 和 while 怎么选?
| 情况 | 用什么 | 例子 |
|---|---|---|
| 知道要重复几次 | for |
打印 1~100、罚抄 100 遍 |
| 不知道几次,只知道何时停 | while |
存钱到够为止、猜数字到猜对为止 |
其实两者能互相替代,但选对了,代码更好读。
第 4 部分:break,提前下车
生活比喻:坐公交车
公交车本来要开到终点站,但你在半路按了下车铃,就提前下车了。
break 就是循环里的下车铃。一执行到它,立刻跳出循环,后面的圈都不跑了。
js
for (let i = 1; i <= 100; i++) {
console.log(i);
if (i === 5) {
console.log("够了,不数了!");
break;
}
}
console.log("循环结束了");
结果只打印 1~5,然后就停了。
实用例子:让用户输入密码,取消就退出
js
while (true) {
let pwd = prompt("请输入密码(点取消退出):");
if (pwd === null) {
alert("你取消了");
break;
}
if (pwd === "123456") {
alert("密码正确,欢迎!");
break;
} else {
alert("密码错误,再试一次");
}
}
两个新知识点:
while (true):条件直接写true,意思是"永远转下去",必须靠break出来。这不算错误的死循环,因为我们安排了出口。null:在prompt弹窗里点 "取消" ,得到的不是文字,而是一个特殊的值null,意思是"什么都没有"。我们可以用pwd === null判断用户是不是点了取消。
第 5 部分:让电脑随机出数字
要做真正的猜数字游戏,答案不能固定为 7,得让电脑随机想一个数。
Math.random():电脑掷骰子
在 Console 里多运行几次:
js
console.log(Math.random());
每次结果都不一样,比如:
0.7364829174
0.0918273645
0.5531029384
它给出一个 0 到 1 之间的随机小数(可能是 0,但永远不会到 1)。
Math是 JavaScript 自带的"数学工具箱",random是英文"随机"。注意M要大写。
把小数变成 1~100 的整数
小数没法拿来猜,我们分三步加工:
js
let answer = Math.floor(Math.random() * 100) + 1;
拆开看:
| 步骤 | 代码 | 结果范围 | 举例 |
|---|---|---|---|
| ① 随机小数 | Math.random() |
0 ~ 0.999... | 0.4736 |
| ② 放大 100 倍 | Math.random() * 100 |
0 ~ 99.999... | 47.36 |
| ③ 去掉小数部分 | Math.floor(...) |
0 ~ 99 | 47 |
| ④ 加 1 | ... + 1 |
1 ~ 100 | 48 |
Math.floor是"向下取整",直接把小数点后面砍掉。floor是英文"地板",可以理解为"往地板方向掉"。 47.99 也会变成 47,不是四舍五入。
万能公式(先记住,会套用就行):
js
// 生成 1 ~ N 的随机整数
Math.floor(Math.random() * N) + 1
- 掷骰子(1~6):
Math.floor(Math.random() * 6) + 1 - 抽奖(1~10):
Math.floor(Math.random() * 10) + 1
动手试:用循环掷 10 次骰子。
js
for (let i = 1; i <= 10; i++) {
let dice = Math.floor(Math.random() * 6) + 1;
console.log("第" + i + "次掷出:" + dice);
}
四、小项目:升级版猜数字游戏 🎯
游戏规则
- 电脑随机想一个 1~100 的数字
- 你来猜,电脑会提示 "大了" 或 "小了"
- 一直猜,直到猜对为止
- 猜对后,告诉你一共猜了几次
- 中途点"取消",可以放弃游戏
第一步:先想清楚流程(用中文写说明书)
记得第一课说的吗?编程 = 给电脑写说明书。 动手写代码前,先用中文把步骤理清楚:
markdown
1. 电脑随机想一个数,放进盒子 answer
2. 准备一个计数盒子 count,从 0 开始
3. 重复做下面的事:
3.1 弹窗让玩家输入
3.2 如果玩家点了取消 → 公布答案,结束
3.3 把输入转换成数字
3.4 次数加 1
3.5 如果猜大了 → 提示"大了"
如果猜小了 → 提示"小了"
如果猜对了 → 恭喜,显示次数,结束
都不是(输入的不是数字)→ 提示"请输入数字"
第二步:翻译成代码
js
// ===== 升级版猜数字游戏 =====
// 1. 电脑随机想一个 1~100 的数
let answer = Math.floor(Math.random() * 100) + 1;
// 2. 计数器
let count = 0;
alert("我想好了一个 1~100 的数字,来猜猜看吧!");
// 3. 一直循环,直到 break
while (true) {
// 3.1 让玩家输入
let input = prompt("请输入你猜的数字(点取消放弃):");
// 3.2 点了取消
if (input === null) {
alert("你放弃了,答案是 " + answer);
break;
}
// 3.3 文字转数字
let guess = Number(input);
// 3.4 次数加 1
count = count + 1;
// 3.5 判断
if (guess > answer) {
alert(guess + " 太大了,往小猜!");
} else if (guess < answer) {
alert(guess + " 太小了,往大猜!");
} else if (guess === answer) {
alert("🎉 恭喜你猜对了!答案就是 " + answer + ",你一共猜了 " + count + " 次!");
break;
} else {
alert("请输入数字哦!");
}
}
console.log("游戏结束");
第三步:讲解几个细节
① 为什么最后要多一个 else?
如果用户输入了"abc",Number("abc") 会得到 NaN(不是数字)。 NaN 很特别,它和任何数比较都是 false:
NaN > 50→ falseNaN < 50→ falseNaN === 50→ false
所以三个条件都不满足,就会走到最后的 else,提示"请输入数字"。
如果不写
else if (guess === answer),而是直接写else当"猜对了",那输入 abc 也会被当成猜对!这是一个很隐蔽的 bug。
② 为什么 let answer = ... 写在循环外面?
如果写在循环里面,每猜一次,答案就换一个 ,永远猜不中。这和前面"存钱罐不能放在循环里"是同一个道理:只需要准备一次的东西,放在循环外面。
③ 为什么用 while (true)?
因为我们不知道玩家要猜几次,有可能 1 次,也有可能 20 次。游戏有两个出口(猜对、取消),都用 break 处理。
第四步:测试你的游戏
开发者都要测试自己的程序,请依次试试:
- 正常猜,能不能提示大了/小了?
- 猜对后,次数对不对?
- 中途点"取消",能不能退出并公布答案?
- 输入
abc,会不会提示"请输入数字"? - 刷新网页再玩一次,答案是不是变了?
偷看答案的小技巧 :测试时可以在
let answer = ...下面加一行console.log("答案是:" + answer);,在 Console 里偷看答案,方便测试。测试完记得删掉。
玩家小技巧 :每次猜中间的数(先猜 50,大了猜 25,小了猜 75......),最多 7 次一定能猜中。你可以试试看。
五、常见错误表
| 错误写法 | 问题 | 正确写法 |
|---|---|---|
for (let i = 1, i <= 10, i++) |
用了逗号 | for (let i = 1; i <= 10; i++) 用分号 |
for (let i = 1; i <= 10; i++) |
中文分号 | 切换英文输入法 |
while 里忘了改变条件 |
死循环,网页卡死 | 确保循环里有让条件变成 false 的代码 |
for (let i = 1; i <= 10; i++); |
小括号后面多了分号,循环体不会被重复 | 小括号后直接跟 { |
let sum = 0 写在循环里面 |
每圈都被清零,结果不对 | 写在循环外面、前面 |
let answer = 随机数 写在循环里面 |
每次答案都变 | 写在循环外面 |
i < 100 想打印到 100 |
只打印到 99(差一个) | i <= 100 |
math.random() |
M 要大写 | Math.random() |
Math.random 忘了括号 |
得不到随机数 | Math.random() |
Math.random() * 100 + 1 没取整 |
得到 48.3729... 这种小数 |
外面套 Math.floor(...) |
忘了 Number(prompt(...)) |
"50" > "6" 按文字比较,结果可能出错 |
先转成数字 |
while (guess = answer) |
用了"放"而不是"问" | while (guess !== answer) |
一个循环里放 alert 并循环 100 次 |
要点 100 次确定 | 循环里多次输出用 console.log |
| 大括号不配对 | 报错 Unexpected end of input |
用缩进对齐,VS Code 点击括号会高亮另一半 |
六、课后练习
🟢 基础题
1. 数数 用 for 循环在 Console 打印 1 到 50。
2. 倒计时 用 for 循环打印 10、9、8......1,最后打印"新年快乐!🎆"。
3. 偶数侦探 打印 1~50 里所有的偶数。要求用两种方法:
- 方法一:每次加 2
- 方法二:每次加 1,配合
if和%筛选
4. 掷骰子 掷 5 次骰子(1~6 的随机数),每次打印"第 X 次:Y 点"。
🟡 进阶题
5. 累加器 用 prompt 让用户输入一个数字 n,计算 1+2+...+n 的和。 (提示:别忘了 Number(),存钱罐放在循环外面)
6. 乘法表 让用户输入一个数字,比如 7,打印:
ini
7 × 1 = 7
7 × 2 = 14
......
7 × 9 = 63
7. 密码锁(最多 3 次) 密码是 "888"。用户最多可以试 3 次:
- 输对了:弹出"开锁成功",结束
- 3 次都错:弹出"密码错误次数过多,已锁定"
(提示:用 for 循环 3 次,输对了用 break。思考一下,怎么知道是"3 次都错完了"?)
8. 存钱计划 用户输入目标金额和每月存款,用 while 算出需要几个月。
🔴 挑战题
9. 限次猜数字 修改今天的猜数字游戏:最多只能猜 7 次 ,7 次没猜中就输了,并公布答案。 (提示:可以在循环里判断 count 是否到了 7)
10. 完整九九乘法表 打印 1×1 到 9×9 的完整乘法表。 (提示:循环里面再套一个循环。想想钟表:时针走 1 格,分针要走一整圈。)
11. 骰子统计员 掷骰子 1000 次,统计掷出 6 的次数一共有多少次。多运行几次,看看结果是不是都在 166 左右?想想为什么。
12. 再来一局 猜数字游戏结束后,用 prompt 或 confirm 问"要再玩一局吗?",如果用户同意,就重新开始(新的随机答案、次数清零)。 (提示:confirm("要再玩吗?") 会弹出带"确定/取消"的窗口,点确定得到 true,点取消得到 false。你可能需要在大循环外面再套一层循环。)
七、本课总结
一张表记住今天的内容
| 知识点 | 写法 | 一句话理解 |
|---|---|---|
| for 循环 | for (let i = 1; i <= 10; i++) { } |
跑操场:起点、条件、每次怎么变 |
i++ / i-- |
i = i + 1 / i = i - 1 |
加 1 / 减 1 的简写 |
| while 循环 | while (条件) { } |
吃饭:只要没饱就继续 |
| 死循环 | 条件永远为 true | 关掉标签页,检查条件有没有变化 |
| break | break; |
按下车铃,立刻跳出循环 |
| null | 点 prompt 的"取消"得到的值 | "什么都没有" |
| 随机整数 | Math.floor(Math.random() * N) + 1 |
1~N 的随机数 |
| 存钱罐模式 | 循环外 let sum = 0,循环内 sum = sum + i |
累加用的固定套路 |
三句话带走
- 知道次数用
for,不知道次数用while。 - 只需准备一次的东西,放在循环外面。
- 写 while 先想好:它什么时候停?
你已经掌握的编程三大基本功
到今天为止,你已经学会了编程里最核心的三种结构:
arduino
顺序:从上往下一行行执行(第 1~2 课)
分支:根据条件选一条路走(第 3 课 if)
循环:重复做一件事(第 4 课 for / while)
世界上所有的程序,不管多复杂,都是由这三种结构组合起来的。 从这节课开始,你已经能写出真正"会玩"的小游戏了。