ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

javascript贪吃蛇案例

2020-11-05 09:04:38  阅读:253  来源: 互联网

标签:style 游戏 javascript 案例 贪吃蛇 let 坐标 关节 snakeArray


初始化(){
    初始化游戏面板和游戏分数显示区
    造蛇()
    造豆()
    监听键盘()
}

造蛇(){
    循环蛇初始化长度次{
        创造蛇的新关节,每个关节都是一个div
        蛇头变红
        蛇的新关节推入数组
        蛇的新关节的左距离为上一个蛇关节左侧
        蛇的新关节展示在面板上
    }
}

造豆(){
    if(存在旧豆){
        从游戏面板上删除旧豆
    }
    创建新豆,每个豆都是一个span
    调用随机坐标(),为新豆生成出生坐标
    随机坐标(){
        面板宽度1000除以20(豆子宽20px),等分成500份
        乘以一个随机数并取整,得出一个0-500的整数
        乘以20得到一个0-1000范围内的20的整数倍,即横坐标
        纵坐标同理
        遍历蛇关节数组{
            if(和当前豆的坐标冲突){
                随机坐标();
            }
        }
    }
    为新豆赋值横纵坐标
    将新豆追加到面板中
}

监听键盘(){
    按了左键:当方向不为右,方向改为左
    按了上键:当方向不为下,方向改为上
    按了右键:当方向不为左,方向改为右
    按了下键:当方向不为上,方向改为下
    按了空格键:暂停和开始游戏效果切换
}

游戏开始(){
    清除旧定时器
    开启新定时器{
        蛇移动()
        撞自己():判断本次移动蛇是否撞到自己
        吃豆子():判断本次移动蛇是否吃到豆子
    }
}

蛇移动(){   
    获取蛇头左距离和上距离
    判断当前蛇的移动方向{
        if(对应方向上出界){
            游戏结束()
        }
        蛇身移动()
        蛇头移动
    }
    蛇身移动(){ 
        循环所有蛇身{
            后面的关节横向顶替前面的关节
            后面的关节纵向顶替前面的关节
        }    
    }
}

撞自己(){
    遍历所有蛇身{
        if(蛇头坐标与某个蛇身关节坐标冲突){
            结束游戏()
        }     
    }
}

吃豆子(){
    if(蛇头坐标和当前豆的坐标一致){
        分数++
        创建一个新的蛇关节
        新蛇关节的出生坐标就是被吃掉豆子的坐标
        新蛇关节加入到蛇的数组中
        新蛇关节展示在游戏面板中
        造豆()
    }
}

游戏结束(){
    清空定时器
    刷新页面
    展示分数
    提示游戏结束
}

游戏暂停(){
    清空定时器
}

游戏重置(){
    刷新页面
}
复制代码

布局: snake.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>贪食蛇</title>
    <link rel="stylesheet" type="text/css" href="snake.css">
    <script type="text/javascript" src="snake.js"></script>
</head>
<body>
<header>
    <article id="head_left">贪食蛇v1.0</article>
    <article id="head_right">您当前的分数为 <span id="score">0</span> 分</article>
</header>
<section id="board"></section>
<footer>
    <button class="buttons" onclick="start();">开始 [ start ]</button>
    <button class="buttons" onclick="pause();">暂停 [ pause ]</button>
    <button class="buttons" onclick="reset();">重置 [ reset ]</button>
</footer>
</body>
</html>

复制代码

样式: snake.css

/*整体:居中*/
body {width: 1000px; margin: 0 auto;}

/*计分板:调整行高、外边距*/
header { 
    height: 30px; background-color: black; color: white;
    line-height: 30px; margin: 10px auto;
}

/*游戏标题:调整左边距、忽略内边距和边框、左漂浮、文字倾斜、字间距*/
#head_left { 
    width: 700px; padding-left: 20px; box-sizing: border-box; 
    float: left; font-style: italic; letter-spacing: 10px;
}

/*计分提示:调整右内边距、忽略内边距和边框、右浮动、文字居右*/
#head_right { 
    width: 300px; padding-right: 20px; box-sizing: border-box; 
    float: right; text-align: right;
}

