Repository navigation
While and Do While
for 循环适合"已知循环次数"的场景:遍历列表、跑固定次数。当循环次数不确定——比如"一直等到某个条件成立"——就轮到 while 出场了。
for fits "known iteration count" cases: iterating lists, running N times. When the count is unknown — "keep going until some condition holds" — while takes over.
例子:
Example:
while (hp < 20) {
hp += 5;
runcmd("CONSOLE", "say 当前血量 " + hp);
}
只要 hp < 20 成立就一直执行,直到 hp 涨到 20 或以上。
As long as hp < 20, the body keeps running, until hp reaches 20 or above.
while (条件) {
循环体;
}
条件为真时执行循环体,执行完再检查一次条件。条件为假时直接退出。
The body runs while the condition is true; after each pass the condition is re-checked. False exits.
和 if 一样,花括号可以省略,但同样建议一律加。
Like if, braces are optional but should always be present.
while 也能遍历列表,只是形式不如 for 直观:
while can iterate lists too, though less natural than for:
var players = @a;
int i = 0;
while (i < players.size()) {
var p = players.get(i);
runcmd("CONSOLE", "say 玩家 " + p.name);
i++;
}
索引 i 必须在循环体内部手动递增。忘记这一句,就会陷入死循环。
The index i must be incremented inside the body. Forget it, and you have an infinite loop.
遍历已知长度的列表用 for。while 适合"条件驱动"的场景,比如一直读文件到末尾、一直等到某个状态变化。
Use for to iterate a known-length list. while fits "condition-driven" loops: reading a file until EOF, waiting for a state to change.
do-while 和 while 的区别只有一点:先执行循环体,再检查条件。这意味着循环体至少执行一次。
do-while differs from while in one point: the body runs first, then the condition is checked. The body runs at least once.
int i = 100;
do {
runcmd("CONSOLE", "say " + i);
i++;
} while (i < 5);
尽管 i 已经是 100,条件 i < 5 不成立,循环体仍然执行了一次,输出 100,然后退出。
Even though i is already 100 and i < 5 is false, the body still runs once, prints 100, then exits.
语法上 do-while 的末尾必须带分号:
Syntactically, do-while requires a semicolon at the end:
do {
...
} while (条件); // ← 别忘这个分号
这个分号经常被忘,忘记后报语法错误。
This semicolon is frequently forgotten and produces a syntax error.
判断规则:
Decision rule:
-
循环次数已知 →
for。 -
循环次数未知,条件在循环之前检查 →
while。 -
循环次数未知,至少要执行一次 →
do-while。 -
Known count →
for. -
Unknown count, condition checked before →
while. -
Unknown count, must run at least once →
do-while.
实际脚本中 do-while 用得很少。绝大多数场景 while 就能满足。如果一开始不确定该不该用 do-while,先写 while 试试。
In practice do-while is rare. Most cases are served by while. When unsure, start with while.
while 最容易写成死循环。下面几种情况要特别注意。
while easily becomes an infinite loop. Watch for these.
int i = 0;
while (i < 10) {
runcmd("CONSOLE", "say " + i);
// ✗ 忘记 i++,永远停在 0
}
while (hp < 20) {
hp = 0; // ✗ hp 越来越小,永远不满足退出条件
}
while (true) {
// 需要 break 才能退出
if (someCondition) {
break;
}
}
最后一种在实现"主循环"或"服务端 tick 任务"时是合理的用法,但必须保证有 break 出口,否则脚本永远卡在这里。
The last form is a legitimate pattern for "main loops" or server tick tasks, but a break exit must exist — otherwise the script hangs forever.
while 的一个实用场景是轮询:反复检查某个条件,直到满足。
A practical while use case is polling: check a condition repeatedly until satisfied.
int attempts = 0;
bool ready = false;
while (attempts < 10 && !ready) {
// 模拟检查
ready = $server(tps)$ > 15;
attempts++;
}
if (ready) {
runcmd("CONSOLE", "say 服务器就绪,尝试 " + attempts + " 次");
} else {
runcmd("CONSOLE", "say 超时");
}
条件里的 attempts < 10 是计数器上限,防止无限等待。写轮询时永远要留一个兜底条件。
The attempts < 10 clause caps the wait. In any polling loop, always keep a fallback condition.
有些语言里可以用 sleep 在循环中等待。HimDSL 内置了 sleep(毫秒),但它会阻塞当前线程。在 main 里调用 sleep 会卡住服务器主线程,导致整个服务器卡顿。
Some languages use sleep inside loops. HimDSL has sleep(ms), but it blocks the current thread. Calling it inside main stalls the server main thread, freezing the whole server.
如果确实需要"等待一段时间再继续",正确做法是使用 @BukkitRunnable 的定时任务(在"事件与调度"章节讲解),把逻辑拆成多次执行,而不是在循环里 sleep。
If you truly need "wait then continue", the right tool is a @BukkitRunnable timer (covered in "Events & Scheduling") splitting the logic across ticks, not a sleep in a loop.
小结:在 main 里不要 sleep。如果只是想模拟一下,把毫秒数设成 0 或 1。
Summary: do not sleep inside main. If you only need a placeholder, use 0 or 1 millisecond.
-
while (条件) { ... },条件为真时执行。 -
do { ... } while (条件);,至少执行一次,末尾带分号。 -
已知次数用
for,未知次数用while,至少一次用do-while。 -
死循环常见原因:忘记更新、条件永不满足。
-
轮询要留兜底条件。
-
sleep会阻塞线程,main里不要用。 -
while (condition) { ... }runs while true. -
do { ... } while (condition);runs at least once; trailing semicolon. -
Known count →
for; unknown →while; at least once →do-while. -
Infinite loops: missing updates, never-false conditions.
-
Polling loops need a fallback condition.
-
sleepblocks; avoid it inmain.
下一章 break / continue / return 讲解如何提前退出循环、跳过某次迭代,以及从函数返回值。
Next, break / continue / return covers exiting loops early, skipping iterations, and returning values from functions.
- 首页 / 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