变色方块

页面部分

HTML文档的结构非常简单,我们的游戏将呈现在这个HTML中id为game的div中,一个li标签,表示一个方块。在style中为按钮及方格添加样式。创建一个HTML文件,将它保存在你理想的位置,名称为index.html。并为这个文件添加以下代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>自动完成</title>
</head>
<style>
body{
background: #FFFFCF;
padding: 0;
margin: 0;
}
#container{
width: 900px;
height: 700px;
background: white;
margin: 0 auto;
}
#backAll,#backThis,#help,#status{
width: 80px;
height: 30px;
border: 4px #fffccf solid;
background: white;
border-radius: 8px;
margin-top: 10px;
outline: none;
}
#game{
margin: 20px 0px 0px 20px;
width: 560px;
height: 560px;
border-top: 5px solid black;
border-right: 5px solid black;
border-radius: 10px;
padding: 0;
}
ul{
margin: 0;
padding: 0;
}
li{
padding: 0;
margin: 0;
list-style: none;
border-left: 5px solid black;
border-bottom: 5px solid black;
float: left;
background: #ea971f;
}
#express{
margin-left: 650px;
}
</style>
<body>
<div id="container">
<input type="button" id="backAll" value="重玩游戏"/>
<input type="button" id="backThis" value="重玩本关"/>
<input type="button" id="help" value="辅助方块"/>
<input type="button" id="status" value="游戏说明"/>
<div id="express">
<span id="myLevel">关卡:1</span>
<span id="myStep">步数:0</span>
</div>
<div id="game">
<ul id="box">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>
</body>
</html>
<script>
</script>

在浏览器中打开该文件,会显示出一个拥有2*2方格的方框。此时,点击按钮和方块都没有效果呈现。由于方块是动态的(即它的数量会发生变化),故,不应在html文件中添加li。所以将index.html文件中

1
2
3
4
5
6
<ul id="box">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>

改为:

1
2
<ul id="box">
</ul>

我们将在javascript中动态添加li。以下代码全部位于标签中

添加方块和方块点击

我们需要在页面加载完成之后再调用功能,所以,代码应放在window.onload中。
想要在ul(id名为box)中呈现图像内容,为它动态添加li,必须在JavaScript中获取到这个元素;同时,我们要决定方块的个数,假设一行的个数为num,则方格的个数为num*num。定义一个数组Oli,将li放入数组中,方便我们去操作li的属性。在JavaScript中添加以下代码:

1
2
3
4
5
6
7
window.onload= function(){
let Obox = document.getElementById('box');
let num = 1;
const Oli = [];
let Ostep = document.getElementById('myStep'); //获取元素,以改变步数值
let Olevel = document.getElementById('myLevel');//获取元素,以改变关卡值
}

因为UL的大小已经固定为560px*560px,所以,li的大小也要跟着个数的改变。li除了自身宽高,还有5px的边框,所以计算方式如下:

1
2
let decent = num*5;
let real = (560-decent)/num;

动态添加li,createElement创建元素,classList.add添加class,控制li的样式。 Oli.push将li放入数组中。 Obox.appendChild将新创建的li放到ul中。设置li的大小和颜色。
为li添加两个自定义属性:data-uid 和 data-usta 。data-uid便于我们找到相对应的li,从0开始计数。data-usta = 0代表该方块是橙色,data-usta = 1代表该方块是蓝色。

1
2
3
4
5
6
7
8
9
10
11
for(let i=0;i<num*num;i++){
let myLi = document.createElement('li');
myLi.classList.add("boxChild");
Oli.push(myLi);
Obox.appendChild(Oli[i]);
Oli[i].style.width = real/num +"px";
Oli[i].style.height = real/num +"px";
Oli[i].style.background = "#ea971f";
Oli[i].setAttribute("data-uid",i);
Oli[i].setAttribute("data-usta",0);
}

为了让代码能重复使用,我们将它封装成一个函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function changeBox(num,Oli){
let decent = num*5;
let real = (560-decent)/num;
for(let i=0;i<num*num;i++){
let myLi = document.createElement('li');
myLi.classList.add("boxChild");
Oli.push(myLi);
Obox.appendChild(Oli[i]);
Oli[i].style.width = real +"px";
Oli[i].style.height = real +"px";
Oli[i].setAttribute("data-uid",i);
Oli[i].setAttribute("data-usta",0);
Oli[i].style.background = "#ea971f";
}
}

并在 const Oli = []; 下面进行调用,以进行初始化。在const Oli = [];添加

1
changeBox(num,Oli);

