Claude Sonnet で 3マッチゲームが作れるのか?

Amazon の Kiro で spec 駆動(仕様駆動)が流行りですが、AI エージェントを使うと Kiro とかじゃなくても結構いけます、というお話です…と同時に、それ以上いけません、というのも記録しておきます。

手元で試している Claude Sonnet は Claude Code の廉価版みたいなもので、GitHub Copilot Pro(月10ドル) + Claude Sonnet(無料)の組み合わせ開発が可能です。業務や精度をアップしたいときは Claude Code 等を使うといいんでしょうがお金が結構かかるのと同時にリクエスト制限が結構きついです。X を見る限り2,3時間でリミットに達する模様。その点では、GitHub Copilot Pro + Claude Sonnet の組み合わせだとリクエストが無制限になっていて(本家、Claude Sonnet だけだと時間内制限があります、何故w)、それなりに開発ができます。ちなみに、皆さんが Opus 4 を使っているらしく、Sonnet 4 のほうは空いていてレスポンスがよいです。

ちなみに、モデルを GPT40 に変えることができるのですが、コード生成の質が悪くて、最初の課題がクリアできません。素直に Claude Sonnet を使う方がいいです。

React Native Expo で3マッチゲームを作る

3マッチゲームは結構古くからあって、ルール自体は隣のブロックを入れ替えて3つに並んだら消えるという簡単なものです。samegame もそうですよね。ルールが簡単なので、プログラムで作るのも比較的簡単なのですが、最初の頃からバリエーションが増えてきて、最近ではいろいろなブロックのアイテムがあります。

Fishdom
https://play.google.com/store/apps/details?id=com.playrix.fishdomdd.gplay&hl=ja

単純に上から下というわけでもなく、課金うんぬんはさておき、ディズニーキャラクター版とかもあったります。単にぽちぽち消すのではなく、ぷよぷよみたいに連鎖しないと意味がありません。

というわけで expo でプロジェクトを作ります

npx create-expo-app swap-game-expo0 --template expo-template-blank-typescript

実は Kiro 風に readme.md を作って、プロジェクトを作成するところからスタートしても構いません。が、プロジェクト構造を最初に決めておいて、どんなフレームワークを使うのかを AI エージェントに伝えたほうが完成の角度が高いです。

Expo プロジェクトができたら、プロンプトに入力します。

3マッチゲームを作って。

設計上いろいろ決めてもいいのですが、ひな形を先に作って貰った方が早いです。

おそらく、この手のゲームのテンプレートがモデル内にある感じがしています。Transformer だけではちょっと無理かなと思うのですが、ここでは問いません。多分、どの AI エージェントを使っても3マッチゲームとかオセロとか定番なものは揃っているでしょう。

スマホで動かす前に PC の web ブラウザ上で動かしてみましょう。

npm run web

で起動できるのですが、web のライブラリが入っていないのでこれを入れます。

npx expo install react-dom react-native-web @expo/metro-runtime

この手の問題は「web ブラウザでも動くように」とプロンプトで指示するといけるような気もするのですが、ペアプロ的に作りながら指示したほうが楽です。

ちなみにプロンプトで「3マッチゲームを作って」と指示をしても同じコードが生成されるとは限りません。AI エージェントは生成 AI と同じように内部ではランダムな回答を出すようになっている(ことが多い)ので、生成されるコードもある程度ランダムになります。つまり、再現性が低いのです。

spec 駆動の場合は、これを要件/設計(claude.md)で詰めることになっていますが、夜間バッチで動かすためのものなので、正確に狙った形の出力を得るのは難しいでしょうね。一案としては、設計を書いたあとに、5~10個ぐらい同時に動かしてコード生成をした後に、よいものをピックアップするよいでしょう。いわゆる A/B テストか、遺伝子プログラミングのように目標を絞っている形になるのですが、まあ、課金は結構かかりそうです。そのあたりは、タイムパフォーマンスをどのあたりで手を打つかというところでしょう。

私の場合は、ペアプロ風に readme.md を書いていくほうが開発スタイルに合っています。

