原生js实现简易版消消乐

效果图

在这里插入图片描述

整体思路

在这里插入图片描述

文件结构

在这里插入图片描述

html结构
<div id="pop_star">
    <div id="targetScore">目标分数:1500</div>
    <div id="nowScore">当前分数:0</div>
    <div id="selectScore">0块0分</div>
</div>
初始化变量
var table;
var squareWidth = 50;//每个小方块的宽度
var boderWidth = 10;//横竖各有多少个小方块
var squareSet = [];//存放小方块,小方块的集合,二维数组
var choose = [];//被选中的小方块的集合
var timer;
var baseScore = 5;//基础分
var stepScore = 10;//递增分
var select_score = document.getElementById('selectScore');//几块几分
var nowScore = document.getElementById('nowScore');//当前分数
var totalScore = 0;//总分数
var targetScore = 1500;//目标分数
var flag=true;// 对点击事件加速,消除过程中不允许有其他的移入和点击操作
var tempSquare = null;//消除过程中如果输入移入其他方块,进行记录
function init() {
    table = document.getElementById('pop_star');
    for (var i = 0; i < boderWidth; i++) {
        squareSet[i] = new Array();
        for (var j = 0; j < boderWidth; j++) {
            var square = createSquare(Math.floor(Math.random() * 5), i, j);//创建小方块
            square.onmousemove = function () {//鼠标悬停事件,鼠标放在某个小方块上时触发
                mouseOver(this);
            }
            square.onclick = function () {//鼠标点击事件
                if(!flag||choose.length==0){//处于被锁定状态时不允许有操作
                    return;
                }
                flag=false;//开始执行点击事件了,此时不能再执行任何点击事件
                tempSquare = null;
                //加分数
                var score = 0;
                for (var i = 0; i < choose.length; i++) {
                    score += baseScore + i * stepScore;
                }
                totalScore += score;
                nowScore.innerHTML = "当前分数:" + totalScore;
                //消灭星星
                for (var i = 0; i < choose.length; i++) {
                    (function (i) {
                        setTimeout(function () {
                            squareSet[choose[i].row][choose[i].col] = null;
                            table.removeChild(choose[i]);
                        }, i * 100)
                    })(i)
                }
                //移动
                setTimeout(function () {
                    move();
                    //判断是否结束
                    setTimeout(function () {
                        var is = isFinish();
                        if(is){
                            if(totalScore>=targetScore){
                                alert('恭喜获胜');
                            }
                            else{
                                alert('游戏失败')
                            }
                        }
                        else{
                            choose=[];
                            flag=true;// 在所有动作都执行完成之后释放锁
                            mouseOver(tempSquare);
                        }
                    }, 300 + choose.length * 150)
                }, choose.length * 100);
            }
            squareSet[i][j] = square;
            table.appendChild(square);
        }
    }
    refresh();
}
window.onload = function () {
    init();
}
创建小方块
function createSquare(value, row, col) {
    var temp = document.createElement('div');
    temp.style.width = squareWidth + 'px';
    temp.style.height = squareWidth + 'px';
    temp.style.background = 'red';
    temp.style.display = 'inline-block';//使小方块能够横向排列
    temp.style.position = "absolute";
    temp.style.borderRadius = '12px';
    temp.style.boxSizing = "border-box";
    temp.num = value;//颜色
    temp.row = row;
    temp.col = col;
    return temp;
}
渲染小方块
function refresh() {
    for (var i = 0; i < squareSet.length; i++) {
        for (var j = 0; j < squareSet[i].length; j++) {
            if (squareSet[i][j] == null) { // 小格子为空
                continue;
            }
            // 设置小方格属性
            squareSet[i][j].row = i;
            squareSet[i][j].col = j;
            squareSet[i][j].style.transition = "left 0.3s, bottom 0.3s";
            squareSet[i][j].style.left = squareSet[i][j].col * squareWidth + "px";
            squareSet[i][j].style.bottom = squareSet[i][j].row * squareWidth + "px";
            squareSet[i][j].style.backgroundImage = "url('./pic/" + squareSet[i][j].num + ".png')";
            squareSet[i][j].style.backgroundSize = "cover";
            squareSet[i][j].style.transform = "scale(0.95)";
        }
    }
}
鼠标悬停事件
function mouseOver(obj) {//obj代表的是小方块
    if(!flag){
        tempSquare = obj;
        return;
    }
    goBack();
    choose = [];
    checkLinked(obj, choose);
    //只有一个小方块无法被消灭
    if (choose.length <= 1) {
        choose = [];
        return;
    }
    flicker(choose);
    selectScore();//计算分数
}
方块闪烁(放大缩小)
function flicker(arr) {
    var num = 0;
    timer = setInterval(function () {
        for (var i = 0; i < arr.length; i++) { // 循环是为了不断的放大缩小(0.95 0.85)
            arr[i].style.border = "3px solid #BFEFFF";
            arr[i].style.transform = "scale(" + (0.90 + 0.05 * Math.pow(-1, num)) + ")";
        }
        num++;
    }, 300)
}
鼠标移走后,方块还原大小
function goBack() {
    if (timer != null) {
        clearInterval(timer);
    }
    for (var i = 0; i < squareSet.length; i++) {
        for (var j = 0; j < squareSet[i].length; j++) {
            if (squareSet[i][j] == null) {
                continue;
            }
            squareSet[i][j].style.border = "0px solid #BFEFFF";
            squareSet[i][j].style.transform = "scale(0.95)";
        }
    }
}
递归查找周围相同颜色的方块
function checkLinked(square, arr) {
    if (square == null) {
        return;
    }
    arr.push(square);
    //向左
    /* 
   1.不能是最左边的
   2.左边得存在一个小块
   3.左边的小方块和当前的小方块颜色相同
   4.左边的小方块没有被收录进数组
   */
    if (square.col > 0 && squareSet[square.row][square.col - 1] && squareSet[square.row][square.col - 1].num == square.num && arr.indexOf(squareSet[square.row][square.col - 1]) == -1) {
        checkLinked(squareSet[square.row][square.col - 1], arr);
    }
    //向右
    if (square.col < boderWidth - 1 && squareSet[square.row][square.col + 1] && squareSet[square.row][square.col + 1].num == square.num && arr.indexOf(squareSet[square.row][square.col + 1]) == -1) {
        checkLinked(squareSet[square.row][square.col + 1], arr);
    }
    //向上
    if (square.row < boderWidth - 1 && squareSet[square.row + 1][square.col] && squareSet[square.row + 1][square.col].num == square.num && arr.indexOf(squareSet[square.row + 1][square.col]) == -1) {
        checkLinked(squareSet[square.row + 1][square.col], arr);
    }
    //向下
    if (square.row > 0 && squareSet[square.row - 1][square.col] && squareSet[square.row - 1][square.col].num == square.num && arr.indexOf(squareSet[square.row - 1][square.col]) == -1) {
        checkLinked(squareSet[square.row - 1][square.col], arr);
    }
}
点击方块下落
function move() {
    // 向下移动
    for (var i = 0; i < boderWidth; i++) {//列
        var pointer = 0;// pointer指向空格子
        for (var j = 0; j < boderWidth; j++) {//行
            if (squareSet[j][i] != null) {
                if (j != pointer) {
                    squareSet[pointer][i] = squareSet[j][i];
                    squareSet[j][i].row = pointer;
                    squareSet[j][i] = null;
                }
                pointer++;
            }
        }
    }
    //横向移动
    for (var i = 0; i < squareSet[0].length;) {
        if (squareSet[0][i] == null) {
            for (var j = 0; j < boderWidth; j++) {
                squareSet[j].splice(i, 1);
            }
            continue;
        }
        i++;
    }
    refresh();
}
计算分数
function selectScore() {
    var score = 0;
    for (var i = 0; i < choose.length; i++) {
        score += baseScore + i * stepScore//基础分加上递增分
    }
    // 5块   5+15+25+35+45=125
    if (score <= 0) {
        return;
    }
    select_score.innerHTML = choose.length + "块" + score + "分";
    select_score.style.transition = null; // 需要还原下次才能直接出现,否则会渐变出现,
    select_score.style.opacity = 1;//马上显示
    setTimeout(function () {
        select_score.style.transition = "opacity 1s";//渐渐消失
        select_score.style.opacity = 0;
    }, 1000)
}
判断游戏是否结束
function isFinish() {
    for(var i=0;i<squareSet.length;i++){
        for(var j=0;j<squareSet[i].length;j++){
            var temp=[];
            checkLinked(squareSet[i][j],temp)// 判断周围是否还存在可以消去的小方块
            if(temp.length>1){
                return false;
            }
        }
    }
    return true;    
}
完整的js
var table;
var squareWidth = 50;//每个小方块的宽度
var boderWidth = 10;//横竖各有多少个小方块
var squareSet = [];//存放小方块
var choose = [];
var timer;
var baseScore = 5;//基础分
var stepScore = 10;//递增分
var select_score = document.getElementById('selectScore');//几块几分
var nowScore = document.getElementById('nowScore');//当前分数
var totalScore = 0;//总分数
var targetScore = 1500;//目标分数
var flag=true;
var tempSquare = null;//消除过程中如果输入移入其他方块,进行记录


