Webプロジェクトを動く状態にするのと、人々が喜んで使う製品に変えるのとでは大きな違いがある。

Test Merkezimを開発するにあたって、当初の目標はとてもシンプルでした。ユーザーが会員登録なしに認知能力を評価し、ブラウザ上で知能ゲームをプレイできる、軽快なプラットフォームを用意すること。

しかしプロジェクトが大きくなるにつれ、タスクは単に問題を表示したり、数個のゲームを作るだけではないことに気づきました。ユーザー導線、モバイル対応、スコアの安全性、ゲーム難易度、ページパフォーマンスは、ゲーム自体と同等に重要でした。

本記事では、プロジェクトを通じて直面した主な問題と、そこから得た教訓を共有します。

ユーザーをテストへ到達させるまでの手順は、できる限り少なくする

初期デザインでは、ユーザーはトップページのボタンを押し、テスト紹介ページへ移動し、再度「開始」ボタンを押し、その後名前入力画面でさらに「テストを開始」ボタンを押す必要がありました。

技術的にはこの流れは機能していました。しかしユーザーにとっては同じ操作を3回繰り返すことになります。

そこで中間の紹介ステップを削除しました。ユーザーはトップページからテスト画面へ到達すると、任意で名前を入力して直接テストを開始できます。

この変更により、シンプルな事実を再認識しました:

クリックが増えるたびに、ユーザーがプロジェクトを離れる新たな機会が生まれる。

画面が本当に必要でなければ、見た目を美しくするのではなく、完全に削除する方が正しい解決策となる場合があります。

PHPとVanilla JavaScriptを選んだ理由

本プロジェクトは共有サーバーで動作する軽量な構成を前提としています。そのため、大規模なフレームワークや必須のビルドプロセスは避けました。

全体の構成は次のようになりました:

  • サーバーサイド:PHP
  • ゲームロジック:Vanilla JavaScript
  • 共通ヘッダー、フッター、サウンド、リーダーボードコンポーネント:PHPパーツ
  • スコア・プレイ回数データ用:サーバーサイドAPI
  • ページ固有:HTML、CSS、JavaScript

このアプローチの最大の利点はデプロイの容易さです。更新されたファイルを直接サーバーへアップロードするだけで、依存関係のインストールは必要ありません。

欠点は、共通コンポーネントを適切に切り出さないと、似たコードが各ゲームで重複し始める点です。そのため、本当に共通する部分のみを中央ファイルへ移動し、ゲーム固有の仕組みはそのまま各ページに残しました。

知能ゲームは本質的に小さな状態機械である

ゲーム開発ではビジュアルデザインに集中しがちですが、本当の難しさはゲームの全状態を正しく管理することにあります:

  • ゲーム開始前にどのボタンが有効か?
  • 無効な操作はどのように扱うか?
  • アンドゥ操作はスコアや手数に影響するか?
  • ページ再読み込み時にプレイヤーは中断したところから再開できるか?
  • ゲーム終了後に新たな入力はブロックされるか?
  • タッチ操作とマウス操作で同じ振る舞いをするか?

例えば「線つなぎパズル」では、プレイヤーはすべてのセルを1本の連続した線で埋め、番号付きの点を正しい順序で通る必要があります。

デスクトップではマウスボタンを長押しし続けるのが疲れるため、同じ行または列の離れたセルをクリックした際に、間の有効セルを自動で埋める機能を追加しました。ルール自体は変わりませんが、操作性が大幅に向上しました。

この小さな変更により、難易度を下げずに操作の摩擦を低減できました。

難易度は盤面サイズだけで決まらない

当初はレベルが上がるにつれて番号付きの点の数を減らしていました。ヒントが少ないほど自動的に難しくなると考えていたからです。

しかし点の数が多い場合も、経路をより多くの強制チェックポイントに結びつけるため、一部の問題では密集した配置を難しくすることがあります。

そこで線形システムではなく、複合的な仕組みを採用しました:

  • 盤面サイズは5×5から8×8まで拡大
  • 同じ盤面サイズ内で点の密度を上下に変動
  • 上級ステージでは3〜9の密度を混在
  • 7ステージごとに全密度パターンを1周
  • 同じ点数が連続しないように制限

これにより、プレイヤーは次のステージでどのような構成が出現するかを予測できなくなります。手続き的生成では単なるランダム性ではなく、制御された多様性こそがバランスの取れた結果をもたらします。

