鱼C论坛

 找回密码
 立即注册
查看: 134|回复: 8

[技术交流] 新春版贪吃蛇大冒险!祝你蛇年大吉!

[复制链接]
回帖奖励 34 鱼币 回复本帖可获得 1 鱼币奖励! 每人限 2 次(中奖概率 90%)
发表于 2025-2-7 19:13:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 中英文泡椒 于 2025-2-10 19:12 编辑

贪吃蛇大家都玩过,新春版贪吃蛇大家体验过吗

项目介绍

贪吃蛇.png

传统贪吃蛇游戏玩家通过控制蛇的移动方向来吃食物,食物越多,蛇的长度越长。

游戏的目标是尽可能获得更高的分数,而我们的新春版贪吃蛇,

通过调用 placeFood 方法,生成随机位置的食物并从 fishc 字符串中取出一个汉字作为食物的字符。

每次蛇吃到食物时,从这个字符串中取出一个汉字并显示在蛇的身体上。

恭喜.png

这不仅是一款经典的贪吃蛇游戏,还能通过在一步步吃的过程中,把祝福吃下去,

寓意“贪吃蛇”逐渐吞噬好运,寓意“越吃越有福气”。


完整代码
<!DOCTYPE html>
<html lang="zh">

<head>
    <meta charset="UTF-8" />
    <title>贪吃蛇</title>
    <style>
        body {
            text-align: center;
            margin-top: 50px;
            font-family: Arial, sans-serif;
        }

        #gameCanvas {
            border: 2px solid #333;
            background-color: #fafafa;
            display: block;
            margin: 0 auto;
        }

        #score {
            font-size: 1.2em;
            margin-bottom: 10px;
        }
    </style>
</head>

<body>
    <h1>贪吃蛇</h1>
    <div id="score">得分:<span id="scoreValue">0</span></div>
    <canvas id="gameCanvas" width="400" height="400"></canvas>

    <script>
        // 1. 获取画布和上下文
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');
        const scoreValue = document.getElementById('scoreValue');

        // 2. 基本参数
        const gridSize = 20;                     // 每格像素
        const tileCount = canvas.width / gridSize;
        let score = 0;
        let gameOver = false;

        // 3. 包含汉字的字符串
        const fishc = "恭贺新春大吉大利蛇年发大财";
        let fishcIndex = 0;   // 用于依次取汉字

        // 4. 蛇的初始状态(数组第0项是蛇头)
        //    蛇的每个身体段仅存坐标 (x, y),不存汉字
        //    汉字将统一保存在 eatenChars 里,按吃到的先后顺序排列
        let snake = [
            { x: 10, y: 10 }  // 仅有一个头部,坐标可自行调整
        ];

        // 5. 用于存储“吃到的汉字”的数组
        //    eatenChars[0] 表示最早吃到的汉字,eatenChars[1] 表示第二次吃到的汉字...
        let eatenChars = [];

        // 6. 食物对象(带有汉字)
        let food = { x: 0, y: 0, char: '' };

        // 7. 初始方向:向右(dx=1, dy=0)
        let dx = 1;
        let dy = 0;

        // 8. 放置食物 + 取汉字
        function placeFood() {
            food.x = Math.floor(Math.random() * tileCount);
            food.y = Math.floor(Math.random() * tileCount);
            food.char = fishc[fishcIndex];
            fishcIndex = (fishcIndex + 1) % fishc.length; // 循环取
        }
        placeFood(); // 游戏开始先放一次食物

        // 9. 游戏主循环
        function gameLoop() {
            if (gameOver) return;
            update();
            draw();
        }

        // 10. 更新
        function update() {
            // 先计算新头部坐标
            const newHead = {
                x: snake[0].x + dx,
                y: snake[0].y + dy
            };

            // (1) 撞墙检测
            if (newHead.x < 0 || newHead.x >= tileCount ||
                newHead.y < 0 || newHead.y >= tileCount) {
                endGame();
                return;
            }

            // (2) 撞到自己
            for (let i = 0; i < snake.length; i++) {
                if (snake[i].x === newHead.x && snake[i].y === newHead.y) {
                    endGame();
                    return;
                }
            }

            // (3) 在头部插入新头
            snake.unshift(newHead);

            // (4) 判断是否吃到食物
            if (newHead.x === food.x && newHead.y === food.y) {
                // 吃到后分数加1,且“蛇长度+1”(本回合不 pop)
                score++;
                scoreValue.textContent = score;

                // 将本次食物的汉字加入到 eatenChars 的“队尾”
                // 表示这是最新吃到的汉字
                eatenChars.push(food.char);

                // 生成下一个食物
                placeFood();
            } else {
                // 没吃到,就移除尾巴(保持长度不变)
                snake.pop();
            }
        }

        // 11. 结束游戏
        function endGame() {
            gameOver = true;
            alert(`游戏结束!得分:${score}`);
        }

        // 12. 绘制
        function draw() {
            // 清空画布
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            // 设置绘制文字属性
            ctx.font = "16px sans-serif";
            ctx.textBaseline = "top";

            // (A) 先画蛇
            //     snake[0] 是头部,不显示汉字
            //     snake[1] ~ snake[n-1] 依次显示 eatenChars[0] ~ eatenChars[n-2]
            //     即:第一个吃到的汉字放在蛇的第1节位置,第二个吃到的放第2节位置……
            for (let i = 0; i < snake.length; i++) {
                // 画身体方块
                ctx.fillStyle = "#008000"; // 绿色
                ctx.fillRect(
                    snake[i].x * gridSize,
                    snake[i].y * gridSize,
                    gridSize,
                    gridSize
                );

                // 从第1节开始,若存在对应的 eatenChars[i-1] 则显示
                if (i > 0) {
                    // i-1 对应 eatenChars 的下标
                    let charIndex = i - 1;
                    if (charIndex < eatenChars.length) {
                        ctx.fillStyle = "#FFFFFF"; // 白色文字
                        ctx.fillText(
                            eatenChars[charIndex],
                            snake[i].x * gridSize + 2,
                            snake[i].y * gridSize + 2
                        );
                    }
                }
            }

            // (B) 再画食物:红底黑字
            ctx.fillStyle = "#FF0000";
            ctx.fillRect(food.x * gridSize, food.y * gridSize, gridSize, gridSize);
            ctx.fillStyle = "#000000";
            ctx.fillText(
                food.char,
                food.x * gridSize + 2,
                food.y * gridSize + 2
            );
        }

        // 13. 方向键控制
        document.addEventListener('keydown', function (e) {
            switch (e.key) {
                case 'ArrowLeft':
                    if (dx !== 1) {
                        dx = -1;
                        dy = 0;
                    }
                    break;
                case 'ArrowUp':
                    if (dy !== 1) {
                        dx = 0;
                        dy = -1;
                    }
                    break;
                case 'ArrowRight':
                    if (dx !== -1) {
                        dx = 1;
                        dy = 0;
                    }
                    break;
                case 'ArrowDown':
                    if (dy !== -1) {
                        dx = 0;
                        dy = 1;
                    }
                    break;
            }
        });

        // 14. 启动游戏循环
        setInterval(gameLoop, 120);
    </script>
