js实现消灭星星(web简易版)


Posted in Javascript onMarch 24, 2020

昨天看视频之后,整理思路,自己完成了简易版消灭星星

思路:

模块1:初始化

  • 初始化总分数、当前分数、背景图、选择的星星分数
  • 初始化星星(生成二维数组,对二维数组的每一个对象设置样式(长、宽、背景图),生成二维数组个div元素节点插入到游戏面板中)

模块2:预判

判断:

 鼠标移动到某一个方块,判断上下左右是否有连接着的小方块(采用递归方法),然后将其存储到数组choose[],移到其他方块时,choose置为空

闪烁:

 将已选中的小方块设置样式(缩放)

显示选择分数:

 设置初始分数和递增分数,根据选中的块数算出选中的分数

模块3:点击

消失:

 点击已选中的小方块,将连着的所有小方块在二维数组的位置设置为空,清空choose数组

移动:

 下移:设置一个指针,指向最下面的行。每当行+1,若遇到不为空的方块,则pointer++,若遇到该列某行为空,则将pointer的行数设为i

  左移:最底部的一行若有一列为空,将右边的所有方块的列-1

判断:

 每次点击完成之后判断游戏是否结束

代码部分

html

html结构很简单

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
 <script src="./index.js"></script>
 <link rel="stylesheet" href="index.css" >
</head>
<body>
 <div id="pop_star">
 <div id="target_score">目标分数:2000</div>
 <div id="now_score">当前分数:0</div>
 <div id="select_score">0块 0分</div>
 </div>
</body>
</html>

CSS

css布局也很简单,相信不用我来说

* {
 margin: 0px;
 padding: 0px;
 }

html, body {
 height: 100%;
 width: 100%;
}

#pop_star {
 width: 500px;
 height: 100%;
 background: url("./pic/background.png");
 margin-left: auto;
 margin-right: auto;
 position: relative;
 background-size: cover;
 font-size: 0px;
}

#target_score {
 width: 100%;
 height: 50px;
 line-height: 50px;
 text-align: center;
 color: white;
 font-size: 20px;
 position: relative;
}

#now_score {
 width: 100%;
 height: 50px;
 line-height: 50px;
 text-align: center;
 color: white;
 font-size: 20px;
 position: relative;
}

#select_score {
 width: 100%;
 height: 50px;
 line-height: 50px;
 text-align: center;
 color: white;
 font-size: 20px;
 position: relative;
 opacity: 0;
}

JS

/*
 创建二维数组
 * 
 * 
 * */