クライアントから送信されるスコアは信頼できない

ブラウザベースのゲームでは、ゲームロジック全体がユーザーから閲覧・改変可能です。そのため、JavaScriptが送信したスコアのみをそのまま受け入れるのは安全ではありません。

サーバーサイドで以下の検証を実装することが重要になりました:

  • ゲームIDをホワイトリストで検証
  • ゲームごとに許可された難易度値を確認
  • 各ゲームに妥当なスコア範囲を設定
  • 非現実的なクリア時間を拒否
  • ユーザーまたはIP単位で送信回数を制限
  • リーダーボード登録前にエントリをサニタイズ

カジュアルゲームプラットフォームでは、全ゲームをサーバー上で再シミュレーションするのは過剰に複雑です。しかし、低コストの検証をいくつか追加するだけで、自動スコア不正の大部分を防げます。

ここでの基本原則は明確です:

クライアントはユーザー体験を管理し、サーバーはデータの受入可否を決定する。

モバイル体験は後付けの機能であってはならない

ゲームの大部分がスマートフォンでプレイされるため、デスクトップデザインを単に縮小するだけでは不十分でした。

モバイル表示では特に以下の点を個別に考慮する必要がありました:

  • ゲーム領域を画面幅に合わせてスケーリング
  • 操作ボタンや残り時間表示が操作エリアを妨げない
  • タッチターゲットを十分に大きくする
  • テキストとアイコンを整列させる
  • ドロップダウンメニューが画面外へはみ出さない
  • スクロール操作とゲーム操作が競合しない

レスポンシブデザインは単にwidth: 100%を使うことではありません。コンテンツの表示順序や、ユーザーの指が届く位置も考慮する必要があります。

パフォーマンス向上に大規模なインフラは必ずしも必要ない

プロジェクトのパフォーマンス面で実施したシンプルな施策は以下の通りです:

  • フォントを外部サービスではなくローカルサーバーから読み込む
  • 大容量画像をWebP形式に変換
  • 画面下部の画像を遅延読み込み
  • 共通CSSファイルを最小限に抑える
  • 不要なJavaScriptライブラリを避ける
  • 画像にwidth・height属性を明示
  • 初回表示に不要なリソースを後回しにする

これらの最適化はそれぞれ単独では小さく見えますが、モバイル回線では累積効果が非常に顕著になります。

SEOとユーザー体験は切り離せない

検索エンジン向けにコンテンツを作成する際、同じ情報を異なるボックスで繰り返し表示してしまうのはよくある誤りです。

より健全なアプローチは次の通りでした:

  • 各ページに1つの明確で説明的なメイン見出しを設ける
  • ページが検索意図に直接答える
  • 表示コンテンツと構造化データを一致させる
  • 類似ページ間で見出しの一貫性を保つ
  • ユーザーを不要な紹介画面で待たせない
  • ゲーム下部でルールと仕組みを実際に説明する

現在、プロジェクトは会員登録不要のIQテスト、即時結果表示、異なるスキルを対象としたブラウザベースの知能ゲームを提供しています。

オンライン検査は専門的・臨床的評価の代替にはならないことを明記することも、信頼できる製品コミュニケーションの重要な一部です。

本プロジェクトから得た主な教訓

開発を通じて学んだ最も重要な点を以下にまとめます:

  1. 機能するユーザー導線が、必ずしも優れたユーザー導線とは限らない。
  2. ランダム生成を制御せずに放置すると、バランスの取れた難易度は生まれない。
  3. モバイル操作はデスクトップ操作とは別に設計する必要がある。
  4. クライアントから送信されるスコアは一切信頼してはならない。
  5. 小さなパフォーマンス改善の積み重ねが大きな差を生む。
  6. SEO向けコンテンツがユーザーに実質的な回答を提供しなければ、長くても意味がない。
  7. プレイヤーをゲームに留めるのは難易度だけでなく、常に変化する体験である。

プロジェクトは今後も、新たなゲームメカニクス、よりバランスの取れたスコアリングシステム、さらなるアクセシビリティ向上に取り組んでいきます。

ブラウザベースのゲームにおいて、ゲーム状態と手続き的難易度をどのように管理していますか?同様のプロジェクトで採用しているアプローチを、コメントでぜひお聞かせください。