今天和大家分享一个用纯PHP写的贪吃蛇游戏项目!在很多人眼中,PHP主要是用于开发后端的语言,主要负责处理请求、生成响应等,但事实上,PHP不仅仅局限于“后端开发”。利用PHP,我们也能实现一些有趣的前端交互应用。接下来,我们就带着大家一步步构建出这个经典的贪吃蛇游戏。
一、游戏背景介绍
贪吃蛇(Snake)是一款经典的游戏,玩家通过控制蛇的移动来吃食物并使蛇的长度不断增长,难度随着蛇的长度增加而加大,直到蛇撞到自己或墙壁游戏结束。
使用PHP实现贪吃蛇,虽然有些挑战,但如果你愿意尝试,你会发现过程非常有趣。
二、设计思路
我们将使用PHP的命令行模式(CLI)来开发这个贪吃蛇游戏。由于PHP没有图形化的库,我们将通过字符界面模拟蛇的移动。游戏规则如下:
- 玩家通过按键控制蛇的移动方向。
- 每次蛇吃到食物,蛇的长度会增加。
- 如果蛇碰到墙壁或者撞到自己的身体,游戏结束。
三、核心实现步骤
- 游戏地图的生成:使用二维数组表示游戏地图,空白处用空格填充,蛇的位置用“#”符号表示,食物的位置用“*”表示。
- 蛇的移动:根据用户的输入来控制蛇的移动方向,并实时更新游戏界面。
- 碰撞检测:每次蛇移动后,检查是否碰撞到墙壁或者自己的身体。
- 食物生成与增长:蛇吃到食物后,长度增加,并且在地图上随机生成新的食物。
- 游戏结束判断:当蛇撞墙或撞到自己时,游戏结束并输出得分。
四、代码实现
下面是游戏的核心代码部分,虽然是用PHP编写,但你会发现逻辑与其他语言并无太大差异。
<?php
// 地图宽度和高度
define('MAP_WIDTH', 20);
define('MAP_HEIGHT', 10);
// 控制蛇的方向,上下左右
$directions = [
'UP' => [-1, 0],
'DOWN' => [1, 0],
'LEFT' => [0, -1],
'RIGHT' => [0, 1],
];
// 初始化蛇的初始位置、长度和方向
$snake = [
['x' => 5, 'y' => 5],
];
$direction = 'RIGHT'; // 初始方向向右
$food = ['x' => rand(1, MAP_HEIGHT - 2), 'y' => rand(1, MAP_WIDTH - 2)]; // 随机生成食物
$score = 0; // 得分
// 渲染游戏地图
function renderMap($snake, $food) {
for ($i = 0; $i < MAP_HEIGHT; $i++) {
for ($j = 0; $j < MAP_WIDTH; $j++) {
if ($i === 0 || $i === MAP_HEIGHT - 1 || $j === 0 || $j === MAP_WIDTH - 1) {
echo '#'; // 边界
} elseif ($i == $food['x'] && $j == $food['y']) {
echo '*'; // 食物
} else {
$isSnake = false;
foreach ($snake as $segment) {
if ($segment['x'] == $i && $segment['y'] == $j) {
echo '@'; // 蛇的身体
$isSnake = true;
break;
}
}
if (!$isSnake) {
echo ' '; // 空白
}
}
}
echo PHP_EOL;
}
echo "Score: $score\n";
}
// 判断是否碰到墙壁或自己
function isGameOver($snake) {
$head = $snake[0];
// 判断是否撞到墙壁
if ($head['x'] <= 0 || $head['x'] >= MAP_HEIGHT - 1 || $head['y'] <= 0 || $head['y'] >= MAP_WIDTH - 1) {
return true;
}
// 判断是否撞到自己
foreach (array_slice($snake, 1) as $segment) {
if ($segment['x'] == $head['x'] && $segment['y'] == $head['y']) {
return true;
}
}
return false;
}
// 更新蛇的状态
function updateSnake(&$snake, $direction) {
global $directions;
$head = $snake[0];
$newHead = [
'x' => $head['x'] + $directions[$direction][0],
'y' => $head['y'] + $directions[$direction][1],
];
array_unshift($snake, $newHead); // 在蛇头添加新位置
}
// 检查是否吃到食物
function checkFood(&$snake, &$food, &$score) {
$head = $snake[0];
if ($head['x'] == $food['x'] && $head['y'] == $food['y']) {
$food = ['x' => rand(1, MAP_HEIGHT - 2), 'y' => rand(1, MAP_WIDTH - 2)]; // 生成新食物
$score++;
} else {
array_pop($snake); // 如果没有吃到食物,蛇就会缩短
}
}
// 处理用户输入方向
function changeDirection($input, $currentDirection) {
if ($input == 'w' && $currentDirection != 'DOWN') return 'UP';
if ($input == 's' && $currentDirection != 'UP') return 'DOWN';
if ($input == 'a' && $currentDirection != 'RIGHT') return 'LEFT';
if ($input == 'd' && $currentDirection != 'LEFT') return 'RIGHT';
return $currentDirection;
}
// 主循环
while (true) {
// 清屏
system('clear');
// 渲染地图
renderMap($snake, $food);
// 判断游戏是否结束
if (isGameOver($snake)) {
echo "Game Over! Final Score: $score\n";
break;
}
// 等待用户输入方向
$stdin = fopen('php://stdin', 'r');
stream_set_blocking($stdin, false); // 非阻塞模式读取
$input = strtolower(fgetc($stdin));
// 更新蛇的方向
$direction = changeDirection($input, $direction);
// 更新蛇的位置
updateSnake($snake, $direction);
// 检查是否吃到食物
checkFood($snake, $food, $score);
// 延迟,控制游戏速度
usleep(200000);
}
五、代码解析
- 地图生成:
renderMap()
函数负责渲染游戏地图,将蛇、食物和边界分别用不同的符号表示。蛇用@
符号,食物用*
符号,墙壁用#
符号。 - 蛇的移动与增长:
updateSnake()
函数根据玩家输入的方向更新蛇的位置,每次移动后,蛇的头部会加入新位置。如果蛇吃到食物,蛇的长度会增加。 - 食物的生成:每次蛇吃到食物,都会在随机位置生成新的食物。
- 碰撞检测:通过
isGameOver()
函数判断蛇是否撞到墙壁或者自己的身体。 - 控制方向:玩家通过输入
w
、s
、a
、d
控制蛇的移动方向,并使用fopen()
和fgetc()
实现非阻塞地读取用户输入。
六、总结与扩展
通过这篇文章和代码示例,我们用纯PHP实现了一个简单的贪吃蛇游戏。这虽然只是个字符界面的游戏,但它展示了PHP在处理游戏逻辑上的潜力。如果你愿意继续拓展,可以考虑以下几个方向:
- 增加关卡和难度:随着游戏的进行,增加游戏难度,比如缩短移动时间,或者增加障碍物。
- 存储玩家分数:通过文件或数据库保存玩家的最高分,并在游戏结束时显示排行榜。
- 网络对战:进一步挑战自己,可以使用 Swoole 或 WebSocket 来实现贪吃蛇的多人对战功能。
谁说PHP只能写后端?在这次贪吃蛇的游戏开发中,PHP一样能胜任“游戏开发”的任务。是不是觉得PHP特别强大?如果你也是PHP爱好者,不妨自己试试写一个吧,最后期待大家的膜拜!