Algorithm & UI/UX
非破壊的な画像タイル分割と
剰余算によるクリア判定アルゴリズム
「回転パズル・くるりん」は、サーバーサイドを一切介さず、ブラウザ上の計算リソースのみで複雑なパズル体験を提供します。その効率的な画像制御と状態管理の仕組みを解説します。
このツールの入力から出力まで
現行コードの確認日:
- 入力
- 写真と分割数を選び、各ピースをタップして回します。
- 処理
- 1枚の背景画像からCSSの内側要素で範囲を切り出し、ピースに90度単位の回転を掛けます。
- 出力
- プレイ用の回転盤面を画面に表示し、クリア後は写真・時間・タップ数を描いた800×1000pxのJPEG(品質指定0.9)を保存できます。
まず確認する点:初期角度は90・180・270度のいずれかです。場所の交換は行わず、元写真の正しい向きを見ながら戻します。
仕上がりの例
猫の写真から作った回転パズルのプレイ画面です。
掲載画像はサイトにある既存の公開作例です。保存済みの資料では運営者の愛猫の写真を使用しています。今回の確認日が、この作例を実行した日を表すわけではありません。
保存済み検証記録の条件を見る
資料の種類は「ツールのプレビュー・結果画面を保存した記録」です。公開作例と保存済み記録で素材や色などが異なる場合があるため、下の数値は保存済み検証記録の条件として読んでください。
- 記録の入力画像
- 800×1066px (JPEG)
- 記録の画面キャプチャ
- 441×441px (PNG)
| 画面の項目 | 記録の値 | 現行コードの初期値・範囲 |
|---|---|---|
| 記録の盤面 | 3×3 | — |
資料ファイルの作成日は実行日として扱っていません。個別端末の処理速度や、ほかの写真に対する検出・加工の精度を測定した資料でもありません。
実装の確認箇所:src/pages/game/puzzle/rotation/index.astro。以下のコード抜粋と出力条件は、この本番実装に基づいて説明します。
仕組みを読み進めるときは、DOM操作の基礎(要素の生成と表示状態の更新)、イベントリスナーの基礎(タップやドラッグから描画へつなぐ流れ)が参考になります。
1. 内側要素の left / top による画像の表示分割
このパズルの最大の特徴は、実際に画像をN個のファイルに分割しているわけではないという点です。1つの画像を background-image として利用し、CSS で背景を持つ内側要素を N 倍の幅・高さにし、left / top の位置をずらすことで、仮想的なタイルを実現しています。
メリット: 画像の切り出し処理(Canvasでのスライス等)を待機する必要がなく、読み込みと縮小が終わるとパズルを開始できます。また、画像の解像度やアスペクト比を問わず、計算式一つでN×Nのグリッドに対応可能です。
全ピースの向きが 360° の整数倍になればクリアです。回転値は1タップごとに 90 を加えます。
function rotationCleared(pieces) {
return pieces.every(piece => piece.rotation % 360 === 0);
} 2. 360度の剰余(Modulo)を活用した状態管理
ピースが回転する際、内部的な回転状態は常に累積されていきますが、クリア判定では「向きが合っているか」のみが重要です。ここで、360を法とする剰余演算を用いることで、ユーザーが何度回転させても正しく「正位置」を判定できる設計にしています。
メリット: 「360度を超えたら0に戻す」といった複雑な条件分岐が不要になり、Array.prototype.every を用いた極めて簡潔な関数型のアプローチでクリア判定を完結させることができます。
3. Canvas API による動的な「クリア記録」の合成
クリア時に生成される記録画像は、Canvas APIを使用してクライアントサイドで動的に合成しています。元の画像の上に、半透明のオーバーレイや統計データ(タイム、タップ数)を描画し、一枚のJPEGとしてエクスポートします。
メリット: サーバーにデータを送信することなく「シェア用コンテンツ」を生成できるため、写真の合成を端末内で行い、ゲーム性を高める付加価値を提供できています。
出力の仕様と確認する点
初期角度は各ピースごとに 90°・180°・270° のいずれかで、最初から正しい向きのピースは作りません。タップすると時計回りに 90° 回り、配置の入れ替えはありません。
入力は長辺 1000px 以下に縮小します。盤面は正方形のタイルに画像を引き伸ばす CSS 表示なので、縦長・横長の写真は縦横比が変わって見える場合があります。正方形の写真だと形を比較しやすくなります。
クリア記録は写真・時間・タップ数を描いた 800×1000px の JPEG(品質指定 0.9)です。計時は1秒ごとのタイマー加算で、別タブや端末の休止中は実時間とずれる場合があります。記録画像の保存と、プレイ状態の保存は別の機能です。
