介紹#
沒有完成入門任務的參考上一篇安裝入門
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 需要我們自己補充實現。
第一部分:簡單的決鬥#
第一部分需要編寫 sorcerer_duel.cairo 中的決鬥函數 duel(ref sorcerer1: Sorcerer, ref sorcerer2: Sorcerer)
,每回合由 sorcerer1 先手,sorcerer2 後手,有任何一方生命結束停止戰鬥,沒有返回值。
使用 cairo 中的loop{}
來實現功能,類似其他編程語言的 while,這部分很容易,在循環中每次生命值減少對方的攻擊力,有一方生命為 0 終止循環。注意生命值不能變為負值。
第二部分:天賦機制#
第二部分需要給法師添加 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 的錯誤
第三部分:團戰#
第三部分是團戰,需要創建 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/ ,最終能做出結果,會獲得巨大的收穫,加油。