此刻,我们的方块还不具备变色的功能。点击方块时,若方块是橙色,则变成蓝色;若为蓝色,则变成橙色;判断方块的颜色,通过li的自定义属性data-usta。将代码封装成函数,便于调用。

1
2
3
4
5
6
7
8
9
function oneLryb(obj){
if(obj.getAttribute('data-usta') == 0){
obj.style.background = "#5283a3";
obj.setAttribute("data-usta",1);
}else if(obj.getAttribute('data-usta') == 1){
obj.style.background = "#ea971f";
obj.setAttribute("data-usta",0);
}
}

点击方块时,改变方块本身,方块相邻的上、下、左、右的颜色。若被点击方块序号为 i ,则上下左右的序号分别为:i-num;i+num;i-1;i+1;同时需要考虑这些方块的上下左右是否都存在方块,即上下左右的序号是否超出了num*num或者小于0;j=0,改变本身;j=1,改变左侧;j=2,改变右侧;j=3,改变上方;j=4,改变下方;符合条件时,调用oneLryb(obj)函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function allLryb(i,Oli,num){
var k = i;
for(let j=0;j<5;j++){
switch(j){
case 0: i = k;oneLryb(Oli[i]);break;
case 1:{
if(i%num-1>=0){
i = i-1;
oneLryb(Oli[i]);
i=k;
}else{
i=k;
}
break;
}
case 2:
if((i%num+1)<num){
i = i+1;
oneLryb(Oli[i]);
i=k;
}
break;
case 3:
if(i-num >=0){
i = i-num;
oneLryb(Oli[i]);
i=k;
}
break;
case 4:
if(num*num >i+num){
i = i+num;
oneLryb(Oli[i]);
i=k;
}
break;
}
}
}

为方块加上点击的功能,点击一次,步数加一

1
2
3
4
5
6
7
8
function run(Oli,i,num){
var obj = Oli[i];
obj.onclick= function(){
step ++;
Ostep.innerHTML = "步数:"+step;
allLryb(i,Oli,num);
}
}

在初始化时,为每个li绑定点击功能。将changeBox(num,Oli)函数的for循环改为

1
2
3
......
Oli[i].style.background = "#ea971f";
run(Oli,i,num);

最后我们需要对所有方块进行检查,当所有方块都变成蓝色时,通关。

1
2
3
4
5
6
7
8
9
function exam(obj,num){
for(let i=0;i<num*num;i++){
if(obj[i].getAttribute('data-usta') !=1){
return false;
}else if(obj[i].getAttribute('data-usta') ==1 &&i+1==num*num){
return true;
}
}
}

每次点击方块之后都应该进行一次检查,若通关,则进入下一关。所以在run(Oli,i,num)方法中调用exam(obj,num);使用setTimeout进行延时,否则方块改变颜色的效果还没有呈现就进行下一关。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function run(Oli,i,num){
var obj = Oli[i];
obj.onclick= function(){
step ++;
Ostep.innerHTML = "步数:"+step;
allLryb(i,Oli,num);
flag = exam(Oli,num);
if(flag){
num = num +1;
Olevel.innerHTML = `关卡:${num}`; //改变关卡值
setTimeout(function(){changeBox(num,Oli);},300);
}
}
}

为按钮添加功能,获取元素。

1
2
3
4
5
let ObackAll = document.getElementById('backAll'); //重玩游戏
let ObackThis = document.getElementById('backThis');//重玩本关
let Ohelp = document.getElementById('help');//辅助方块,暂时还用不上
let Ostatus = document.getElementById('status');//游戏说明
let ObChild = document.getElementsByClassName('boxChild');

“重玩游戏”按钮点击效果:步数归零,关卡回到第一关,重新初始化方格。

1
2
3
4
5
6
7
8
9
10
ObackAll.onclick = function(){
for(let j=ObChild.length-1;j>0;j--){
ObChild[j].remove();
}
step = 0;
Ostep.innerHTML = "步数:"+step;
num = 1;
Olevel.innerHTML = `关卡:${num}`;
changeBox(num,Oli);
}

“重玩本关”按钮点击效果:将所有方块变成橙色

1
2
3
4
5
6
7
ObackThis.onclick = function(){
let len = Math.sqrt(ObChild.length);
for(let j=ObChild.length-1;j>0;j--){
ObChild[j].remove();
}
changeBox(len,Oli);
}

“游戏说明”按钮点击效果

1
2
3
Ostatus.onmouseenter = function(){
alert(`游戏说明\n点击方块,改变方块本身及相邻的方块\n所有方块颜色变成蓝色,即通关`)
}

完整代码移步:github

您的支持将鼓励我继续创作!