猫の手ツール

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秒ごとのタイマー加算で、別タブや端末の休止中は実時間とずれる場合があります。記録画像の保存と、プレイ状態の保存は別の機能です。