var table ;
var suqareWidth = 50 ; //一个星星/方块边长
var boardWidth = 10 ; //横竖方块个数
var squareSet = [];//小方块的集合,二维数组
var choose = [];//有相邻的小方块,将其放到这个数组
var timer = null ;
var baseScore = 5 ;
var stepScore = 10 ;
var totalScore = 0 ;
var targetScore = 1500;
var flag = true ;
var tempSquare = null;//在处理鼠标动作过程中,动作被屏蔽,导致事件处理完成,有不连贯现象
function createSquare(value , row , col){
 //创建小方块节点
 var blocks = document.createElement('div');
 //设置样式
 blocks.style.width = suqareWidth + 'px';
 blocks.style.height = suqareWidth + 'px';
 blocks.style.display = 'inline-block';
 blocks.style.boxSizing = 'border-box';
 blocks.style.position = 'absolute';
 blocks.style.borderRadius = "12px";
 //小方块的行和列,小方块的num.jpg
 blocks.num = value ;
 blocks.row = row ;
 blocks.col = col ;
 return blocks;
}
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 * suqareWidth + 'px';
 squareSet[i][j].style.bottom = squareSet[i][j].row * suqareWidth + 'px';
 //背景图
 squareSet[i][j].style.backgroundImage = "url('img/" + squareSet[i][j].num + ".png')";
 squareSet[i][j].style.backgroundSize = 'cover';
 squareSet[i][j].style.transform = 'scale(0.95)';//是图片缩小至原来的0.95倍
 }
 }
}
function checkLinked(square , arr){
 //严谨判断
 if(square == null){
 return;
 }
 //添加小方块到arr
 arr.push(square);
 /*
 判断位于该小方块左边的小方格是否能被收录进选择数组
 1.小方格不能是最左边的
 2.小方格左边必须有小方块
 3.小方块左边的要和该小方块颜色相同
 4.该小方块左边没有被收录到数组中去
 5.递归
 * 
 * */
 //向左
 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 < boardWidth - 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 < boardWidth - 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.9 + 0.05 *Math.pow(-1 , num))+")";
 }
 //小方块闪烁完成之后num++,使其再次缩放
 num++;
 },300);
}
function back(){
 //若计时器还存在,清楚计数器
 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 selectScore(){
 var socre = 0 ;
 //遍历choose
 for(var i = 0 ; i < choose.length ; i++){
 socre += baseScore + stepScore * i ;
 }
 //严谨判断
 if (socre <= 0) {
 return ;
 }
 //设置select_score的样式
 var select_score = document.getElementById('select_score');
 select_score.innerHTML = choose.length + "块" + socre + "分";
 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 mouseOver(obj){
 //当鼠标在移动到该方块突然移动到其他位置时
 if(!flag){
 tempSquare = obj;
 return ;
 }
 //当鼠标移开选中的方块之后,让其回到原来的样式
 back();
 //选择相邻相同的小方格
 //传一个数组
 choose = [];
 checkLinked(obj , choose);//obj是当前鼠标移到的小方块,choose是存储响铃小方块的数组
 if (choose.length <= 1) {
 choose = [] ;
 return;
 }
 //将选中的设置样式,让其闪烁
 flicker(choose);
 //显示所选中的小方块的分数
 selectScore();
}
function move(){
 /*
 1.设置一个指针,开始的时候指针指向最下面一行
 2.此时指针和j是否一样,一样都++。
 3.若改行该列该列有小方块,均++,反之j++,pointer不变,循环判断该条件
 3.当j移动到该列某行的小方块,该小方块存在,则将j指向的小方块的位置设置为指针指向的那一个小方块的位置
 * */
 //向下移动
 for (var i = 0 ; i < boardWidth ; i ++) {
 var pointer = 0;//pointer指向小方块,当遇到null的时候停止,等待上面的小方块落到这里来
 for (var j = 0 ; j < boardWidth ; 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 < boardWidth ; j ++) {
  squareSet[j].splice(i, 1);
  }
  continue;
 }
 i ++;
 }
 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 < boardWidth ; i++){
 squareSet[i] = new Array();
 for(var j = 0 ; j < boardWidth; j++){
 //创建小方块
 var square = createSquare(Math.floor(Math.random() * 5), i, j);
 //鼠标移动到该方块
 square.onmouseover = function(){
 mouseOver(this);
 }
 //点击小方块时的操作
 square.onclick = function(){
 //小方块在被点击的时候其他操作不能影响他的执行
 if(choose.length == 0 || !flag ){
 return ;
 }
 flag = false;
 tempSquare = null ;
 /*
 1.增加当前分数
 2.小方块消失
 3.向下或想做移动
 4.判断游戏是否结束
 */ 
 var socre = 0 ;
 //遍历choose
 for(var i = 0 ; i < choose.length ; i++){
 socre += baseScore + stepScore * i ;
 }
 totalScore += socre ;//总分数
 //改变样式
 document.getElementById('now_score').innerHTML = '当前分数:' + totalScore;
 //小方块消失
 /*
 1.从二维数组里面移除选择了的小方块
 2.在面板上移除div,不然div会一直占着格子
 * */
 for(var i = 0 ; i < choose.length ; i++){
 //立即函数,立即出发该函数,否则的话,不会执行
 (function(i){
 setTimeout(function(){
 //将二维数组的某一值设置为空,后面的会向前移
 squareSet[choose[i].row][choose[i].col] = null ;
 //移除div
 table.removeChild(choose[i]);
 },i * 100);
 })(i);
 }
 //移动
 setTimeout(function(){
 move();
 setTimeout(function(){
 var finished = isFinish();
 if(finished){
 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();
}

其实这里还有优化的就是闯关部分,大致的思路就是,游戏每过一关增加目标分数,当游戏结束时,闯关失败,目标分数恢复初始值。

大家有什么不懂,可以在评论区评论。

jq进阶版的源码详情见我github,网址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery实现选项联动轮播效果【附实例】
Apr 19 Javascript
JS实现字符串转驼峰格式的方法
Dec 16 Javascript
jquery与ajax获取特殊字符实例详解
Jan 08 Javascript
jQuery插件autocomplete使用详解
Feb 04 Javascript
jquery实现轮播图效果
Feb 13 Javascript
Angular 4环境准备与Angular cli创建项目详解
May 27 Javascript
在Vue组件中获取全局的点击事件方法
Sep 06 Javascript
详解vue文件中使用echarts.js的两种方式
Oct 18 Javascript
vue打包之后生成一个配置文件修改接口的方法
Dec 09 Javascript
JS实现鼠标拖拽盒子移动及右键点击盒子消失效果示例
Jan 29 Javascript
bootstrap table列和表头对不齐的解决方法
Jul 19 Javascript
Vue-router编程式导航的两种实现代码
Mar 04 Vue.js
JavaScript实现移动端带transition动画的轮播效果
Mar 24 #Javascript
javascript实现滚动条效果
Mar 24 #Javascript
Webpack中SplitChunksPlugin 配置参数详解
Mar 24 #Javascript
JS实现点星星消除小游戏
Mar 24 #Javascript
js实现小星星游戏
Mar 23 #Javascript
JS Array.from()将伪数组转换成数组的方法示例
Mar 23 #Javascript
Vue+elementUI实现多图片上传与回显功能(含回显后继续上传或删除)
Mar 23 #Javascript
You might like
PHP实现时间轴函数代码
2011/10/08 PHP
利用PHP扩展vld查看PHP opcode操作步骤
2013/03/04 PHP
排序算法之PHP版快速排序、冒泡排序
2014/04/09 PHP
php将print_r处理后的数据还原为原始数组的解决方法
2016/11/02 PHP
Laravel自动生成UUID,从建表到使用详解
2019/10/24 PHP
[IE&amp;FireFox兼容]JS对select操作
2007/01/07 Javascript
jQuery 技巧小结
2010/04/02 Javascript
javascript面向对象编程代码
2011/12/19 Javascript
为JavaScript类型增加方法的实现代码(增加功能)
2011/12/29 Javascript
Javascript基础教程之JavaScript语法
2015/01/18 Javascript
简介JavaScript中的getUTCFullYear()方法的使用
2015/06/10 Javascript
Nodejs下DNS缓存问题浅析
2016/11/16 NodeJs
微信公众平台开发教程(六)获取个性二维码的实例
2016/12/02 Javascript
javascript 中设置window.location.href跳转无效问题解决办法
2017/02/09 Javascript
angularjs+bootstrap实现自定义分页的实例代码
2017/06/19 Javascript
jquery实现用户登陆界面(示例讲解)
2017/09/06 jQuery
Vue2.0实现组件数据的双向绑定问题
2018/03/06 Javascript
JavaScript实现联动菜单特效
2020/01/07 Javascript
vue实现标签云效果的示例
2020/11/09 Javascript
Python tkinter模块弹出窗口及传值回到主窗口操作详解
2017/07/28 Python
浅谈python可视化包Bokeh
2018/02/07 Python
python实现beta分布概率密度函数的方法
2019/07/08 Python
Python笔记之观察者模式
2019/11/20 Python
python 读取数据库并绘图的实例
2019/12/03 Python
关于python pycharm中输出的内容不全的解决办法
2020/01/10 Python
Pytorch 使用opnecv读入图像由HWC转为BCHW格式方式
2020/06/02 Python
Python Opencv轮廓常用操作代码实例解析
2020/09/01 Python
如何启动时不需输入用户名与密码
2014/05/09 面试题
如何为DataGridView添加一个定制的Column Type
2014/01/21 面试题
《圆明园的毁灭》教学反思
2014/02/28 职场文书
ktv好的活动方案
2014/08/15 职场文书
2014年党员自我评议(5篇)
2014/09/12 职场文书
甜品蛋糕店创业计划书
2014/09/21 职场文书
工商局副局长个人对照检查材料
2014/09/25 职场文书
2015年发展党员工作总结报告
2015/03/31 职场文书
员工福利申请报告
2015/05/15 职场文书