導入
Webアプリケーション開発において、HTTPはステートレス(状態を保持しない)なプロトコルです。そのため、複数ステップにわたる処理や、ゲームのような進行状況が必要なアプリケーションでは、サーバー側で状態を保持する仕組みが不可欠です。今回は、PHPのセッション管理機能を用いて、ブラックジャックという「状態遷移」を伴うプログラムを実装し、その仕組みと注意点を解説します。
基礎知識
PHPのセッション($_SESSION)は、ユーザーごとに固有のIDを発行し、サーバー上のストレージにデータを保存する仕組みです。これにより、ページ遷移を跨いで変数の値を保持できます。ゲーム開発においては、山札の状態や手札の情報をセッションに保存することで、ユーザーが「ヒット」や「スタンド」を選択するたびに、ゲームの進行状況を更新・維持することが可能になります。
実装/解決策
状態管理を行う際のポイントは、「データの初期化」「状態の更新」「判定」の3フェーズを明確に分けることです。
1. データの初期化: ゲーム開始時に山札(Deck)を生成し、シャッフルします。
2. 状態の更新: ユーザーのGETリクエスト(Hit/Stand)を受け取り、山札からカードを引く(array_shift)処理を行います。
3. 判定: 手札の合計値を計算し、バースト(21超え)や勝敗を判定します。
サンプルプログラム
以下は、ゲームのロジック部分を抽出した実装例です。
10) {
$total += 10;
} elseif ($num === 1) {
$ace_count++;
$total += 1;
} else {
$total += $num;
}
}
// エースの特殊処理:バーストしない範囲で10を加算(11として扱う)
for ($i = 0; $i < $ace_count; $i++) {
if ($total + 10 <= 21) {
$total += 10;
}
}
return $total;
}
// ゲームの状態管理
if (!isset($_SESSION['cards']) || isset($_GET['reset'])) {
// 山札の初期化
$deck = [];
foreach (['spade', 'heart', 'diamond', 'club'] as $suit) {
for ($i = 1; $i <= 13; $i++) {
$deck[] = ['num' => $i, ‘suit’ => $suit];
}
}
shuffle($deck);
$_SESSION[‘cards’] = $deck;
$_SESSION[‘player’] = [array_shift($_SESSION[‘cards’]), array_shift($_SESSION[‘cards’])];
}
// ヒット処理
if (isset($_GET[‘hit’])) {
$_SESSION[‘player’][] = array_shift($_SESSION[‘cards’]);
}
$player_total = sum_up_hands($_SESSION[‘player’]);
?>
応用・注意点
実務レベルでこのような状態管理を行う際は、以下の点に注意してください。
1. セッションの肥大化を防ぐ:
セッションに巨大なオブジェクトや配列を格納しすぎると、サーバーのメモリを圧迫します。必要なデータ(IDや最小限のフラグ)だけを保持し、計算可能なデータは都度算出する設計が推奨されます。
2. 不正な操作への耐性:
今回のサンプルはURLパラメータ(?hit)で操作していますが、実際のアプリケーションではCSRF対策としてトークンを使用したり、POSTリクエストを利用して意図しない操作を防ぐ実装が必要です。
3. セッションの破棄:
ゲーム終了やログアウト時には、session_destroy()を使用して不要なデータを確実に破棄することで、セキュリティ向上とリソース節約に繋がります。
このように、セッションを活用した状態管理はWebアプリ開発の基本です。ぜひこのコードをベースに、さらに複雑なルールやUIの実装に挑戦してみてください。