CodeCombat 事件与宠物编程

Event Handling & Parallel Actions(70-81关)

第 70 关

快速赛跑 (Fast Race)

战术思路分析:并行行动

正常情况下,代码是**按顺序**执行的(英雄跑完,宠物才开始跑)。但赛跑需要英雄和宠物**同时**出发!

核心:事件处理器 (Event Handler)

我们使用 `pet.on("spawn", petMove)` 来将宠物的移动代码设置为一个**事件处理器**。当宠物一生成("spawn"事件),`petMove` 函数就会被触发,并与英雄的代码**并行**运行。

Hero: Move (Sequential)
Pet: On "Spawn" (Parallel)

Python 程序解法

1
def petMove(event):
定义宠物移动函数
2
pet.moveXY(50, 21)
宠物移动到终点
3
4
# 使用pet.on("spawn", petMove)替换petMove()
5
pet.on("spawn", petMove)
将 petMove 绑定到宠物的 "spawn" 事件
6
hero.moveXY(50, 12)
英雄开始移动(与宠物同时进行)
第 71 关

沙漠蘑菇 (Desert Mushrooms)

战术思路分析:安全收集

蘑菇有毒,英雄必须在安全血量时才能收集。宠物可以帮忙取回药水。

宠物技能:`findNearestByType()`

宠物可以根据类型(字符串)查找最近的单位或物品:
`potion = pet.findNearestByType("potion")`
然后使用 `pet.fetch(potion)` 将药水带回给英雄。

Pet: findNearestByType("potion")

Python 程序解法

1
def onSpawn(event):
宠物生成事件处理器
2
while True:
宠物循环,持续检查药水
3
# 宠物可以根据类型找到最近的物品。
4
potion = pet.findNearestByType("potion")
寻找最近的药水
5
# 如果存在药水则让宠物取回:
6
if potion:
7
pet.fetch(potion)
宠物取回药水
8
9
pet.on("spawn", onSpawn)
绑定事件
10
11
# 蘑菇有毒,不要太快收集。
12
while True:
英雄主循环
13
someItem = hero.findNearestItem()
14
if someItem and hero.health > hero.maxHealth / 3:
只有血量安全 (大于 1/3) 时才收集
15
# 收集someItem:
16
hero.moveXY(someItem.pos.x, someItem.pos.y)
移动收集
第 72 关

蘑菇之声 (Mushroom Minder)

战术思路分析:多目标取回

英雄需要打败骷髅并打开宝箱,宠物负责取回药水和金钥匙。

关键:连续 `pet.fetch()`

宠物可以连续接收多个 `fetch` 命令,它会排队执行:先找药水并取回,再找金钥匙并取回。

Fetch(Potion) → Fetch(Key)

Python 程序解法

1
def onSpawn (event):
宠物生成事件处理器
2
# 宠物要找到生命药水(类型是 "potion"):
3
potion = pet.findNearestByType("potion")
寻找药水
4
# 并将它取回:
5
pet.fetch(potion)
取回药水
6
# 宠物要找到金钥匙(类型是"gold-key"):
7
goldKey = pet.findNearestByType("gold-key")
寻找金钥匙
8
# 并将它取回:
9
pet.fetch(goldKey)
取回金钥匙
10
11
# 宠物可以发现的不仅仅是物品:
12
skeleton = pet.findNearestByType("skeleton")
宠物也可以用来找敌人
13
pet.on("spawn", onSpawn)
绑定事件
14
15
while True:
英雄主循环
16
if skeleton.health > 0:
如果骷髅活着
17
hero.attack(skeleton)
攻击骷髅
18
else:
否则(骷髅已死)
19
hero.moveXY(31, 38)
移动到宝箱位置
第 73 关

钥匙陷阱 (Key Trap)

战术思路分析:宠物代劳

钥匙附近是陷阱,英雄不能亲自去拿!必须让宠物完成所有取回任务。

取回所有钥匙

宠物将按顺序执行 **铜钥匙、银钥匙和金钥匙** 的取回任务,无需英雄操心。

Fetch(Bronze) → Fetch(Silver) → Fetch(Gold)

Python 程序解法

1
def onSpawn(event):
宠物生成事件处理器
2
# 宠物需要找到并拿回3把钥匙。
3
pet.fetch(pet.findNearestByType("bronze-key"))
取回铜钥匙
4
pet.fetch(pet.findNearestByType("silver-key"))
取回银钥匙
5
pet.fetch(pet.findNearestByType("gold-key"))
取回金钥匙
6
7
pet.on("spawn", onSpawn)
绑定事件
8
9
while True:
英雄主循环:负责战斗
10
enemy = hero.findNearestEnemy()
11
if enemy and enemy.team == "ogres":
12
hero.attack(enemy)
13
if hero.health < 300:
14
potion = pet.findNearestByType("potion")
15
if potion:
16
hero.moveXY(potion.pos.x, potion.pos.y)
第 74 关

命令链 (Chain of Command)

战术思路分析:识别发令者