結論から言えば「3マッチゲームを作って」というプロンプトだけで、ここまでいけます。ブロックをマウスで選択して交換する、ブロックが消える、というルールは満たしてあります。UI としてはしょぼいですが、最初のプロトタイプとしてはこれで十分ですよね。去年あたりに所謂「AI 驚き屋」さんがやっていたのもこんな感じです。ブロック崩しとかオセロとかちょっとしゅたシューティングゲームとかの定番は、モデル自身が持っているテンプレート(たぶん)から引っ張ってくるだけで ok です。これは TypeScript で書かれていますが、他の言語に直すこともできます。こういう使い方は便利ですね。

ジェルを SVG で描画する

遊べるの少し動かしてみるのですが、かなりしょぼいです。

小学生の夏休みの宿題ならばなんとかななりそうだけど、仕事?では無理そうです。コードを見ると単純なHTMLを使っているだけなので、消えるときのアニメーションとから落下のアニメーションがありません。このあたり「落下のアニメーションを付けて」とか試行錯誤することもできるのですが、そもそも SVG 形式で描画しないとカラフルにはなりませんよね。

SVG を使ってジェルなどをカラフルにして。

プロンプトで「SVG」を指定するのですから、spec駆動の場合には設計時に「SVG形式を使うどうか」というのが問題になりますよね。そのあたりspec駆動の場合は狙うことができるのかは不明です。ただし、SwiftUI とか Compose UI とかの標準的なコンポーネントだけ使う場合はうまくいくかもしれません。そのあたり、デザイナー視点をどう含めるかが問題ですが。私の場合は、ロジックを先に作って UI で装飾、という手順のほうがよいと思っています。

SVG 形式を使ったのでかなりカラフルになっています。「カラフル」という用語を使ったのですが、これもモデルに内で最適化されたものでしょう。これあこれで遊べるのですが、落下アニメーションとか爆弾のアイテムとかがないので、かなりしょぼいです。

落下アニメーションを付ける

落下アニメーションを付けて。
ジェルが3つ消えるときに爆弾アイテムを出現させて。

SVG のときもそうでしたが、AI エージェントは App.tsx をがんがん書き変えます。これが人の開発者であれば、構造化したり共通化したりするところですが AI の場合は検索できるパターンがあれば機械的に書き変えるの手間がかからないので、全て書き変えてしまう勢いです。

将来的に AI エージェントで出力させたコードの Git 履歴とかが難しいでしょうね。ある程度コード量が多くなってくると、トークン数の制限のためにコードを部分的に読み出すように最適化されてきます。このときに、設計スタイルとしてオブジェクト指向の各種パターンを使うかどうかは定かではないのですが、試した感じでは「1回のトークン数を超えていくところからバグを大量発生」させていきます。おそらく全体の整合性がとれなくなってしまうのでしょう。人の開発者ならば、構造化して眺めるコード量を抑えるのですが、現在の AI エージェントではその視点がありません(上位バージョンの Opus 4 にはあるかもしれません)。なので、AI エージェントが読み込みやすいようにある程度コードを構造化するようにプロンプトで誘導するのがベターかもしれません。

落下アニメーションが、ジェルが消える場所を埋めるように落下させて。
爆弾をクリックしたら、上下左右の4個のジェルを消して。爆発アニメーションを付けて。

あと、ブラウザでアニメーションがうまく表示されていないので、書き変えて貰います。

落下アニメーションがブラウザででていません。

このあたり、一発で思った通りのものが出力されません。それどころか、何かの指示を出すたびにどこかのバグを含めてしまいます。それをいちいち UI を動かして動作を確認していきます。このあたりは、ちょうどテスターの役割を人間が担います。

ゲームを動かして、ちょっとずつ完成させていくイメージですね。自分でコーディングしたほうが早いのではないか?って場合もあるでしょうが。実際、ある程度の複雑なコードの場合は人間がやったほうがよさそうです。ただし、AI エージェントのコードは可読性がよくないので、人が読むのは一苦労です。可読性が良くなるようにリファクタリングした貰うといいかもしれません。

落下するときのアニメーションをなめらかにしたり、爆弾アイテムをつけたりした状態がこの状態になります。動きがおかしいですよね。一見すると複雑な条件で設計ができそうなのですが、3マッチゲームはなかなか完成しません。

おそらく、条件の組み合わせ爆発のときに駄目っぽい感じがします。業務アプリケーションのように管理画面で CRUD 機能をつけるとかカテゴリから商品をひらくとかいうステートがあまり変化しないものは大丈夫なのですが、3マッチゲームのようにまともにやると遷移表が爆発しそうなものは AI エージェント頼りでは難しそうです。

