貪吃蛇通常由前端 Canvas/JS 實現。本文展示一種**純 PHP 後端渲染**的另類方案:每幀由 PHP GD 繪製圖片,前端 `` 輪詢刷新,鍵盤控制通過超鏈接傳遞方向參數。這不具備生產實用性,但極佳地展示了 PHP GD 動態繪圖、Session 狀態管理、無狀態 HTTP 模擬遊戲循環的技術細節。
'down','down'=>'up','left'=>'right','right'=>'left'];
if (!isset($_SESSION['con']) || $_SESSION['con'] !== $opposite[$dir]) {
$_SESSION['con'] = $dir;
}
}
}
?>
控制
分數:= $_SESSION['count'] ?? 0 ?>
0) $_SESSION['ud'] -= $step; else $_SESSION['ud'] = 0; break;
case 'down': if ($_SESSION['ud'] < $H-$step) $_SESSION['ud'] += $step; else $_SESSION['ud'] = $H-$step; break;
case 'left': if ($_SESSION['lr'] > 0) $_SESSION['lr'] -= $step; else $_SESSION['lr'] = 0; break;
case 'right': if ($_SESSION['lr'] < $W-$step) $_SESSION['lr'] += $step; else $_SESSION['lr'] = $W-$step; break;
}
// 吃食物判定
if (abs($_SESSION['lr'] - $_SESSION['food_x']) < $grid && abs($_SESSION['ud'] - $_SESSION['food_y']) < $grid) {
$_SESSION['count'] = ($_SESSION['count'] ?? 0) + 1;
// 重新生成食物(避免生成在蛇身上,簡化略過)
$_SESSION['food_x'] = rand(0, $cols-1) * $grid;
$_SESSION['food_y'] = rand(0, $rows-1) * $grid;
}
// 繪製蛇身(簡化:只畫頭和按長度延伸的幾節,無真正身體隊列)
$len = ($_SESSION['count'] ?? 0) + 1; // 身長 = 分數+1
for ($i = 0; $i < $len; $i++) {
$segX = $_SESSION['lr'];
$segY = $_SESSION['ud'];
// 簡單反向延伸(實際需隊列存儲歷史座標)
switch ($dir) {
case 'up': $segY += $i * $step; break;
case 'down': $segY -= $i * $step; break;
case 'left': $segX += $i * $step; break;
case 'right': $segX -= $i * $step; break;
}
// 邊界保護
$segX = max(0, min($W-$grid, $segX));
$segY = max(0, min($H-$grid, $segY));
imagerectangle($img, $segX, $segY, $segX+$grid, $segY+$grid, $snakeColor);
}
// 輸出
imagejpeg($img, null, 80);
imagedestroy($img);
PHP 貪吃蛇
// 在 tcs.php 中用數組存儲身體座標隊列
if (!isset($_SESSION['snake'])) {
$_SESSION['snake'] = [[$_SESSION['lr'], $_SESSION['ud']]]; // 初始只有一節
}
// 移動:頭部新座標入隊,尾部出隊(未吃食物時)
$head = [$_SESSION['lr'], $_SESSION['ud']];
array_unshift($_SESSION['snake'], $head);
// 吃食物判定
$ate = ($head[0] == $_SESSION['food_x'] && $head[1] == $_SESSION['food_y']);
if (!$ate) {
array_pop($_SESSION['snake']); // 移除尾部
} else {
$_SESSION['count']++;
// 重生食物...
}
// 繪製:遍歷 $_SESSION['snake'] 畫每一節
foreach ($_SESSION['snake'] as $seg) {
imagerectangle($img, $seg[0], $seg[1], $seg[0]+$grid, $seg[1]+$grid, $snakeColor);
}
// 撞牆/撞自己判定
if ($head[0] < 0 || $head[0] >= $W || $head[1] < 0 || $head[1] >= $H) { /* Game Over */ }
foreach (array_slice($_SESSION['snake'], 1) as $seg) {
if ($seg[0] == $head[0] && $seg[1] == $head[1]) { /* Game Over */ }
}
| 層面 | 原始方案 | 現代方案 |
|---|---|---|
| 渲染 | PHP GD → JPEG → ` | 前端 Canvas/WebGL + requestAnimationFrame |
| 通信 | 超鏈接 + Session + Meta Refresh | WebSocket / Server-Sent Events / HTTP 長輪詢 |
| 狀態存儲 | PHP Session (文件鎖) | Redis (Pub/Sub 廣播) + 內存數組 |
| 邏輯權威 | 後端每幀計算 | 後端權威驗證 + 前端預測渲染 (Client-side prediction) |
| 多玩家 | 不可行 | 房間模式、狀態同步、延遲補償 |
這個「PHP 版貪吃蛇」是一個極佳的**教學級案例**,涵蓋:
雖不具備實用價值,但通過動手實現,能深刻理解「遊戲循環、狀態同步、渲染管線、網絡模型」等核心概念,為後續學習 Node.js/Swoole/WebSocket 實時遊戲服務器打下堅實基礎。