</body>

</html>

大家有改进的建议可以评论一下,求评分



@cjjJasonchen @yinda_peng @python爱好者. @鱼小二 @学习编程中的Ben @唯有无奈 @sfqxx @小凯2013 @KeyError @元豪

评分

参与人数 5荣誉 +17 鱼币 +12 贡献 +13 收起 理由
python爱好者. + 5 + 5 + 3 鱼C有你更精彩^_^
sfqxx + 5 + 3 吞噬改为积攒
smallwh + 3 + 3 + 3 鱼C有你更精彩^_^
鱼小二 + 2 + 2 + 2 感谢楼主无私奉献!
小甲鱼的二师兄 + 2 + 2 + 2 鱼C有你更精彩^_^

查看全部评分

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2025-2-10 19:12:28 | 显示全部楼层

回帖奖励 +1 鱼币

这个不错!顶上去!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-2-12 00:10:23 | 显示全部楼层

回帖奖励 +1 鱼币

寓意“贪吃蛇”逐渐吞噬好运,寓意“越吃越有福气”。

应该改为“积攒”好运
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-2-12 09:03:07 | 显示全部楼层

回帖奖励 +1 鱼币

这个不错!顶上去!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-2-12 09:23:58 | 显示全部楼层
鱼小二 发表于 2025-2-12 00:10
应该改为“积攒”好运

好的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-2-13 11:27:45 | 显示全部楼层

回帖奖励 +1 鱼币

挺有意思的,顶一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 7 天前 | 显示全部楼层

回帖奖励 +1 鱼币

好欸
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 6 天前 | 显示全部楼层

回帖奖励 +1 鱼币


还没改,快点改
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 09:54 | 显示全部楼层

回帖奖励 +1 鱼币

支持
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-2-23 01:03

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表