テスト可能なように構造化する

まあ、ゲームロジックの場合は、いろいろな条件が重なるので View と Logic を分離させておくのがよいでしょう。

ジェルの消去や爆弾の出現条件をテストできるようにコードを構造化して。

果たして、テスト可能なように構造化してくれるでしょうか?

デバッグ画面っぽいものは出るのですが、なんか違うんですよね…これは、Claude の中の人が悪いのか、Sonnet が悪いのか。

続きは後日。

ちなみに、現在のルールとかは次のプロンプトを使うとよいです。

設計書を design.md に書き出して。

ファイル名とか文言とかは変更しても大丈夫です。まあ、致命的なのは、この design.md を最初に渡して3マッチゲームが完成されないことなんですよね。これも再現性がないので、何回か繰り返すと猿がシェイクスピアを生み出す確率でうまく出力されるかもしれないですが。

# 3マッチゲーム 設計書

## 概要
React Native/Expoを使用したモバイル向け3マッチパズルゲーム。SVGベースのカラフルなジェルと爆弾アイテム、落下アニメーション、爆発エフェクトを特徴とする。

## 技術仕様

### フレームワーク・ライブラリ
- **React Native**: 18.x
- **Expo**: SDK対応
- **react-native-svg**: SVGグラフィックス
- **TypeScript**: 型安全性

### 対応プラットフォーム
- iOS
- Android
- Web (Expo Web)

## ゲーム仕様

### 基本ルール
1. 8x8のグリッドボード
2. 5種類のジェル(赤、緑、青、黄、紫)
3. 隣接するタイル同士の交換
4. 3個以上の同色マッチで消去
5. 重力による落下システム
6. 空いたスペースに新しいタイルが補充

### 特殊アイテム
- **爆弾**: 4個以上のマッチで生成
- **爆弾効果**: 上下左右4方向のタイルを消去
- **爆発アニメーション**: スケール・透明度変化

### 勝利条件・ゲーム終了
- エンドレス仕様(現在)
- 将来的にスコアシステム、レベル制を追加予定

## アーキテクチャ設計

### コンポーネント構成

```
App
├── ExplosionEffect (爆発エフェクト)
├── BombTile (爆弾タイル)
├── AnimatedGelTile (ジェルタイル)
└── DebugPanel (デバッグUI)
```

### 状態管理

```typescript
// メインゲーム状態
const [board, setBoard] = useState<TileType[][]>() // ボード状態
const [selected, setSelected] = useState<Position>() // 選択中タイル
const [isAnimating, setIsAnimating] = useState<boolean>() // アニメーション中フラグ
const [explosions, setExplosions] = useState<Position[]>() // 爆発エフェクト
const [debugMode, setDebugMode] = useState<boolean>() // デバッグモード

// アニメーション管理
const animationValues = useRef<Animated.Value[][]>() // 落下アニメーション値
```

### データ型定義

```typescript
// 基本型
const TILE_TYPES = ['red', 'green', 'blue', 'yellow', 'purple'] as const;
const SPECIAL_ITEMS = ['bomb'] as const;
type TileType = typeof TILE_TYPES[number] | typeof SPECIAL_ITEMS[number] | null;

// 位置情報
interface Position {
y: number;
x: number;
}

// アニメーション情報
interface AnimationInfo {
fromY: number;
toY: number;
tile: TileType;
}
```

## ゲームロジック設計

### GameLogicオブジェクト

```typescript
const GameLogic = {
// ボード操作
createBoard(): TileType[][] // ランダムボード生成
createTestBoard(pattern): TileType[][] // テスト用ボード生成
cloneBoard(board): TileType[][] // ボードクローン

// マッチング処理
findMatches(board): boolean[][] // マッチ検出
removeMatches(board, matched): result // マッチ消去

// 爆弾処理
handleBombExplosion(board, y, x): count // 爆弾爆発処理
shouldGenerateBomb(count): boolean // 爆弾生成判定

// タイル操作
dropTiles(board): void // 落下・補充処理

// テスト・デバッグ用
countTotalMatches(board): number // マッチ数カウント
countTilesByColor(board, color): number // 特定色カウント
boardToString(board): string // ボード文字列化
}
```