宠物只能回应**英雄**的命令。你需要从事件数据中提取说话者(`event.speaker`)并进行身份验证。

事件属性:`event.speaker`

在 `onHear(event)` 函数中,`event.speaker` 存储了说话者的单位对象。
判断条件:`if event.speaker == hero:`

IF event.speaker == hero: pet.say()

Python 程序解法

1
def onHear(event):
宠物监听事件
2
# "hear"事件设置event.speaker属性。
3
# 检查宠物是否听到了英雄的话:
4
if event.speaker == hero:
检查说话者是否是英雄
5
pet.say("WOOF")
宠物回应,唤醒巫师
6
7
pet.on("hear", onHear)
绑定事件
8
9
while True:
英雄主循环
10
enemy = hero.findNearestEnemy()
11
# 如果有敌人:
12
if enemy:
13
# 使用hero.say()提醒你的宠物
14
hero.say("Ogres!")
英雄发出指令
15
# 移动到营地内的X处。
16
hero.moveXY(30, 33)
17
# 然后返回营地外的X处。
18
hero.moveXY(30, 15)
第 75 关

宠物工程师 (Pet Engineer)

战术思路分析:兵种区分

宠物需要根据不同的呼救者(`archer` 或 `soldier`)移动到不同的按钮(控制机器人或大炮)。

关键:`event.speaker` 与 `elif`

首先找到两个发出指令的单位对象 (`archer`, `soldier`),然后在 `onHear` 中用 `if/elif` 结构比较 `event.speaker`。

IF Speaker == Archer: Left Button
ELIF Speaker == Soldier: Right Button

Python 程序解法

1
def onHear(event):
宠物监听事件
2
# 找到门卫
3
archer = pet.findNearestByType("archer")
找到弓箭手对象
4
soldier = pet.findNearestByType("soldier")
找到士兵对象
5
# 如果"event.speaker"参数是 `archer`:
6
if event.speaker == archer:
如果说话者是弓箭手
7
# 移动到左边的按钮。
8
pet.moveXY(32, 30)
移动到左按钮 (机器人)
9
# 如果"event.speaker"参数是`soldier`:
10
elif event.speaker == soldier:
否则,如果说话者是士兵
11
# 移动到右边的按钮。
12
pet.moveXY(48, 30)
移动到右按钮 (大炮)
13
14
pet.on("hear", onHear)
绑定事件
15
16
# 您不必更改下面的代码。
17
while True:
英雄主循环
18-20
# ... 英雄防御逻辑 ...
第 76 关

宠物翻译家 (Pet Translator)

战术思路分析:解密指令

炮兵说的是反向词!宠物必须将听到的消息(`event.message`)解密,然后说出正确的反向词。

事件属性:`event.message`

在 `onHear` 函数中,`event.message` 存储了说出的字符串。宠物需要检查这个字符串来决定说什么:
`if message == "North": pet.say("Htron")`

Message: "North"
Pet Say: "Htron"

Python 程序解法

1
def onHear(event):
2
# 宠物听到的消息在event.message中
3
message = event.message
获取听到的消息
4
# 如果消息是 "North":
5
if message == "North":
6
# 宠物说 "Htron"。
7
pet.say("Htron")
翻译并说出
8
# 如果消息是 "South":
9
if message == "South":
10
# 宠物说 "Htuos"。
11
pet.say("Htuos")
翻译并说出
12
# 如果消息是 "East":
13
if message == "East":
14
# 宠物说 "Tsae"。
15
pet.say("Tsae")
翻译并说出
16
17
pet.on("hear", onHear)
绑定事件
18
19-22
# ... 英雄主循环 ...
英雄负责战斗,确保不攻击斗士
第 77 关

宠物副官 (Pet Lieutenant)

战术思路分析:语音控制

英雄通过喊话来命令宠物移动到治疗点或火炮点。

IF/ELIF 语音命令

- `if event.message == "Fire"`: 宠物移动到火炮点 (`64, 16`)。
- `elif event.message == "Heal"`: 宠物移动到治疗点 (`64, 52`)。

Say("Fire") → Pet Moves to (64, 16)

Python 程序解法

1
def onHear(event):
宠物监听事件
2
# event.message包含所听到的文本。
3
# 如果有人说 "Fire"
4
if event.message == "Fire":
如果听到 Fire
5
# 用pet.moveXY()移动到底部的X标记
6
pet.moveXY(64, 16)
移动到下方 (火炮)
7
pet.say("MEAW")
宠物回应
8
# 如果有人说 "Heal"
9
elif event.message == "Heal":
否则如果听到 Heal
10
# 用pet.moveXY()移动到顶部的X标记
11
pet.moveXY(64, 52)
移动到上方 (治疗)
12
pet.say("MEAW")
宠物回应
13
14
pet.on("hear", onHear)
绑定事件
15-25
# ... 英雄主循环 ...
英雄负责战斗和呼叫
第 78 关

炼金术 (Alchemy)

战术思路分析:送药待命