/*分数数字:文字加粗,下划线*/
#score { 
    color: yellow; font-weight: bold; text-decoration: underline;
}

/*游戏面板:居中、父元素设置成相对点*/
#board { 
    height: 500px; background-color: black;
    margin: 0 auto; position: relative;
}

/*豆子:显示为区块、圆角、z轴、绝对定位*/
#board span { 
    width: 20px; height: 20px; background-color: yellow;
    display: block; border-radius: 50%; 
    z-index: 0; position: absolute; 
}

/*蛇:圆角、绝对定位、z轴*/
#board div { 
    width: 20px; height: 20px; background-color: skyblue; 
    border-radius: 50%; position: absolute; z-index: 1; 
}

/*功能按钮区:内容居中*/
footer { text-align: center; }

/*功能按钮:文字颜色、外边距*/
footer .buttons{ 
    width: 150px; height: 30px;background-color: black;
    color: yellow; margin: 10px; 
}
复制代码

脚本: snake.js

let snakeArray = []; /*初始化蛇关节的数组*/
let isPause = false; /*游戏是否暂停:未暂停*/
let snakeSize = 5; /*蛇的初始长度*/
let direct = "right"; /*蛇初始方向:向右*/
let speed = 80; /*蛇移动初始速度:80*/
let score, timer, board, bean; /*游戏初始分数显示区,定时器,面板,豆*/

// 初始化(){
onload = () => {
    //     初始化游戏面板和游戏分数显示区
    board = document.querySelector("#board");
    score = document.querySelector("#score");
    //     造蛇()
    createSnake();
    //     造豆()
    createBean();
    //     监听键盘()
    keyListener();
};

// 造蛇(){
function createSnake() {
    //     循环蛇初始化长度次{
    for (let i = 0; i < snakeSize; i++) {
        //         创造蛇的新关节,每个关节都是一个div
        let snake = document.createElement("div");
        //         蛇头变红
        if (i === 0) {
            snake["style"]["backgroundColor"] = "red";
        }
        //         蛇的新关节推入数组
        snakeArray.push(snake);
        //         蛇的新关节的左距离为上一个蛇关节左侧
        snake["style"]["left"] = (snakeSize - i - 1) * 20 + "px";
        //         蛇的新关节展示在面板上
        board.appendChild(snake);
    }
}

// 造豆(){
function createBean() {
    //     if(存在旧豆){
    if (bean) {
        //     从游戏面板上删除旧豆
        board.removeChild(bean);
    }
    //     创建新豆,每个豆都是一个span
    bean = document.createElement("span");
    let x = null, y = null;
    //     调用随机坐标(),为新豆生成出生坐标
    randomXY();

    //     随机坐标(){
    function randomXY() {
//         面板宽度1000除以20(豆子宽20px),等分成500份
//         乘以一个随机数并取整,得出一个0-500的整数
//         乘以20得到一个0-1000范围内的20的整数倍,即横坐标
//         纵坐标同理
        x = parseInt("" + (Math.random() * (1000 / 20))) * 20;
        y = parseInt("" + (Math.random() * (500 / 20))) * 20;

//         遍历蛇关节数组{
        for (let i = 0; i < snakeArray.length; i++) {
            //             if(和当前豆的坐标冲突){
            if (snakeArray[i]["offsetLeft"] === x) {
                if (snakeArray[i]["offsetTop"] === y) {
//                 随机坐标();
                    randomXY();
                    break;
                }
            }
        }
    }

//     为新豆赋值横纵坐标
    bean["style"]["left"] = x + "px";
    bean["style"]["top"] = y + "px";
//     将新豆追加到面板中
    board.appendChild(bean);
}

//监听键盘
function keyListener() {
    document.onkeydown = event => {
        let oEvent = event || window.event;
        switch (oEvent.keyCode) {
            case 37 :
                //     按了左键:当方向不为右,方向改为左
                if (direct !== "right") {
                    direct = "left";
                }
                break;
            case 38 :
                //     按了上键:当方向不为下,方向改为上
                if (direct !== "down") {
                    direct = "up";
                }
                break;
            case 39 :
                //     按了右键:当方向不为左,方向改为右
                if (direct !== "left") {
                    direct = "right";
                }
                break;
            case 40 :
                //     按了下键:当方向不为上,方向改为下
                if (direct !== "up") {
                    direct = "down";
                }
                break;
            case 32 :
                //     按了空格键:暂停和开始游戏效果切换
                if (!isPause) {
                    pause();
                } else {
                    start();
                }
                isPause = !isPause;
                break;
        }
    }
}

