Repository navigation
For Loop
for 循环由三部分组成:初始化、条件、更新。
A for loop has three sections: init, condition, update.
for (初始化; 条件; 更新) {
循环体;
}
执行流程:先运行初始化一次;然后检查条件,为真则执行循环体;循环体结束后执行更新;再回到条件检查。如此往复,直到条件为假。
Flow: run init once; check condition; if true, run the body; after the body, run update; back to the condition. Repeat until the condition is false.
for (int i = 0; i < 5; i = i + 1) {
runcmd("CONSOLE", "say 第 " + i + " 次");
}
输出:
Output:
第 0 次
第 1 次
第 2 次
第 3 次
第 4 次
注意 i 从 0 开始,到 4 结束,共 5 次。i < 5 为假时退出,此时 i 是 5。
Note that i starts at 0 and ends at 4, five iterations total. The loop exits when i < 5 is false, at which point i is 5.
三部分都可以为空,但分号必须写全:
All three sections may be empty, but the semicolons must be present:
// 只写条件
int i = 0;
for (; i < 5; i = i + 1) { ... }
// 只写初始化
for (int i = 0; ; i = i + 1) { ... } // 若没有 break 会死循环
// 三部分都省略
for (;;) { ... } // 死循环,需要 break
日常脚本里很少需要省略。除非你在写"无限循环加 break"这种结构,否则三部分都写全是更好的选择。
Omitting sections is rarely needed in everyday scripts. Unless you are writing an "infinite loop with break", writing all three is clearer.
这一条必须单独讲,因为它和你的直觉不一样。
This one deserves its own section because it defies intuition.
省略更新部分的 for 不会死循环,而是只执行一次然后退出。
A for without an update does not loop forever — it runs once and exits.
for (int i = 0; i < 10;) {
runcmd("CONSOLE", "say " + i);
}
// 只输出 "0",然后退出,控制台会打印一条警告
HimDSL 在检测到没有更新语句时会主动打断循环,同时向控制台写一条警告。这是防止初学者写出死循环的安全设计。
HimDSL breaks the loop when it detects no update statement and writes a warning to the console. This is a safety feature against accidental infinite loops.
如果你的逻辑真的需要跳过更新(比如在循环体内部手动更新),请改用 while 循环。while 的用法在下一章。
If your logic truly needs to skip the update (say, updating inside the body), use a while loop instead. That is the next chapter.
最常见的用法是遍历一个列表,用索引从 0 到 size()-1:
The most common pattern: iterate from 0 to size()-1:
var players = @a;
int total = players.size();
for (int i = 0; i < total; i = i + 1) {
var p = players.get(i);
string name = p.name;
runcmd("CONSOLE", "say 玩家 " + name + " 在线");
}
几点值得注意:
A few points:
-
total只取一次,而不是在条件里写i < players.size()。列表长度在循环过程中不会变,提前取值可以省一点开销,也更清楚地表达意图。 -
i < total而不是i <= total - 1,后者容易写错。 -
循环变量
i在循环外不可见。 -
totalis read once instead of writingi < players.size()in the condition. The list length does not change during the loop; pre-reading saves a bit and expresses intent. -
Use
i < total, noti <= total - 1— the latter is easy to get wrong. -
The loop variable
iis not visible after the loop.
更新部分通常写 i = i + 1,也可以写成 i++ 或 i += 1:
The update is usually i = i + 1, but i++ or i += 1 work too:
for (int i = 0; i < 5; i++) { ... }
for (int i = 0; i < 5; i += 1) { ... }
for (int i = 0; i < 5; i = i + 1) { ... }
三者等价。选哪种看个人习惯,同一个脚本里保持一致就好。
All three are equivalent. Pick one style and stay consistent within a script.
i 也可以从大往小:
i can count down as well:
for (int i = 10; i > 0; i--) {
runcmd("CONSOLE", "say 倒计时: " + i);
}
条件 i > 0 保证不会执行到 i == 0。循环结束时 i 是 0。
i > 0 ensures the loop stops before i == 0. After the loop, i is 0.
不只是 i++,可以写任意更新表达式:
The update can be any expression, not only i++:
// 每次 +2,遍历偶数
for (int i = 0; i < 10; i += 2) {
runcmd("CONSOLE", "say " + i);
}
// 0, 2, 4, 6, 8
for 可以嵌套。内层循环变量名不要与外层重名:
for nests. The inner loop variable should not shadow the outer one:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
runcmd("CONSOLE", "say (" + i + ", " + j + ")");
}
}
上例会输出 9 行。如果要跳过内层某次,用 continue;要跳出内层,用 break(下一章)。
The above prints 9 lines. To skip one inner iteration use continue; to exit the inner loop use break (next chapter).
嵌套循环的总次数是外层次数乘以内层次数。三层以上嵌套基本意味着逻辑需要重构,考虑拆成函数。
Total iterations of nested loops = outer × inner. Three or more levels of nesting usually means the logic should be split into functions.
for (int i = 0; i < 10;) { ... } // ✗ 只跑一次
不是死循环,但也得不到想要的结果。解决方法:写 i++。
for (int i = 0; i <= total; i++) {
players.get(i); // ✗ 最后一次会越界
}
正确写法是 i < total。
for (int i = 0; i < 10; i = i + 1) { ... } // ✓
for (int i = 0; i++ < 10; ) { ... } // ✗ 罕见且难以维护
条件部分应当只做判断,不做修改。
Not an infinite loop, but not what you want. Add i++.
Off-by-one; the last iteration goes out of bounds. Use i < total.
The condition should test, not modify.
-
for (init; condition; update)。 -
三部分都可省略,分号必须有。
-
省略更新部分只会执行一次,不会死循环。
-
遍历列表用
i < list.size()模式。 -
更新部分可以写
i++、i += 1、i = i + 1,三者等价。 -
嵌套循环总次数是乘积,超过三层考虑重构。
-
for (init; condition; update). -
All three sections optional; semicolons required.
-
Omitting update runs once, not an infinite loop.
-
Iterate lists with the
i < size()pattern. -
Updates may be
i++,i += 1, ori = i + 1; equivalent. -
Nested total = product; three or more levels suggest refactoring.
下一章 [while 与 do-while / While-and-Do-While] 讲另外两种循环,特别是当循环次数不确定时的用法。
Next, [while 与 do-while / While-and-Do-While] covers the other two loops, especially when the iteration count is not known in advance.
- 首页 / Home
- 安装与快速开始 / Installation & Quick Start
- 第一个脚本 / Your First Script
- 命令速查 / Command Reference
- 自动执行脚本 / Auto-run Scripts
- 定义函数 / Defining Functions
- 函数重载 / Function Overloading
- Lambda 表达式 / Lambda Expressions
- 函数式接口 / Functional Interfaces
- 选择器总览 / Selectors Overview
- 选择器过滤器 / Selector Filters
- EntityRef 引用 / EntityRef
- 占位符参考 / Placeholders Reference
- PlaceholderAPI 桥接 / PAPI Bridge
- 创建 GUI / Creating a GUI
- GUISlot 槽位 / GUISlot
- 点击回调 / Click Callbacks
- onClose 回调 / onClose Callback
- GUI 刷新 / GUI Refresh
- 数学函数 / Math Built-ins
- 高精度计算 / BigDecimal Built-ins
- 字符串函数 / String Built-ins
- 集合函数 / Collection Built-ins
- 文件 I/O / File I/O
- 命令与 sleep / Commands & sleep