宠物必须在听到炼金术师说 `"Fetch"` 时才去拿药水;听到其他任何话时,都应回到待命点(红色标记)。

IF/ELSE 决策

- `if message == "Fetch"`: 拿药水 (`pet.fetch()`)。
- `else`: 回到待命点 (`pet.moveXY(54, 34)`)。

IF "Fetch": Fetch()
ELSE: Move(Red X)

Python 程序解法

1
def onHear(event):
2
# 找到最近的药水。
3
potion = pet.findNearestByType("potion")
4
message = event.message
获取消息
5
# 如果事件的消息是 "Fetch"
6
if message == "Fetch":
如果听到 "Fetch"
7
# 让宠物拿取药水。
8
pet.fetch(potion)
去拿药水
9
# 其他(对于任何其他消息):
10
else:
否则(任何其他消息)
11
# 用pet.moveXY 让宠物回到红色标记。
12
pet.moveXY(54, 34)
回到待命点
13
14
pet.on("hear", onHear)
绑定事件
15-20
# ... 英雄主循环 ...
英雄负责战斗和移动
第 79 关

概念挑战. 宠物探索者 (Pet Explorer)

战术思路分析:双重认证

宠物必须确保:**说话者是探索者** (`event.speaker == explorer`) **AND** **说的是正确的数字** (`event.message == "1"`)。

AND 与嵌套 IF

首先用 `if event.speaker == explorer:` 排除农民。然后在内部嵌套 `if/elif` 来检查 `event.message`。

IF Speaker == Explorer:
  IF Message == "1": Move

Python 程序解法

1
explorer = hero.findNearestFriend()
找到探索者对象
2
3
def onHear(event):
4
if event.speaker == explorer:
如果说话者是探索者 (排除了农民)
5
if event.message == "1":
如果消息是 "1"
6
pet.moveXY(8, 26)
移动到按钮 1
7
elif event.message == "2":
如果消息是 "2"
8
pet.moveXY(26, 39)
移动到按钮 2
9
elif event.message == "3":
如果消息是 "3"
10
pet.moveXY(26, 13)
移动到按钮 3
11
12
pet.on("hear", onHear)
绑定事件
第 80 关

危险钥匙 (Dangerous Keys)

战术思路分析:精确取钥匙

只有圣骑士(`paladin`)知道哪把钥匙是安全的。宠物必须听从圣骑士的命令,并使用 `findNearestByType` 找到正确的钥匙取回。

多重查找与 IF/ELIF

宠物首先需要预先找到所有三种钥匙的对象。然后,在 `onHear` 中,通过检查 `event.speaker` 和 `event.message` 来精确地执行 `fetch`。

IF Speaker == Paladin:
  IF Message == "Gold": Fetch(GoldKey)

Python 程序解法

1
def onHear(event):
2
# 宠物可以找到圣骑士和钥匙。
3
paladinUnit = pet.findNearestByType("paladin")
找到圣骑士对象
4
goldKey = pet.findNearestByType("gold-key")
预先找到所有钥匙
5
silverKey = pet.findNearestByType("silver-key")
6
bronzeKey = pet.findNearestByType("bronze-key")
7
# 如果event.speaker是paladinUnit:
8
if event.speaker == paladinUnit:
第一层检查:说话者必须是圣骑士
9
# 如果event.message是"Gold":
10
if event.message == "Gold":
如果命令是 Gold
11
# 宠物需要取金钥匙。
12
pet.fetch(goldKey)
取金钥匙
13
# 如果event.message是 "Silver":
14
elif event.message == "Silver":
如果命令是 Silver
15
# 宠物需要取银钥匙。
16
pet.fetch(silverKey)
取银钥匙
17
# 如果event.message是"Bronze":
18
elif event.message == "Bronze":
如果命令是 Bronze
19
# 宠物需要取青铜钥匙。
20
pet.fetch(bronzeKey)
取铜钥匙
21
22
pet.on("hear", onHear)
绑定事件
第 81 关

奥林匹克比赛 (Olympic Race)

战术思路分析:发令枪

比赛开始的条件非常严格:**必须是裁判** (`wizard`) **AND** **说的必须是 `"Start"`**。

AND 组合判断

`if event.speaker == referee and event.message == "Start":`
只有当两个条件都为真时,宠物才能开始比赛,否则就是抢跑!

IF Speaker AND Message: Run!

Python 程序解法

1
def onHear(event):
宠物监听事件
2
referee = pet.findNearestByType("wizard")
找到裁判员(巫师)对象
3
# 如果说话的人是裁判员referee并且说的是"Start":
4
if event.speaker == referee and event.message == "Start":
双重条件:裁判 AND Start
5
# 让宠物跑到红色标记。
6
pet.moveXY(53, 27)
跑到队伍标记
7
# 然后跑回来。
8
pet.moveXY(6, 27)
跑过终点线
9
10
# 指派onHear函数来处理"hear"事件。
11
pet.on("hear", onHear)
绑定事件