作っているiOSのボードゲームアプリに、2つ目のゲームを足しました。1つ目とよく似たゲームなので、共通の仕組みにまとめたくなりましたが、結局まとめませんでした。この記事では、2本目を作るときに共通化するかどうかをどう決めたか、子ども向けにCPUの強さをどう手加減したかを書きます。
作りたかったもの
1つのアプリから2つのゲームを選んで遊べる形にすることが目標でした。もともと入っていたのは「きえるまるばつ」です。3目並べですが、盤に置いた駒が消えていきます。
そこに「ふつうのまるばつ」、つまり駒が消えない3目並べを足します。完了の条件は3つ決めていました。2つのゲームを選んで遊べること、ふつうのまるばつが引き分けを扱えること、つよいCPUが手加減されていることです。もちろんビルドとテストも通っていなければいけません。
画面の流れはこう変えました。タイトル画面をゲーム選択画面にして、「ゲームを選ぶ→対戦相手を選ぶ→対局」の2段の移動にします。
flowchart LR A["ゲーム選択"] --> B["まるばつ<br/>2人で遊ぶ"] B --> C["対戦相手を選ぶ"] C --> D["対局"] A --> E["1人で遊ぶゲーム<br/>(今後追加)"] E --> D
この図は、選んだゲームによって画面の道が2つに分かれることを表しています。あとからマインスイーパーのような1人で遊ぶゲームを足したときに、対戦相手を選ぶ画面が邪魔になるのが分かっていました。マインスイーパーは今回まだ作っていませんが、先に足すと決めているものです。
そこで、ゲームの種類を並べた一覧をアプリの中に用意しました。その一覧の項目ごとに「このゲームは対戦相手を選ぶ必要があるか」を書いておきます。必要がないゲームは、対戦相手の画面を通らずそのまま対局に入ります。
AIへの頼み方
作業は Claude Code に頼みました。私が決めたのは、どこまで作るかと、どの設計を採るかです。設計については、同じ案を ChatGPT にも見せて意見をもらいました。
頼んだ内容は、ゲーム選択画面を作ってふつうのまるばつを足すこと、という大きさのものです。細かい手順は私が書いていません。そのかわり、できたものを見て「ここは共通化しないでほしい」「CPUが強すぎる」と判断を返していく形になりました。
結果として、既存のきえるまるばつの中身(盤の状態・進行の処理・CPU)には1行も手が入りませんでした。ふつうのまるばつは、その3つをそれぞれ別に作り、独立した部品として足しています。既存のほうはすでにテストが通って動いています。そこに手を入れれば、動いていたゲームを壊すおそれがあります。
つまずいたところ
いちばん迷ったのは、共通化するかどうかです。2つのゲームはどちらも3目並べで、盤も同じ3×3です。どんな盤にも使える汎用の「盤ゲームエンジン」を1つ作り、2つのゲームをその上に乗せたくなりました。「どのゲームも同じ作りにする」という取り決めを先に決めてしまう手もあります。1つ作れば2つのゲームが動く、という形はきれいに見えます。
次につまずいたのが引き分けです。きえるまるばつは駒が消えるので、盤が埋まって引き分けになることがありません。そのため結末は「勝った人はだれか」という1つの記録だけで足りていました。だれも勝っていなければ、その記録は空にしておきます。
ところがふつうのまるばつには、盤が9マス埋まって決着しない引き分けがあります。記録が空のままでは、「まだ勝負がついていない」と「引き分けで終わった」を見分けられません。
3つめは、つよいCPUが強すぎたことです。最後まで全部読む「完全読み」にすると、CPUは絶対に負けません。子どもが一度も勝てないゲームになってしまいます。
残りは細かい問題でした。iPadで見ると選択ボタンが画面の幅いっぱいに伸びて間の抜けた見た目になります。ボタンの白い文字は、地色のオレンジに対して読みにくいままでした。そしてテストの期待値を、私(と Claude Code)は2回まちがえました。
どう判断したか
共通化はしないと決めました。理由は、共通化できるところが思ったより少なかったからです。盤の大きさを変えられるようにしても、駒が消える順序・勝利条件・引き分けの扱い・CPUの評価はどれもゲームごとに違います。2本目を作った時点で本当に重なっているのは、マスの位置と手番の2つだけでした。ChatGPT の助言もこの方向だったので、汎用のエンジンも「どのゲームも同じ作りにする」という取り決めも作りませんでした。
flowchart TB S["共有するもの<br/>マスの位置・手番・画面の部品"] G1["きえるまるばつ<br/>状態・進行・CPU"] G2["ふつうのまるばつ<br/>状態・進行・CPU"] S --> G1 S --> G2
この図は、2つのゲームが何を共有し、何を別々に持っているかを表しています。
引き分けについては、ふつうのまるばつ専用の結末の記録を新しく作りました。「だれかの勝ち」と「引き分け」の2つを、きちんと区別して持てるものです。既存の記録を無理に広げると、きえるまるばつ側にも手を入れることになります。それは避けたかったので、新しいゲームの側だけに新しい記録を用意しました。
CPUの強さは、勘ではなく自動対戦で測って決めました。深さというのは、CPUが何手先まで読むかの数です。相手役には「勝てる手と、相手の勝ちを止める手が分かる打ち手」を用意しました。深さごとに2000局ずつ戦わせ、CPUが先手のときと後手のときの平均をとっています。
| 読む深さ | 相手の勝率 | CPUの勝率 |
|---|---|---|
| 2 | 21.7% | 23.8% |
| 3 | 21.7% | 38.0% |
| 4 | 14.1% | 37.4% |
| 9(完全読み) | 0.0% | 46.3% |
2つの勝率を足しても100%にならないのは、残りが引き分けだからです。深さ9(完全読み)では相手が一度も勝てず、600局を通して負けなしでした。完全読みが絶対に負けないことは、これで確かめられました。
深さ2はCPUが弱すぎます。深さ4以上にすると、こんどは相手の勝率が下がっていきます。相手が2割ほど勝てて、CPUもそれなりに勝つ深さ3を採りました。なぜ深さ3なのかという根拠は、あとで自分が忘れるのでコードのコメントに残しています。
画面の部品は共有しました。盤を描く部品に盤の状態をまるごと渡すのをやめ、「そのマスがだれの駒か」だけを受け取る形に変えています。こうすると、描く側はゲームの決まりごとを何も知らなくてよくなります。駒が消えるゲームでも消えないゲームでも、同じ部品で描けます。
テストの期待値をまちがえた件は、直し方が2通りに分かれました。「最後のマスで勝つ」手順は、Pythonで盤面を並べ直して検算したところ、そもそも3つ揃わないことが分かったので手順を差し替えました。もう1件は「もういっかい」を押したあとに思考中になるかどうかで、こちらは実装が正しく、テストの期待値が誤りでした。もういっかいのあとは×が先手になるので、CPUがまた考え始めるのが正しい動きです。実装に合わせてテストを直しました。
この経験から、新しいテストの手順は先にPythonで盤面を再現して検算するようにしました。Swiftのテストを書く前に、途中で決着していないか、期待した結末になるかを別の方法で確かめる流れです。
できたもの
シミュレータ(パソコンの中でiPhoneを再現する仕組み)のiPhone 17 Pro でテストを実行し、66件すべてが通りました。既存が37件、新しく書いたのが29件です。テストは、調べる対象ごとに9つのまとまりへ分けています。既存のテストは1件も緩めていません。
ビルドは、前に作ったものを全部消してから作り直す形でも試しました。作り直したファイルだけを見ていると、警告が前回の結果に隠れて見えないことがあるからです。この作り直しでも、コンパイラの警告は0件でした。
ボタンの読みにくさは、スクリーンショットの画素から文字と地色の明るさの比を測って直しました。白文字のときは 2.31:1 で、濃い茶に変えたあとは 7.65:1 です。この比はWCAG(ウェブの見やすさの基準)で 4.5:1 以上が求められているもので、Appleは小さい文字では 7:1 を目標にするよう書いています。直したのは文字の色だけで、地色のオレンジはそのままです。
ゲーム選択画面の見た目は、iPhone 17 Pro と iPad Pro 11-inch のシミュレータで確認しました。iPadでボタンが伸びる問題は、読みやすい幅に収める指定を入れて直りました。
やり残したこともあります。盤面を実際にタップする操作の確認と、画面の移動が本当に動くことの確認ができていません。画面を機械に自動で操作させるには、パソコン側でアクセシビリティ(操作を代行する仕組み)の許可を出す必要があり、今回はそれができませんでした。
まとめ
- 2本目を作る時点では、共通化できる部分は思ったより少ない。盤の形が同じでも、勝利条件やCPUの評価は別物になる。重なっているものを数えてから決めるほうが安全だった。切り出すのは、重なりが本当に見えてからでも遅くない。
- 結末の残し方は、あとから足すゲームでつまずきやすい。「勝った人」だけを記録していると、引き分けのあるゲームを足せない。
- CPUの強さは自動対戦で測ると決めやすい。何千局か戦わせて勝率を見れば、「強すぎる」を数字で説明できる。
次は、実際に指でタップして画面の移動が動くことを確かめます。
参考にした資料
- Understanding Success Criterion 1.4.3: Contrast (Minimum) | W3C
- Accessibility | Apple Developer Documentation(Human Interface Guidelines)
- Running tests and interpreting results | Apple Developer Documentation
この記事は、筆者の開発記録をもとにAI(Claude)が下書きし、筆者が確認して公開しています。