// 游戏开始(){
function start() {
    //     清除旧定时器
    clearInterval(timer);
    //     开启新定时器{
    timer = setInterval(() => {
//     蛇移动()
        move();
//     撞自己():判断本次移动蛇是否撞到自己
        isHit();
//      吃豆子():判断本次移动蛇是否吃到豆子
        isEat();
    }, speed);
}

// 蛇移动(){
function move() {
    //     获取蛇头左距离和上距离
    let hLeft = snakeArray[0].offsetLeft;
    let hTop = snakeArray[0].offsetTop;
//     判断当前蛇的移动方向{
    switch (direct) {
        case "left":
//         if(对应方向上出界){
            if (hLeft <= 0) {
//             游戏结束()
                gameover();
                return;
            }
//         蛇身移动()
            snakeBodyMove();
//         蛇头移动
            snakeArray[0]["style"]["left"] = hLeft - 20 + "px";
            break;
        case "up":
            if (hTop <= 0) {
                gameover();
                return;
            }
            snakeBodyMove();
            snakeArray[0]["style"]["top"] = hTop - 20 + "px";
            break;
        case "right":
            if (hLeft >= 1000 - 20) {
                gameover();
                return;
            }
            snakeBodyMove();
            snakeArray[0]["style"]["left"] = hLeft + 20 + "px";
            break;
        case "down":
            if (hTop >= 500 - 20) {
                gameover();
                return;
            }
            snakeBodyMove();
            snakeArray[0]["style"]["top"] = hTop + 20 + "px";
            break;
    }

//     蛇身移动(){
    function snakeBodyMove() {
        //         循环所有蛇身{
        for (let i = snakeArray.length - 1; i > 0; i--) {
            //             后面的关节横向顶替前面的关节
            snakeArray[i]["style"]["left"] = snakeArray[i - 1]["style"]["left"];
            //             后面的关节纵向顶替前面的关节
            snakeArray[i]["style"]["top"] = snakeArray[i - 1]["style"]["top"];
        }
    }
}

/*判断本次移动是否撞到自己*/
function isHit() {
    //     遍历所有蛇身{
    for (let i = 1, j = snakeArray.length; i < j; i++) {
        //         if(蛇头坐标与某个蛇身关节坐标冲突){
        if (snakeArray[0].offsetLeft === snakeArray[i].offsetLeft) {
            if (snakeArray[0].offsetTop === snakeArray[i].offsetTop) {
                //             结束游戏()
                gameover();
                break;
            }
        }
    }
}


// 吃豆子(){
function isEat() {
    //     if(蛇头坐标和当前豆的坐标一致){
    if (snakeArray[0].offsetLeft === bean.offsetLeft) {
        if (snakeArray[0].offsetTop === bean.offsetTop) {
            //         分数++
            score.innerText = parseInt(score.innerText) + 1;
            //         创建一个新的蛇关节
            let snake = document.createElement("div");
            //         新蛇关节的出生坐标就是被吃掉豆子的坐标
            snake["style"]["left"] = bean["style"]["left"];
            snake["style"]["top"] = bean["style"]["top"];
            //         新蛇关节加入到蛇的数组中
            snakeArray.push(snake);
            //         新蛇关节展示在游戏面板中
            board.appendChild(snake);
            //         造豆()
            createBean();
        }
    }
}

// 游戏结束(){
function gameover() {
    //     清空定时器
    clearInterval(timer);
    //     刷新页面
    location.reload();
    //     提示游戏结束
    alert("game over!");
}


// 游戏暂停(){
function pause() {
    //     清空定时器
    clearInterval(timer)
}


// 游戏重置(){
function reset() {
    //     刷新页面
    location.reload();
}



标签:style,游戏,javascript,案例,贪吃蛇,let,坐标,关节,snakeArray
来源: https://www.cnblogs.com/wjlynew/p/13929816.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有