3つめは Battleship(バトルシップ)。2人で遊ぶ「船しずめ」ゲームです。 自分の船の場所は相手に絶対見せないのに、攻撃が当たったか外れたかはウソをつけない。ゼロ知識証明のすごさが、ゲームで体感できます。
何を作るの?
- 2人のプレイヤーが、自分の船の位置を秘密のままコミットする
- 交互に攻撃し、相手は「当たり(HIT)/外れ(MISS)」を答える
- 先に決められた数を当てた方が勝ち
何を学べるの?
- 隠した状態(private state):船の場所はチェーンに出さない
- ズルの検出:当たっているのに「MISS」とウソをついたら、契約が見破る
- 状態マシン:手番の順番を
enumで管理する - テスト:Vitest で「成功も失敗も」全部テストする
たとえ話:手品のタネは見せない
手品師は、タネを見せずに「ちゃんと成立している」ことを観客に納得させますよね。
Battleship も同じ。船の場所(タネ)は見せずに、「いまの答えはルール通り正しい」ことだけを証明します。
しかも、ウソをつこうとすると assert が見破って取引が失敗します。
契約の中身(本物・短い)
状態を enum で表します。
公開ステートと、秘密の入口(witness):
船の場所は、そのままではなくハッシュにしてコミットします。
そして手番のチェックは assert で守ります。
ズルの検出(イメージ):当たっているのに MISS と答えると、assert(...) が「Cheat Detected」で取引を止めます。
テストも学べる
Battleship にはテストの作りかたのページもあります。
- ローカル網(Docker の proof server・indexer・node)で動かす
- 「成功するはず」と「失敗するはず(ズル)」の両方をテスト
- 例:
expect(state.turn).toEqual(TurnState.PLAYER_1_SHOOT)のように状態を確認
進む前に理解しておくこと
- Bulletin Board(秘密の本人確認の感覚)
- ゼロ知識証明(見せずに証明)
- Compact の書きかた(
enum/Set/assert/witness)
開発者として理解すべきこと
- 秘密の状態をハッシュでコミットし、ZK で「正しさ」だけ示す典型
- ルール違反(ズル)を
assertで契約自身に検出させる設計 - 手番などの流れは 状態マシン(enum)で管理する
- テスト(成功も失敗も)を書いて、契約の正しさを守る
公式Docsではどこ?
- Battleship: contract(外部リンク・別タブで開きます)
- Battleship: tests(外部リンク・別タブで開きます)
- ソース:example-battleship(外部リンク・別タブで開きます)
今日のまとめ
- Battleship=船を見せずに、当たり外れだけ正直に証明するゲーム
- 学べること:隠した状態・ズル検出・状態マシン・テスト
- 秘密はハッシュでコミット、ルールは
assertで守る
今はここだけでOK
「船の場所は見せない。でもウソはつけない」——この一文に Battleship の全部がつまっています。
つぎに読むページ
➡️ ブラウザの DApp と本番デプロイへ。Leaderboard チュートリアル