介绍#
没有完成入门任务的参考上一篇安装入门
Sparring Sorcerers 是 Cairo 的 数据结构与算法任务 Think Cairo 的第一篇,主要解决所有权和数组操作。需要编写 2 个法师组成的队伍对战。
sorcerer.cairo 中是定义法师,法师有 attack,health,talent 属性,有 new 和 with_talent2 个生成实例的方法,还有获取 attack 和 health,如果 health 为 0 失败的 bool。
sorcerer_duel.cairo 和 sorcerer_battle.cairo 需要我们自己补充实现。
Part I: Simple Duels#
第一部分需要编写 sorcerer_duel.cairo 中的决斗函数 duel(ref sorcerer1: Sorcerer, ref sorcerer2: Sorcerer)
,每回合由 sorcerer1 先手,sorcerer2 后手,有任何一方生命结束停止战斗,没有返回值。
使用 cairo 中的loop{}
来实现功能,类似其他编程语言的 while,这部分很容易,在循环中每次生命值减少对方的攻击力,有一方生命为 0 终止循环。注意生命值不能变为负值。
Part II: The Talent Mechanic#
第二部分需要给法师添加 Talent,一共有 3 种新天赋,Venomous 是每轮攻击力 + 1,Swift 是如果对手的攻击力小于 4,只会有 1 点伤害,Guardian 可以抵挡第一次伤害。
注意函数 fn duel(ref sorcerer1: Sorcerer, ref sorcerer2: Sorcerer)
中的参数 ref,有了 ref 可以直接修改传入的参数,改变函数外的状态。参考 https://book.cairo-lang.org/ch04-02-references-and-snapshots.html?highlight=snapshot#mutable-references
我的做法是把 attack 赋值到一个 mut 变量,命名 damage,后面生命值减去 damage,let mut damage1 = sorcerer1.attack;
,
这儿读取 attack 值用 sorcerer1.attack () 也可以,因为 Sorcerer 里实现了fn attack(self: @Sorcerer) -> u8 { *self.attack }
,@是获取快照,* 是快照转为新变量。但需要引入 use src::sorcerer::SorcererImpl;
先判断 Swift,例如 sorcerer2 如果是 Swift 且 sorcerer1 攻击力大于 4,damage = 1。
判断 Guardian,如果是的话,在战斗时跳过生命值修改,并改成 Talentless 即可。
最后判断是 Venomous,把 attack+=1(不是 damage),这儿需要直接修改 sorcerer.attack。
需要注意 enum 的对比方法,
mut 关键字,其他部分和一般编程语言类似
loop 中的条件判断语句需要 “;” 结尾,否则会出现 loop 中不能使用 condition 的错误
Part III: Team Battles#
第三部分是团战,需要创建 2 个数组 Array,分别派出第一个法师出战,如果生命变为 0 就换下一个法师,至于攻击的先手后手,你需要对照测试用例 test/battle_test_3.cairo 去看。
同样函数的 team array 用了 ref: fn battle(ref team1: Array<Sorcerer>, ref team2: Array<Sorcerer>)
,后续的操作会直接改变 array。
基础思路是:每次 battle 都派出队伍里第一个 sorcerer 进行 duel,如果生命为 0 就换下一人,直到任一方队伍人数为 0 且战斗的法师生命为 0 结束。
但是直接修改 array 里的元素,就算用了 ref,也不会生效,需要把元素用 pop_front 弹出来后进行修改后再加回去。
还有很多细节需要根据测试用例进行调整,本地通过后线上还有更严格的测试,还需要完善代码。
如果测试用例不能通过,建议用 debug 一步一步查询原因。
总结#
真正有难度的内容开始了,希望能你保持耐心,如果卡住了,多看看其他文档,例如
https://github.com/starkware-libs/cairo/tree/main/corelib/src 和 https://book.cairo-lang.org/ ,最终能做出结果,会获得巨大的收获,加油。