如何纯php写的贪吃蛇游戏,膜拜了

237 阅读4分钟

今天和大家分享一个用纯PHP写的贪吃蛇游戏项目!在很多人眼中,PHP主要是用于开发后端的语言,主要负责处理请求、生成响应等,但事实上,PHP不仅仅局限于“后端开发”。利用PHP,我们也能实现一些有趣的前端交互应用。接下来,我们就带着大家一步步构建出这个经典的贪吃蛇游戏。

一、游戏背景介绍

贪吃蛇(Snake)是一款经典的游戏,玩家通过控制蛇的移动来吃食物并使蛇的长度不断增长,难度随着蛇的长度增加而加大,直到蛇撞到自己或墙壁游戏结束。

使用PHP实现贪吃蛇,虽然有些挑战,但如果你愿意尝试,你会发现过程非常有趣。

二、设计思路

我们将使用PHP的命令行模式(CLI)来开发这个贪吃蛇游戏。由于PHP没有图形化的库,我们将通过字符界面模拟蛇的移动。游戏规则如下:

  • 玩家通过按键控制蛇的移动方向。
  • 每次蛇吃到食物,蛇的长度会增加。
  • 如果蛇碰到墙壁或者撞到自己的身体,游戏结束。

三、核心实现步骤

  1. 游戏地图的生成:使用二维数组表示游戏地图,空白处用空格填充,蛇的位置用“#”符号表示,食物的位置用“*”表示。
  2. 蛇的移动:根据用户的输入来控制蛇的移动方向,并实时更新游戏界面。
  3. 碰撞检测:每次蛇移动后,检查是否碰撞到墙壁或者自己的身体。
  4. 食物生成与增长:蛇吃到食物后,长度增加,并且在地图上随机生成新的食物。
  5. 游戏结束判断:当蛇撞墙或撞到自己时,游戏结束并输出得分。

四、代码实现

下面是游戏的核心代码部分,虽然是用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);
}

五、代码解析

  1. 地图生成renderMap() 函数负责渲染游戏地图,将蛇、食物和边界分别用不同的符号表示。蛇用@符号,食物用*符号,墙壁用#符号。
  2. 蛇的移动与增长updateSnake() 函数根据玩家输入的方向更新蛇的位置,每次移动后,蛇的头部会加入新位置。如果蛇吃到食物,蛇的长度会增加。
  3. 食物的生成:每次蛇吃到食物,都会在随机位置生成新的食物。
  4. 碰撞检测:通过 isGameOver() 函数判断蛇是否撞到墙壁或者自己的身体。
  5. 控制方向:玩家通过输入 wsad 控制蛇的移动方向,并使用 fopen()fgetc() 实现非阻塞地读取用户输入。

六、总结与扩展

通过这篇文章和代码示例,我们用纯PHP实现了一个简单的贪吃蛇游戏。这虽然只是个字符界面的游戏,但它展示了PHP在处理游戏逻辑上的潜力。如果你愿意继续拓展,可以考虑以下几个方向:

  • 增加关卡和难度:随着游戏的进行,增加游戏难度,比如缩短移动时间,或者增加障碍物。
  • 存储玩家分数:通过文件或数据库保存玩家的最高分,并在游戏结束时显示排行榜。
  • 网络对战:进一步挑战自己,可以使用 Swoole 或 WebSocket 来实现贪吃蛇的多人对战功能。

谁说PHP只能写后端?在这次贪吃蛇的游戏开发中,PHP一样能胜任“游戏开发”的任务。是不是觉得PHP特别强大?如果你也是PHP爱好者,不妨自己试试写一个吧,最后期待大家的膜拜!