For Loop - HimxhMC/HimDSL GitHub Wiki
for 循环 / For Loop
基本形式 / The Basic Form
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 Are Optional
三部分都可以为空,但分号必须写全:
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.
省略更新部分会怎样 / What Happens Without Update
这一条必须单独讲,因为它和你的直觉不一样。
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.
用 for 遍历列表 / Iterating a List
最常见的用法是遍历一个列表,用索引从 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.
复合赋值与自增 / Compound Assignment and Increment
更新部分通常写 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.
递减循环 / Counting Down
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.
步长不为 1 / Non-Unit Steps
不只是 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
嵌套循环 / Nested Loops
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.
常见错误 / Common Mistakes
错误一:忘记写更新语句
for (int i = 0; i < 10;) { ... } // ✗ 只跑一次
不是死循环,但也得不到想要的结果。解决方法:写 i++。
错误二:条件写成 i <= total
for (int i = 0; i <= total; i++) {
players.get(i); // ✗ 最后一次会越界
}
正确写法是 i < total。
错误三:在条件里改 i
for (int i = 0; i < 10; i = i + 1) { ... } // ✓
for (int i = 0; i++ < 10; ) { ... } // ✗ 罕见且难以维护
条件部分应当只做判断,不做修改。
Mistake 1: Missing the update
Not an infinite loop, but not what you want. Add i++.
Mistake 2: i <= total
Off-by-one; the last iteration goes out of bounds. Use i < total.
Mistake 3: Mutating i inside the condition
The condition should test, not modify.
小结 / Summary
-
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.
下一步 / Next Steps
下一章 [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.