### 処理フロー

#### 1. タイル交換処理
```
handleTileClick(y, x)
├── 爆弾チェック
│ ├── 爆発アニメーション開始
│ ├── handleBombExplosion()
│ ├── dropTiles()
│ ├── 落下アニメーション
│ └── processMatches()
└── 通常タイル
├── 選択状態更新
├── 隣接チェック
├── タイル交換
└── processMatches()
```

#### 2. マッチ処理
```
processMatches(board, shouldGenerateBombs)
├── findMatches()
├── removeMatches()
├── 爆弾生成判定 (4個以上)
├── dropTiles()
├── 落下アニメーション
└── 再帰処理(連鎖)
```

#### 3. 落下アニメーション
```
calculateDropAnimations(oldBoard, newBoard)
├── 各列の移動追跡
├── animationMapの生成
└── 距離計算

animateDrop(animationData)
├── アニメーション設定
├── 並列実行
└── 完了コールバック
```

## UI/UX設計

### ビジュアルデザイン
- **テーマ**: ダークモード(背景: #1a1a2e)
- **ジェル**: SVGグラデーション、立体感
- **爆弾**: メタリック質感、導火線付き
- **エフェクト**: 爆発は放射グラデーション + 火花

### アニメーション仕様
```typescript
// 落下アニメーション
duration: Math.abs(fromY - toY) * 80 // 距離比例
easing: Linear // 等速度

// 爆発エフェクト
scale: 0 → 3 // 拡大
opacity: 1 → 0 // 透明化
duration: 400ms // 固定時間
```

### レスポンシブ対応
- タイルサイズ: 38px固定
- ボードサイズ: 8 * 42px (パディング含む)
- 画面サイズに応じた中央配置

## テスト設計

### テスト機能
```typescript
// デバッグモード機能
testThreeMatch() // 3マッチテスト
testBombGeneration() // 4+マッチ→爆弾生成テスト
testBombExplosion() // 爆弾爆発テスト
logBoardState() // ボード状態ログ出力
forceMatchAt() // 強制マッチ作成
```

### テストパターン
1. **3マッチテスト**: 爆弾生成されない
2. **4+マッチテスト**: 爆弾生成される
3. **爆弾テスト**: 十字方向消去確認
4. **連鎖テスト**: 連続マッチ処理
5. **落下テスト**: アニメーション確認

## パフォーマンス設計

### 最適化手法
- `useNativeDriver: false`: Web互換性重視
- アニメーション並列実行: `Animated.parallel()`
- 状態更新最小化: 必要時のみsetBoard()
- メモリ管理: アニメーション完了時リセット

### レンダリング最適化
- `key`属性適切設定: `tile-${y}-${x}`
- SVGグラデーションID重複回避: `${color}-${position}`
- 条件付きレンダリング: デバッグパネル、エフェクト

## セキュリティ・品質

### エラーハンドリング
- 境界値チェック: 配列インデックス
- null/undefined対策: オプショナルチェーン
- アニメーション中操作制限: isAnimatingフラグ

### コード品質
- TypeScript型安全性
- ESLintルール準拠
- コメント・ドキュメント完備
- 関数型プログラミング重視

## 今後の拡張予定

### 機能追加
- [ ] スコアシステム
- [ ] レベル制・難易度調整
- [ ] 音効・BGM
- [ ] 特殊アイテム追加(レインボー、ラインクリア等)
- [ ] アチーブメントシステム

### 技術改善
- [ ] Redux/Zustand状態管理
- [ ] React.memo最適化
- [ ] PWA対応
- [ ] オフライン機能
- [ ] マルチプレイヤー

### テスト強化
- [ ] Jest単体テスト
- [ ] E2Eテスト (Detox)
- [ ] パフォーマンステスト
- [ ] アクセシビリティテスト

## 開発環境

### 必要ツール
```bash
npm install -g expo-cli
npm install react-native-svg
```

### 実行方法
```bash
npx expo start # 開発サーバー起動
npx expo start --web # Web版実行
```

### ビルド
```bash
npx expo build:ios # iOS向けビルド
npx expo build:android # Android向けビルド
```

---

**作成日**: 2025年7月22日
**バージョン**: 1.0.0
**更新者**: AI Development Assistant
カテゴリー: 開発 パーマリンク