//创建小方块
function createSquare(value, row, col) {
    var temp = document.createElement('div');
    temp.style.width = squareWidth + 'px';
    temp.style.height = squareWidth + 'px';
    temp.style.background = 'red';
    temp.style.display = 'inline-block';//使小方块能够横向排列
    temp.style.position = "absolute";
    temp.style.borderRadius = '12px';
    temp.style.boxSizing = "border-box";
    temp.num = value;//颜色
    temp.row = row;
    temp.col = col;
    return temp;
}
//检查周围相同颜色的小方块
function checkLinked(square, arr) {
    if (square == null) {
        return;
    }
    arr.push(square);
    //向左
    /* 
   1.不能是最左边的
   2.左边得存在一个小块
   3.左边的小方块和当前的小方块颜色相同
   4.左边的小方块没有被收录进数组
   */
    if (square.col > 0 && squareSet[square.row][square.col - 1] && squareSet[square.row][square.col - 1].num == square.num && arr.indexOf(squareSet[square.row][square.col - 1]) == -1) {
        checkLinked(squareSet[square.row][square.col - 1], arr);
    }
    //向右
    if (square.col < boderWidth - 1 && squareSet[square.row][square.col + 1] && squareSet[square.row][square.col + 1].num == square.num && arr.indexOf(squareSet[square.row][square.col + 1]) == -1) {
        checkLinked(squareSet[square.row][square.col + 1], arr);
    }
    //向上
    if (square.row < boderWidth - 1 && squareSet[square.row + 1][square.col] && squareSet[square.row + 1][square.col].num == square.num && arr.indexOf(squareSet[square.row + 1][square.col]) == -1) {
        checkLinked(squareSet[square.row + 1][square.col], arr);
    }
    //向下
    if (square.row > 0 && squareSet[square.row - 1][square.col] && squareSet[square.row - 1][square.col].num == square.num && arr.indexOf(squareSet[square.row - 1][square.col]) == -1) {
        checkLinked(squareSet[square.row - 1][square.col], arr);
    }
}
//方块闪烁
function flicker(arr) {
    var num = 0;
    timer = setInterval(function () {
        for (var i = 0; i < arr.length; i++) {
            arr[i].style.border = "3px solid #BFEFFF";
            arr[i].style.transform = "scale(" + (0.90 + 0.05 * Math.pow(-1, num)) + ")";
        }
        num++;
    }, 300)
}
//计算分数
function selectScore() {
    var score = 0;
    for (var i = 0; i < choose.length; i++) {
        score += baseScore + i * stepScore//基础分加上递增分
    }
    if (score <= 0) {
        return;
    }
    select_score.innerHTML = choose.length + "块" + score + "分";
    select_score.style.transition = null;//此处必须还原
    select_score.style.opacity = 1;//马上显示
    setTimeout(function () {
        select_score.style.transition = "opacity 1s";//渐渐消失
        select_score.style.opacity = 0;
    }, 1000)
}
//鼠标移走,小方块恢复大小
function goBack() {
    if (timer != null) {
        clearInterval(timer);
    }
    for (var i = 0; i < squareSet.length; i++) {
        for (var j = 0; j < squareSet[i].length; j++) {
            if (squareSet[i][j] == null) {
                continue;
            }
            squareSet[i][j].style.border = "0px solid #BFEFFF";
            squareSet[i][j].style.transform = "scale(0.95)";
        }
    }
}
//鼠标悬停事件
function mouseOver(obj) {//obj代表的是小方块
    if(!flag){
        tempSquare = obj;
        return;
    }
    goBack();
    choose = [];
    checkLinked(obj, choose);
    //只有一个小方块无法被消灭
    if (choose.length <= 1) {
        choose = [];
        return;
    }
    flicker(choose);
    // console.log(choose);
    selectScore();//计算分数
}
//小方块渲染
function refresh() {
    for (var i = 0; i < squareSet.length; i++) {
        for (var j = 0; j < squareSet[i].length; j++) {
            if (squareSet[i][j] == null) {
                continue;
            }
            squareSet[i][j].row = i;
            squareSet[i][j].col = j;
            squareSet[i][j].style.transition = "left 0.3s, bottom 0.3s";
            squareSet[i][j].style.left = squareSet[i][j].col * squareWidth + "px";
            squareSet[i][j].style.bottom = squareSet[i][j].row * squareWidth + "px";
            squareSet[i][j].style.backgroundImage = "url('./pic/" + squareSet[i][j].num + ".png')";
            squareSet[i][j].style.backgroundSize = "cover";
            squareSet[i][j].style.transform = "scale(0.95)";
        }
    }
}
//小方块往下掉
function move() {
    for (var i = 0; i < boderWidth; i++) {//列
        var pointer = 0;
        for (var j = 0; j < boderWidth; j++) {//行
            if (squareSet[j][i] != null) {
                if (j != pointer) {
                    squareSet[pointer][i] = squareSet[j][i];
                    squareSet[j][i].row = pointer;
                    squareSet[j][i] = null;
                }
                pointer++;
            }
        }
    }
    //横向移动
    for (var i = 0; i < squareSet[0].length; i++) {
        if (squareSet[0][i] == null) {
            for (var j = 0; j < boderWidth; j++) {
                squareSet[j].splice(i, 1);
            }
            continue;
        }
    }
    refresh();
}
//判断是否结束
function isFinish() {
    for(var i=0;i<squareSet.length;i++){
        for(var j=0;j<squareSet[i].length;j++){
            var temp=[];
            checkLinked(squareSet[i][j],temp)
            if(temp.length>1){
                return false;
            }
        }
    }
    return true;    
}
//初始化
function init() {
    table = document.getElementById('pop_star');
    for (var i = 0; i < boderWidth; i++) {
        squareSet[i] = new Array();
        for (var j = 0; j < boderWidth; j++) {
            var square = createSquare(Math.floor(Math.random() * 5), i, j);//创建小方块
            square.onmousemove = function () {//鼠标悬停事件,鼠标放在某个小方块上时触发
                mouseOver(this);
            }
            square.onclick = function () {//鼠标点击事件
                if(!flag||choose.length==0){
                    return;
                }
                flag=false;
                tempSquare = null;
                //加分数
                var score = 0;
                for (var i = 0; i < choose.length; i++) {
                    score += baseScore + i * stepScore;
                }
                totalScore += score;
                nowScore.innerHTML = "当前分数:" + totalScore;
                //消灭星星
                for (var i = 0; i < choose.length; i++) {
                    (function (i) {
                        setTimeout(function () {
                            squareSet[choose[i].row][choose[i].col] = null;
                            table.removeChild(choose[i]);
                        }, i * 100)

                    })(i)
                }
                //移动
                setTimeout(function () {
                    move();
                    //判断是否结束
                    setTimeout(function () {
                        var is = isFinish();
                        if(is){
                            if(totalScore>=targetScore){
                                alert('恭喜获胜');
                            }
                            else{
                                alert('游戏失败')
                            }
                        }
                        else{
                            choose=[];
                            flag=true;
                            mouseOver(tempSquare);
                        }
                    }, 300 + choose.length * 150)
                }, choose.length * 100);
            }
            squareSet[i][j] = square;
            table.appendChild(square);
        }
    }
    refresh();
}

window.onload = function () {
    init();
}
  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

callmeCassie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值