在第 17 关"恐惧之门"中,塔林需要不停地攻击一扇大门直到它被打破。如果没有循环,你要写多少行 hero.attack("Door")?答案是:你根本不知道要写几行,因为你不确定门要被打多少次才会碎!
这就是循环(Loop)出现的原因——当你需要让英雄重复做某件事时,循环就是你的超级武器。
假设没有循环,第 17 关你可能要这样写:
hero.attack("Door") # 第1次 hero.attack("Door") # 第2次 hero.attack("Door") # 第3次 hero.attack("Door") # 第4次 hero.attack("Door") # 第5次……够了吗?不知道! # 也许还需要20次?50次?100次?😱
问题太多了:代码又长又丑、你不确定要写多少次、修改时要改几十处相同的代码……
有了循环,同样的任务只需要两行代码:
while True: hero.attack("Door")
两行代码做到了无限次攻击!门总会碎的——而你不需要关心到底要打几次。
在第 14 关"闹鬼的迷宫"中,安雅需要不断重复"向右走两步、向上走两步"的模式来穿越迷宫。没有循环需要写一大堆重复代码,有了循环只需要 5 行:
while True: hero.moveRight() hero.moveRight() hero.moveUp() hero.moveUp()
编程界有一条著名的原则叫 DRY——Don't Repeat Yourself(不要重复你自己)。如果你发现自己在复制粘贴相同的代码,那就是使用循环的信号。循环就是实现 DRY 原则的最基本工具。
循环(Loop)是程序中的一种控制结构,它能让一段代码重复执行多次(甚至无限次)。你只需写一遍要重复的动作,循环帮你执行千百次。
在学术课程中,循环有一个更正式的名字:迭代(Iteration)。"迭代"的意思就是"反复做"。每执行一遍循环体就叫做"一次迭代"。
AP 计算机科学原理课程将Iteration列为算法三大构建块之一(顺序、选择、迭代)。所有复杂的算法都可以用这三种结构组合而成。
英国 A Level 课程区分两种迭代:确定性迭代(事先知道重复多少次,如 for i in range(10))和不确定性迭代(不知道要重复多少次,靠条件控制)。while True 属于不确定性迭代的极端情况——永远重复!
无限循环就是永远不停的循环——除非外部力量强制中断它。while True: 就是最经典的无限循环。在 CodeCombat 的关卡中,游戏结束(通关或失败)时循环自动停止。
有限循环会在一定次数后停止,比如"重复 10 次"。在后面的学习中你会遇到 for i in range(10): 这样的有限循环,它精确地执行 10 次后停止。
while 循环的逻辑是:"当某个条件为真时,就一直重复。"条件变为假时停止。本单元学习最简单的情况:条件永远为真(True)。
for 循环是另一种循环方式,适合"遍历一个序列"或"重复固定次数"。后续单元会学到。
本单元只学一种循环:while True。它是最简单、最直接的循环——让代码永远重复。掌握了它,后面的有条件循环就是小菜一碟!
while 是 Python 的关键字,意思是"当……的时候"。它告诉 Python:"接下来有一个条件,只要这个条件为真,就重复执行下面的代码。"
while 后面跟着的是一个条件。每次循环开始前,Python 会检查这个条件——如果为真(True),就执行循环体;如果为假(False),就跳过循环。
while True 后面必须跟一个冒号 :。冒号的作用是说"下面是循环体了,开始缩进吧!"忘了冒号会直接报语法错误。
循环体(Loop Body)就是要被重复执行的那些代码——它们被缩进放在 while True: 下面。每次循环都会从头到尾执行一遍循环体中的所有语句。
while True: # ← 关键字 + 条件 + 冒号 hero.moveRight() # ← 循环体(缩进4个空格) hero.moveLeft() # ← 循环体(继续缩进)
True 是 Python 的保留关键字,代表"真"。它不是变量,不能被重新赋值。
你可以把 True 想象成对一个问题回答"是!"。当 while 后面的条件是 True 时,就像问"要继续吗?"答案永远是"是!"——所以永远继续。
布尔类型(Boolean / bool)是最简单的数据类型——只有两个值:True(真/是/开)和 False(假/否/关)。就像灯的开关只有开和关两种状态。
while True: # ✓ 正确:T 大写 while true: # ✗ 错误:t 小写,Python 不认识 while TRUE: # ✗ 错误:全大写也不行
布尔值是所有条件判断的基础。while 后面的条件最终都会被计算为 True 或 False。本单元中我们直接写 True,后续你会学到像 hero.health > 0 这样的条件表达式——它的结果也是布尔值。
while True: 翻译成人话就是:"当 True 为真时,重复执行下面的代码。"那 True 什么时候不为真呢?永远不会!所以这就是一个永远重复的循环。
这就像问"1+1等于2吗?"——答案永远是"是"。所以循环永远不会自己停下来。在 CodeCombat 中,关卡通过或英雄死亡时循环才会被强制终止。
while True: 创建的循环被称为无限循环(Infinite Loop)或永久循环(Forever Loop)。它是循环家族中最"执着"的成员——除非外力介入,否则永不停歇。
无限循环在真实编程中非常常见:游戏的主循环(每帧都在更新画面)、聊天程序(一直等待新消息)、服务器程序(持续监听请求)——都是 while True 的变体。
你正在玩的 CodeCombat 本身就运行着一个无限循环:每一帧更新画面、检测碰撞、处理输入……直到你关闭游戏为止。你写的 while True: 代码正是在这个框架中运行的!
来看第 13 关"焰中舞动"的完整解法:
while True: hero.moveRight() hero.moveLeft()
安雅就像在"跳舞"一样——不断地左右移动来躲避火球。这个舞蹈会一直跳下去直到通关!
while True: # ✓ 有冒号 while True # ✗ 没冒号 → SyntaxError!
循环体中的每一行都必须缩进(通常是 4 个空格)。缩进告诉 Python:"这些代码属于循环内部,要被重复执行。"
来看第 16 关"循环仓库"——循环体有 4 条语句:
while True: hero.moveUp(2) # 循环体第1行 hero.moveRight(2) # 循环体第2行 hero.moveDown() # 循环体第3行 hero.moveLeft() # 循环体第4行
每次循环都会按顺序执行这 4 行,然后回到第 1 行重新开始——形成一个"回"字形的路径模式!
缩进(Indentation)就是代码行前面的空白。在 Python 中,缩进不是为了好看——它是语法的一部分,决定了代码的结构和层次关系。
在 Python 中,缩进告诉解释器"这些代码是一组的,它们属于上面那个结构(如 while 循环)"。不缩进的代码就在循环外面。
这是 Python 和很多其他语言的最大区别:缩进不是可选的美化——它是强制性的语法要求。缩进错了,程序就错了。
在 C、Java、JavaScript 等语言中,代码块用花括号 {} 包围。Python 用缩进替代了花括号——更简洁但也更需要注意格式。
Python 社区约定用 4 个空格表示一级缩进。在 CodeCombat 的编辑器中按 Tab 键会自动插入 4 个空格。
在 CodeCombat 编辑器中,你只需要按一下 Tab 键就能正确缩进。编辑器会自动处理空格的问题。
while True: hero.moveRight() # 4 个空格 ✓ hero.moveUp() # 4 个空格 ✓ (一致!)
while True: hero.moveRight() # 4 个空格 hero.moveUp() # 6 个空格 ✗ 不一致!IndentationError!
当缩进出问题时,Python 会报 IndentationError。看到这个错误时,检查你的缩进是否一致——所有循环体内的代码都应该对齐在同一个位置。
代码块(Code Block)就是一组具有相同缩进层级的语句,它们被视为一个整体。循环体就是一个典型的代码块。
while True: 下面缩进的所有语句共同组成了一个代码块——这就是循环体。它们作为一个整体被重复执行。
冒号 : 标志着"接下来有一个新的代码块",下一行开始缩进就是代码块的开始。
当缩进恢复到上一级别时,代码块就结束了。不过在 while True: 的情况下,由于循环是无限的,循环体后面通常不会再有代码——它会一直循环下去。
代码块可以嵌套——一个循环里面可以有 if 判断,if 里面还可以有另一个循环。每嵌套一层就多缩进 4 个空格。这个概念在后续关卡中会用到。
缩进是 Python 用来区分"循环内"和"循环外"的唯一方式。来看第 18 关"攻破突袭"的代码结构:
# 这些代码不缩进 → 循环外(只执行一次) hero.moveRight() hero.moveUp() hero.attack("Chest") hero.moveDown() while True: # 这些代码缩进 → 循环内(重复执行) hero.moveRight(3) hero.moveDown(3)
只有缩进的代码才会被重复。不缩进的代码只执行一次然后就"过去了"。
在 while True: 之前的代码都是顶格写的(不缩进),它们只执行一次。
while True: hero.moveRight() # ✗ 错误!没缩进 → IndentationError
hero.moveRight() # ✗ 错误!没有 while 就缩进 → IndentationError hero.moveLeft() # ✓ 顶级代码不需要缩进
第 13 关"焰中舞动"是最简单的循环移动:安雅不断左右移动来躲避火球。
while True: hero.moveRight() # 右! hero.moveLeft() # 左!然后再右、再左、再右……
第 15a 关"迷一般的 Kithmaze"需要更复杂的移动组合:
while True: hero.moveRight() hero.moveDown() hero.moveRight(2) hero.moveUp()
当迷宫有重复的结构时(比如每段走廊都是相同形状),用循环来重复这个模式就能自动穿越整个迷宫。第 14、15 关就是这个原理。
第 15b 关"辐射光环"中,安雅需要重复"捡发光石→经过骷髅"的模式:
while True: hero.moveUp() # 走到发光石 hero.moveDown() # 退回来 hero.moveRight(2) # 趁骷髅被吓跑时通过!
当你不知道需要攻击多少次时,用循环"一直攻击"就对了。第 17 关"恐惧之门"就是经典例子:
while True: hero.attack("Door") # 砍!砍!砍!直到门碎为止
这可能是你写过的最短的循环程序——仅仅两行代码就完成了"破门"任务。不管门有多厚、需要砍多少下,循环都会帮你坚持到底。
同样的任务,循环 vs 手动对比:手动写可能需要 20+ 行 attack("Door");用循环只需要 2 行。而且如果门变厚了(需要更多次攻击),循环代码不需要任何修改——它自动适应!
循环体里可以组合不同类型的命令。比如"走一步,砍一下"的巡逻模式。
第 16 关"循环仓库"中,循环体组合了多个移动命令来按"回"字形路线收集宝石。
循环体内的语句仍然按照顺序结构从上到下执行。一轮循环结束后,回到循环体第一行重新开始。就像一首歌唱到结尾后,从头再唱一遍。
有些操作只需要做一次——比如"走到门前面"。走到以后就不需要再走了,接下来要做的是不断攻击门。这类一次性操作就放在 while True: 之前。
第 19 关"橱柜里的骷髅"完美展示了这个模式:
# 循环前:移动到橱柜旁(只做一次) hero.moveUp() hero.moveRight(2) hero.moveDown(2) # 循环内:不断攻击橱柜(重复执行) while True: hero.attack("Cupboard")
先移动到正确的位置,再开始循环操作——这是"初始化 → 循环"模式的经典应用。
在第 18 关"攻破突袭"中,先攻击箱子获取药水(一次性操作),然后才开始循环逃跑。
有时你需要先收集一个道具(比如速度药水),然后再开始循环移动。道具只需要拿一次,所以放在循环前面。
| 位置 | 执行次数 | 适合放什么 | 例子 |
|---|---|---|---|
| 循环前(不缩进) | 1 次 | 一次性操作 | 移动到位、打开箱子 |
| 循环内(缩进) | 无限次 | 需要重复的操作 | 攻击门、巡逻路线 |
问自己:"这个动作需要做几次?"如果答案是"一次"→ 放循环前;如果是"很多次/一直做"→ 放循环里。
这种"先准备、后循环"的结构是编程中极其常见的模式。即使在大型程序中,你也经常能看到:初始化阶段(加载资源、设置参数)→ 主循环(持续运行的核心逻辑)。
设计循环的第一步是发现模式——观察地图,找出哪些动作在反复出现。第 14 关的迷宫就是"右右上上"不断重复。第 15 关是"右右下"不断重复。
找到重复单元后,把它写进循环体就完成了!重复单元 = 循环体。
有些动作不属于重复模式(比如到达起始位置),就放在循环之前。
CodeCombat 中的迷宫关卡都是精心设计的——有明显的重复结构让你用循环来解决。学会"用眼睛找模式"是通关的关键技能。
循环体必须是一个完整的重复周期。如果模式是"右右上上",那循环体就要包含全部四步——不能只放一半。
第 16 关要求使用不超过 5 条语句。使用参数(如 moveUp(2) 代替两次 moveUp())可以精简循环体。
循环体执行完一轮后,英雄的状态应该能让下一轮正确开始。如果第一轮结束时英雄在错误位置,第二轮就会走错路。
写完循环后,在脑中模拟前两轮:第一轮走对了吗?第二轮从上一轮结束位置开始还对吗?两轮都对,后面基本就没问题了。
在 CodeCombat 中,游戏会帮你管理循环的终止。但在传统编程中,一个意外的无限循环会导致程序永远运行下去——必须手动杀掉它。
无限循环会持续占用 CPU 资源。如果你的电脑突然变慢或风扇狂转,可能就是某个程序进入了意外的无限循环。
在终端/命令行中,Ctrl + C 可以强制终止一个正在运行的 Python 程序。这是程序员处理"失控"循环的急救措施。
几乎所有游戏的核心都是一个无限循环:更新画面 → 处理输入 → 计算逻辑 → 再更新画面……
网站服务器需要 24/7 等待用户请求——这也是无限循环。
比如温度监控系统:不断读取温度 → 判断是否超标 → 如果超标就报警。
在实际开发中,while True 通常配合 break 使用——在满足某个条件时跳出循环。这让"无限循环"变成了"当条件满足时退出的循环"。
break 是 Python 的关键字,意思是"立刻终止当前循环"。它让 while True 有了"出口"。
while True: # 做某件事 if 条件满足: break # 退出循环!
当前关卡不需要 break(因为游戏会帮你终止循环),但在后面的关卡中你会学到如何优雅地控制循环的退出。
循环最大的好处:写一遍,用无数遍。不管要重复多少次,代码量不变。
如果你想改变移动方向,只需改循环体里的一行。如果没用循环(复制了 20 遍),你得改 20 个地方——而且很容易漏掉某一处。
第 17 关用循环只需 2 行;没有循环可能需要 30+ 行。代码越短越好维护。
写的代码越少,出错的机会就越少。循环让你把潜在的错误点从 N 处减少到 1 处。
第 15 关要求"使用少于 5 条语句",第 16 关要求"使用不超过 5 条语句"——循环 + 参数是达成这些挑战的关键。
虽然行数不是唯一标准,但更短的代码通常更容易理解和维护。
CodeCombat 的"语句限制"挑战鼓励你用最少的代码完成任务——这正是循环和参数大展身手的时候。
代码要简洁但不能"晦涩难懂"。while True: hero.moveRight(2); hero.moveDown() 比用难以理解的技巧更好——清晰第一!
while True: 语句1 语句2 ...
冒号是 Python 的"代码块开始标志"——while、if、for、def 后面都需要冒号。
4 个空格 = 1 级缩进。循环体内所有语句保持相同缩进。按 Tab 键自动处理。
将来你会学到把 True 替换为其他条件:while hero.health > 0:(当英雄还活着时循环)。
意思是"当……的时候"。开启一个条件循环。
永远为真的值。while True: = 永远循环。首字母必须大写。
与 True 相反。while False: 的循环体永远不会执行(没意义但能理解概念)。
在循环内部使用,立刻终止当前循环。后续关卡学习。
跳过本次循环的剩余部分,直接开始下一轮循环。后续关卡学习。
恭喜你掌握了循环的力量!来看第 18 关"攻破突袭"的完整解法,回顾"初始化 + 循环"的结构:
# === 初始化阶段(循环前,只执行一次) === hero.moveRight() # 走到岔路口 hero.moveUp() # 走到箱子旁 hero.attack("Chest") # 打开箱子获取药水 hero.moveDown() # 回到主走廊 # === 循环阶段(重复执行,持续逃跑) === while True: hero.moveRight(3) # 全速向右冲! hero.moveDown(3) # 全速向下跑!逃离精灵!
| 核心概念 | 关键知识 | 对应关卡 |
|---|---|---|
| 循环的需求 | DRY 原则:不要重复自己 | 第13关 |
| while True: | 创建无限循环的语法 | 第13关 |
| 布尔值 True | 永远为真,首字母大写 | 第13关 |
| 缩进(4空格) | 缩进 = 循环体内部 | 第13关 |
| 循环体 | 被重复执行的代码块 | 全部关卡 |
| 循环内移动 | 重复移动模式穿越迷宫 | 第14/15/15a/15b关 |
| 循环内攻击 | 持续攻击直到目标摧毁 | 第17关 |
| 循环前初始化 | 一次性操作放循环之前 | 第18/19关 |
| 模式识别 | 观察重复模式 → 写入循环体 | 第14/15/16关 |
| 代码简洁 | 循环 + 参数 = 最少语句数 | 第15/16关 |
安雅学会了在火焰中跳舞,塔林掌握了用循环破门的暴力美学。
下一站:第四单元——变量与赋值,让英雄学会"记住"事情!🧠
CodeCombat 编程知识 · 计算机科学入门(暗影地牢):第三单元
CodeCombat教研团队