服务器之家:专注于服务器技术及软件下载分享
分类导航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服务器之家 - 编程语言 - JavaScript - 原生js实现俄罗斯方块

原生js实现俄罗斯方块

2021-11-01 16:04贝尔格尔屌丝 JavaScript

这篇文章主要为大家详细介绍了原生js实现俄罗斯方块,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了js实现俄罗斯方块的具体代码,供大家参考,具体内容如下

效果如下

原生js实现俄罗斯方块

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
<!DOCTYPE html>
<html lang="en">
 
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <link rel="stylesheet" href="../css/Demo.css" >
 <title>俄罗斯方块</title>
</head>
 
<body>
 <div class="square" id="local">
 <div class="title"><h2>我方游戏区域</h2></div>
 <div class="game" id="local_game">
 
 </div>
 <div class="tip" id="local_tip">
 </div>
 <div class="next" id="local_next">
 
 </div>
 <div class="info">
  <div>用时<span id="local_time">&nbsp;&nbsp;0</span></div>
  <div>得分<span id="local_score" class="score">&nbsp;&nbsp;0</span></div>
 </div>
 </div>
 <div class="square" id="remote">
 <div class="title"><h2>对方游戏区域</h2></div>
 <div class="game" id="remote_game">
 
 </div>
 <div class="tip" id="remote_tip">
 </div>
 <div class="next" id="remote_next">
 
 </div>
 <div class="info">
  <div>用时<span id="remote_time">&nbsp;&nbsp;0</span></div>
  <div>得分<span id="remote_score" class="score">&nbsp;&nbsp;0</span></div>
  <div class="btn">
  <button id="down">down</button>
  <button id="left">left</button>
  <button id="right">right</button>
  <button id="rotate">rotate</button>
  <button id="fall">fall</button><!-- 下坠 -->
  <button id="fixed">fixed</button><!-- 固定 -->
  <button id="performNext">performNext</button><!-- 产生下一个 -->
  <button id="checkClear">checkClear</button><!-- 是否消行 -->
  <button id="gameover">gameover</button><!-- 游戏是否结束 -->
  <button id="settime">settime</button>
  <button id="addscore">addscore</button>
  <button id="gamestate">gamestate</button><!-- 游戏状态赢或输 -->
  <button id="addTaiLines">addTaiLines</button><!-- 底部增加一行 -->
  </div>
 </div>
 </div>
</body>
<script src="../js/square.js"></script>
<script src="../js/squareFactory.js"></script>
<script src="../js/game.js"></script>
<script src="../js/local.js"></script>
<script src="../js/remote.js"></script>
<script type="text/javascript" src="../js/Demo.js"></script>
 
</html>

css

?
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
77
78
.square{
 width: 400px;
 height: 500px;
 position: absolute;
 border: solid 1px red;
}
.title{
 width: 400px;
 text-align: center;
 margin: 0 auto;
}
.game{
 width: 200px;height: 400px;
 border-bottom: 1px solid blue;
 border-right: 1px solid blue;
 border-left: 1px solid blue;
 position: absolute;
 background-color: #f2faff;
 top: 70px;
 left: 10px;
}
.next{
 width: 80px;height: 80px;
 position: absolute;top: 70px;left: 250px;
 border: solid 0px red;
}
.info{
 position: absolute;top: 170px;left: 250px;
 border: solid 0px red
}
 
.none,.current,.done{
 width: 20px;height: 20px;
 position: absolute;
 box-sizing: border-box;
}
 
 
.tip{
 width: 100px;
 position: absolute;
 top: 270px;
 left: 250px;
 font-size: 20px;
 color:red;
 border: solid 0px red;
}
 
 
.score{
 color:green;
}
/* 消失的方块 */
.none{
 background-color: #414141;
 border: solid 1px white
}
 
/* 正在操作的方块 */
.current{
 background-color: pink;
 border:solid 1px red;
}
 
/* 落下的方块 */
.done{
 background:#d2f028;
 border:solid 1px black
}
 
#remote{
 left: 500px;
}
 
.btn{
 width: 70px;
 border: solid 0px red
}

Demo.js

?
1
2
3
4
5
6
var local = new local();
local.start();
 
var remote = new Remote();
remote.start(2,2);
remote.bindEvents();

game.js

?
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
//核心逻辑 2
var Game = function(){
 //这两个div为游戏中的两个最大的容器盒子 dom元素
 var gameDiv;
 var nextDiv;
 var timeDiv;
 var scoreDiv;
 var local_tipDiv;
 //游戏界面框中的方块坐标
 var gameData=[
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
 ]
 
 //装载所有的div的容器 数组
 //next中的div
 var nextDivs = [];
 //游戏框中的div
 var gameDivs = [];
 
 //定义两个方块
 //当前方块
 var cur;
 //下一个方块
 var next;
 
 //渲染游戏框中的div
 /**
  *
  * @param {*} container 最大容器 也就是这个div要被添加到容器
  * @param {*} data div的矩阵数据
  * @param {*} divs 用于装载所有的div
  */
 var initDiv = function(container,data,divs){
  for(var i=0;i<data.length;i++){
   var DIV = [];
   for(var j=0;j<data[i].length;j++){
    var div = document.createElement("div");
    div.classList.add('none');
    div.style.top=i*20+"px";
    div.style.left=j*20+"px";
    container.appendChild(div);
    DIV.push(div);
   }
   divs.push(DIV)
  }
 };
 
 //刷新游戏界面的div 和提示下一个的div
 /**
  *
  * @param {*} data div的矩阵数据
  * @param {*} divs 装载div的容器
  */
 var refresh = function(data,divs){
  for(var i = 0;i<data.length;i++){
   for(var j=0;j<data[i].length;j++){
    if(data[i][j]==0){
     divs[i][j].className = "none"
    }
    else if(data[i][j]==1){
     divs[i][j].className = "done"
    }
    else if(data[i][j]==2){
     divs[i][j].className = "current"
    }
   }
  }
 } ;
 
 
//初始化方法
 var init = function(doms,type,dir){
  gameDiv = doms.gameDiv;//游戏区域的大div
  nextDiv = doms.nextDiv;//提示区域的大div
  timeDiv = doms.timeDiv;//显示时间的div
  scoreDiv = doms.scoreDiv;//显示分数的dom
  local_tipDiv = doms.local_tip;//显示游戏状态
 
  //这里返回的是七种方块的其中一种 这些方块都继承square对象的成员
  next = squareFactory.prototype.make(type,dir);
 
  initDiv(gameDiv,gameData,gameDivs);
  initDiv(nextDiv,next.data,nextDivs);
  refresh(next.data,nextDivs);
  //console.log(gameData)
 };
 
 //下移
 this.down = function(){
  //这里是将isValue方法传入到canDown中 里canDown中判断下落的点是否合法
  if(cur.canDown(isValue)){
   //移动组合方块之前先清除数据 在重新添加
   clearGameData();
   //这里x加一 那么组合方块的初始下标位置变化加一 如从第十行开始 那么变化变成
   //第十一行
   cur.onDown(); //这里x轴控制的上下 y控制的是左右
   setData();
   refresh(gameData,gameDivs);
   //console.log(gameData);
   return true;
  }else{
   return false;
  }
  //这里我们需要注意 若next提示框中的组合方块四周都有空位时 我们就算不清除
  //它也能正常移动 这是因为后来方块会替换现有的空位 而现有的空位便会
  //向下移动
  //0 1 1 0
  //0 0 0 0
  //例如 我们若向右加一的话 那么它便会变成这样
  //0 0 1 1 这是因为它本来前面有个空位 所以加1后 后来的空位便会替换
  //原本1的位置 而原本1的位置由于加1了 所以也会整体向右移动
 };
 
 //左
 this.left = function(){
  if(cur.canLeft(isValue)){
   clearGameData();
   cur.onLeft();
   setData();
   refresh(gameData,gameDivs)
   //console.log(gameData)
  }
 };
 
 //右
 this.right = function(){
  if(cur.canRight(isValue)){
   clearGameData();
   cur.onRight();
   setData();
   refresh(gameData,gameDivs)
   //console.log(gameData)
  }
 };
 
 //上
 this.up = function(){
  if(cur.canRotate(isValue)){
   cur.onrotate();
   setData();
   refresh(gameData,gameDivs)
  }
 };
 
 //直接坠落
 //在内部调用自己用this引用的方法时 也要加上this
 this.fall = function(){ while( this.down() ); };
 
 
 //清除方块
 var clearGameData = function(){
  for(var i=0;i<cur.data.length;i++){
   for(var j=0;j<cur.data[i].length;j++){
    if(check(cur.origin,i,j))
    gameData[cur.origin.x+i][cur.origin.y+j] = 0
   }
  }
 };
 //用于设置当前组合方块的位置变化
 var setData = function(){
  //外循环四次
  for(var i=0;i<cur.data.length;i++){
   //内循环四次
   for(var j=0;j<cur.data[i].length;j++){
    //将 square中的data矩阵的值赋给插入到gameData矩阵中的指定位置
    //例如 这里x为10 那么一级数组的开始位置下标就是 10+0
    //二级数组中的开始下标就是5+0
    //也就是data[10+0][5+0]
    //第二次就是 data[10+1][5+1] 以此类推
    //这里注意一级数组控制的是上下 二级数组控制的是左右
    //也就是说 x轴是上下 y轴是左右
    if(check(cur.origin,i,j))
    gameData[cur.origin.x+i][cur.origin.y+j] = cur.data[i][j]
   }
  }
 };
 
 
//底部增加行
this.addTaiLines = function(lines){
 //lines为底部增加的行 例如line为2
 //将所有的方块往上移动两行
 // i=0;i<20 - 2;i++
 // gamedata[0] = gamedata[0+2] 例如从0开始 第一行就变成了第三行
 // gamedata[1] = gamedata[1+2] 第二行就变成了第四行
 // gamedata[2] = gamedata[2+2] 第三行就变成了第五行
 /**
  * 0 0 0 0 0 0 0 0 0 0
  * 2 2 2 2 2 2 2 2 2 2
  * 2 2 2 2 2 2 2 2 2 2
  * 2 2 2 2 2 2 2 2 2 2
  */
 for(var i=0;i<gameData.length-lines.length;i++){
  gameData[i] = gameData[i+lines.length];
 }
 //再把所有底部增加的内容显示出来
 //i=0 i<2 i++
 //gamedata[20-2+0](18) = lines[0]
 //gamedata[20-2+1](19) = lines[1]
 for(var i=0;i<lines.length;i++){
  gameData[gameData.length-lines.length+i] = lines[i];
 }
 cur.origin.x-=lines.length;
 if(cur.origin.x<0){
  cur.origin.x = 0;
 }
 refresh(gameData,gameDivs);
}
 
//设置时间显示
this.setTime = function(times){
 timeDiv.innerText = "--"+times+"s";
}
 
 
this.gameState = function(win){
 if(win){
  local_tipDiv.innerText = "你赢了"
 }else{
  local_tipDiv.innerText = "你输了"
 }
}
 
 
//产生下一个方块
this.performNext = function(type,dir){
 //首先先将下一个方块赋值给当前操作的方块
 cur = next;
 //然后重新设置当前游戏区域的方块
 setData();
 //在显示提示下一个方块
 next = squareFactory.prototype.make(type,dir);
 //然后刷新游戏区和提示区
 refresh(gameData,gameDivs)
 refresh(next.data,nextDivs);
}
 
 
//消行
var Fraction = 0;
this.checkclear = function(){
 Fraction = 0;
 //从最后一行开始 判断是否全部为1 若为1 则表示那一行以及全部铺满
 //否则clear为false 并跳出当前循环 例如第一次 若19行没有铺满 则跳出循环
 for(var i=gameData.length-1;i>=0;i-=1){
  var clear = true;
  for(var j=0;j<gameData[0].length;j+=1){
   //gamedata[19][0]!=1
   //or
   //gamedata[19][1]!=1 ....
   if(gameData[i][j]!=1){
    clear = false;
    break;
   }
  }
  //若clear为true 说明这一行全部铺满
  if(clear){
   Fraction += 1;
   //例如 m=19;m>0;m--
   for(var m = i;m>0;m--){
    //n=0;n<10;n++ 注 gamedata为20 其中每一个数组的长度为10
    for(var n=0;n<gameData[0].length;n++){
     //例如 外循环第一次
     //gamendata[19][0] = gamedata[19-1][0];
     //gamendata[19][1] = gamedata[19-1][1]; ....
     // 外循环第二次
     //gamendata[18][0] = gamedata[18-1][0];
     //gamendata[18][1] = gamedata[18-1][1]; ....
     gameData[m][n] = gameData[m-1][n];
     //将上一行的内容移动到下一行
    }
   }
   //n=0;n<10;n++
   for(var n=0;n<gameData[0].length;n++){
    //gamedata[0][0] = 0
    //gamedata[0][1] = 0
    //gamedata[0][2] = 0 ....
    gameData[0][n] = 0;
   }
   //i++的作用是让最下面一行被清除后 比如 19行铺满 我们便将18行往下移动一个行
   //然后在重新判断当前移动后的18行(也就是19行)是否铺满
   //因为每次循环完成后 i都会-1 如果底层没有铺满我们便正常循环 如果底层铺满
   //我们便重头开始检测
   console.log("当前i",i)
   i++;
  }
 }
 addscore(Fraction)
}
 
var score = 0;
var addscore = function(scoreCount){
 switch(scoreCount){
  case 1:
   score +=10;
   break;
  case 2:
   score +=30;
   break;
  case 3:
   score +=50;
   break;
  case 4:
   score +=100;
   break;
 }
 scoreDiv.innerText = "--"+score;
}
 
 
 
//游戏结束
this.gameover = function(){
 var over = false;
 for(var i=0;i<gameData[0].length;i++){
  if(gameData[1][i]==1){//若第二行以及有落下的方块 那么游戏便结束
   over = true;
  }
 }
 return over;
}
 
 /**
  *
  * @param {*} pos 等于当前方块的x 和 y的原点
  * @param {*} x 等于当前方块的上下位置的变化值
  * @param {*} y 左右位置的变化值
  */
 //判断当前是否可以移动
 var check = function(pos,x,y){
  if(pos.x+x < 0){return false}
  else if(pos.x+x >= gameData.length){return false}
  else if(pos.y+y < 0){return false}
  else if(pos.y+y >= gameData[0].length){return false}
  //这里是判断如果我们落下的这个位置已经有一个方块的话 那也不合法
  //若这个方块已经落下 我们便判定它的矩阵数据为1
  else if(gameData[pos.x+x][pos.y+y]==1){return false}
  else{return true}
 };
 /*
  10 + 0 > length ?
  10 + 1 > length ?
 0 0 1 0 0 5 + 1 > length ?
 1 0 1 0 0
 2 0 1 1 0
 3 0 0 0 0
  0 1 2 3
 */
 
 
//让当前方块变得不可移动
this.fixed = function(){
 for(var i=0;i<cur.data.length;i++){//0 1 2 3
  for(var j=0;j<cur.data[0].length;j++){//0 1 2 3
   if(check(cur.origin,i,j)){
    //若当前方块的值是 2 也就是说还处于操作状态的话
    //我们便将它赋值为 1 因为2等于操作中的方块 1等于以及落下的方块
    //而以及落下的方块是不可以移动 这个判断是写在check方法中的
    if(gameData[cur.origin.x+i][cur.origin.y+j]==2){
     gameData[cur.origin.x+i][cur.origin.y+j] = 1;
    }
   }
  }
 }
 refresh(gameData,gameDivs);
}
 
 //检测当前next中的矩阵数据是否合法
 /**
  *
  * @param {*} pos 当前方块的原点
  * @param {*} nextdata next中方块矩阵
  */
 var isValue = function(pos,nextdata){
  for(var i = 0;i<nextdata.length;i++){
   for(var j=0;j<nextdata[0].length;j++){
    //判断当前next的矩阵数据中的每一个位置是否等于0
    //若不等于0则判断当前的点是否还能继续下降
    if(nextdata[i][j]!==0){
     //若不能 则直接返回false
     if(!check(pos,i,j))return false;
    }
   }
  }
  //若都没有问题则返回true
  return true;
 }
 
 
 //将这个init导出 因为这里这个init是一个私有的方法
 this.init = init;
 this.addscore = addscore;
};

local.js

?
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//我的游戏区域 1
var local = function(){
 // 先声明游戏对象
 var game;
 
 //定义定时器时间间隔
 var INTERVAL = 500;
 
 //定义定时器
 var time = null;
 
 //计算时间
 var timeCount = 0;
 var times = 0;
 
 //定义一个start开始方法
 this.start = function(){
  //获取游戏中两个界面的dom元素
  var dom = {
   gameDiv:document.querySelector("#local_game"),
   nextDiv:document.querySelector("#local_next"),
   timeDiv:document.querySelector("#local_time"),
   scoreDiv:document.querySelector("#local_score"),
   local_tip:document.querySelector("#local_tip")
  };
  //实例化Game;
  game = new Game();
  //并将dom传入到Game的初始化方法中
  game.init(dom,generateType(),generateDir());
  //产生初始方块
  game.performNext(generateType(),generateDir());
  bindKeyEvent();
  //游戏开始时定义一个定时器 让方块自动下移
  time = setInterval(move,INTERVAL);
 };
 
 function move(){
  //时间计数
  timeFunc();
 
  if(!game.down()){
   game.fixed();
   //判断是否消行
   game.checkclear();
 
   //判断是否结束游戏
   if(game.gameover()){
    stop();
    game.gameState(false);
   }else{
    //当当前方块已经落到底部后 我们便产生下一个方块
    game.performNext(generateType(),generateDir())
   }
  }
 }
 
 var timeFunc = function(){
  //计算秒数 因为每过500毫秒会调用一次
  timeCount+=1;
  if(timeCount==2){
   timeCount = 0;
   times += 1;
   //设置显示时间
   game.setTime(times);
  }
 
  if(times%5==0){
   // game.addTaiLines(generrateBottomLine(1));
  }
 }
 
 //随机生成干扰行
 /**
  *
  * @param {*} linenum 生成干扰行的行数
  */
 var generrateBottomLine = function(linenum){
  //定义一个二维数组
  var lines = [];
  for(var i=0;i<linenum;i++){
   //二维数组中的一维数组
   var line = [];
   for(var j=0;j<10;j++){
    //随机生成0-2的数
    line.push(Math.ceil(Math.random()*2)-1);
   }
   lines.push(line);
  }
  return lines;
 }
 
 //产生一个随机数 代表着方块的种类
 function generateType(){
  //产生0-6的整数
  return Math.ceil(Math.random()*7)-1
 }
 
 //产生一个随机数 代表方块旋转的方向
 function generateDir(){
  //产生0-6的整数
  return Math.ceil(Math.random()*4)-1
 }
 
 //游戏结束
 function stop(){
  if(time){
   clearInterval(time)
   time = null;
  }
  document.onkeydown = null;
 }
 
 //声明键盘事件
 var bindKeyEvent = function(){
  document.onkeydown = function(e){
   switch(e.keyCode){
    case 38: //up
     game.up();
    break;
    case 39: //right
     game.right();
    break;
    case 40: //down
     game.down();
    break;
    case 37: //left
     game.left();
    break;
    case 32: //space
     game.fall();
    break;
   }
  }
 }
 
}

remote.js

?
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
//对方游戏区域
//这个js主要为对方的操作意识
var Remote = function(){
 //游戏对象
 var game;
 //开始 决定方块类型 和旋转方向
 var start = function(type,dir){
  //获取游戏中两个界面的dom元素
  var dom = {
   gameDiv:document.querySelector("#remote_game"),
   nextDiv:document.querySelector("#remote_next"),
   timeDiv:document.querySelector("#remote_time"),
   scoreDiv:document.querySelector("#remote_score"),
   local_tip:document.querySelector("#remote_tip")
  };
  //实例化Game;
  game = new Game();
  //并将dom传入到Game的初始化方法中
  game.init(dom,type,dir);
 };
 
 //绑定事件
 var bindEvents = function(){
  document.querySelector("#left").onclick = function(){
   game.left();
  }
  document.querySelector("#right").onclick = function(){
   game.right();
  }
  document.querySelector("#down").onclick = function(){
   game.down();
  }
  document.querySelector("#rotate").onclick = function(){
   game.up();
  }
  document.querySelector("#fall").onclick = function(){
   game.fall();
  }
  document.querySelector("#fixed").onclick = function(){
   game.fixed();
  }
  document.querySelector("#performNext").onclick = function(){
   game.performNext(2,2);
  }
  document.querySelector("#checkClear").onclick = function(){
   game.checkclear();
  }
  document.querySelector("#gameover").onclick = function(){
   game.gameover();
  }
  document.querySelector("#settime").onclick = function(){
   game.setTime(20);
  }
  document.querySelector("#addscore").onclick = function(){
   game.addscore(3);
  }
  document.querySelector("#gamestate").onclick = function(){
   game.gameState(true);
  }
  document.querySelector("#addTaiLines").onclick = function(){
   game.addTaiLines([[1,0,0,1,0,1,0,1,1,1]]);
  }
 }
 
 //导出方法
 this.start = start;
 this.bindEvents = bindEvents;
}

square.js

?
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
77
78
79
80
81
82
83
//所有的方块的公共逻辑 3
var square = function(){
 //方块提示框中的方块数据
 this.data = [
  [0,0,0,0],
  [0,0,0,0],
  [0,0,0,0],
  [0,0,0,0]
 ];
 this.dir = 0;
 
 //方块坐标原点
 this.origin={
  x:0,
  y:0
 }
};
 
//检测当前矩阵数据中的方块位置能否下降
square.prototype.canDown=function(isvalue){
 var test = {};
 //console.log(this.origin.x,this.origin.x + 1);
  //这里要加1的原因是因为 这个方法是在我们还没有执行到加1程序之前调用的
  //所以我们需要手动给它去加1
 test.x = this.origin.x + 1;
 test.y = this.origin.y;
 return isvalue(test,this.data);
};
 
square.prototype.canLeft=function(isvalue){
 var test = {};
 test.x = this.origin.x;
 test.y = this.origin.y - 1;
 return isvalue(test,this.data);
};
 
square.prototype.canRight=function(isvalue){
 var test = {};
 test.x = this.origin.x;
 test.y = this.origin.y + 1;
 return isvalue(test,this.data);
};
 
//下落方法 这个方法我们放到原型对象上 因为下落方法是主要的方法
square.prototype.onDown = function(){
 this.origin.x += 1;
};
 
square.prototype.onLeft = function(){
 this.origin.y -= 1;
};
 
square.prototype.onRight = function(){
 this.origin.y += 1;
};
 
 
//下面是旋转的功能
square.prototype.canRotate = function(isvalue){
 var testdir = (this.dir + 1)%4;//因为是在旋转指向前进行的判断 所以我们先加1
 var testrotate = [
  [0,0,0,0],
  [0,0,0,0],
  [0,0,0,0],
  [0,0,0,0]
 ];
 for(var i=0;i<this.data.length;i++){
  for(var j=0;j<this.data[i].length;j++){
   testrotate[i][j] = this.rotate[testdir][i][j]
  }
 }
 return isvalue(this.origin,testrotate);
};
 
square.prototype.onrotate = function(num){
 num = num|1;
 this.dir = (this.dir+num)%4;//因为是在旋转指向前进行的判断 所以我们先加1
 for(var i=0;i<this.data.length;i++){
  for(var j=0;j<this.data[i].length;j++){
   this.data[i][j] = this.rotate[this.dir][i][j]
  }
 }
};

squareFactory.js

?
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
//工厂 用于生成不同的方块
//所有的方块的公共逻辑 3
var square1 = function(){
 //这样写 当我们实例化square1的时候 square中this引用的成员将会添加到square1上
 square.call(this);
 //四个不同的旋转方向 默认是0 也就是第一个
 this.rotate = [
  [
   [0,2,0,0],
   [0,2,0,0],
   [0,2,2,0],
   [0,0,0,0]
  ],
  [
   [0,0,0,0],
   [2,2,2,0],
   [2,0,0,0],
   [0,0,0,0]
  ],
  [
   [2,2,0,0],
   [0,2,0,0],
   [0,2,0,0],
   [0,0,0,0]
  ],
  [
   [0,0,2,0],
   [2,2,2,0],
   [0,0,0,0],
   [0,0,0,0]
  ]
 ];
};
square1.prototype = square.prototype;//打通原型链
 
 
var square2 = function(){
 //这样写 当我们实例化square1的时候 square中this引用的成员将会添加到square1上
 square.call(this);
 //四个不同的旋转方向 默认是0 也就是第一个
 this.rotate = [
  [
   [0,2,0,0],
   [0,2,0,0],
   [0,2,0,0],
   [0,2,0,0]
  ],
  [
   [0,0,0,0],
   [2,2,2,2],
   [0,0,0,0],
   [0,0,0,0]
  ],
  [
   [0,2,0,0],
   [0,2,0,0],
   [0,2,0,0],
   [0,2,0,0]
  ],
  [
   [0,0,0,0],
   [2,2,2,2],
   [0,0,0,0],
   [0,0,0,0]
  ]
 ];
};
square2.prototype = square.prototype;
 
var square3 = function(){
 //这样写 当我们实例化square1的时候 square中this引用的成员将会添加到square1上
 square.call(this);
 //四个不同的旋转方向 默认是0 也就是第一个
 this.rotate = [
  [
   [0,2,0,0],
   [2,2,2,0],
   [0,0,0,0],
   [0,0,0,0]
  ],
  [
   [2,2,2,0],
   [0,2,0,0],
   [0,0,0,0],
   [0,0,0,0]
  ],
  [
   [0,2,0,0],
   [2,2,0,0],
   [0,2,0,0],
   [0,0,0,0]
  ],
  [
   [2,0,0,0],
   [2,2,0,0],
   [2,0,0,0],
   [0,0,0,0]
  ]
 ];
};
square3.prototype = square.prototype;
 
var square4 = function(){
 //这样写 当我们实例化square1的时候 square中this引用的成员将会添加到square1上
 square.call(this);
 //四个不同的旋转方向 默认是0 也就是第一个
 this.rotate = [
  [
   [2,2,0,0],
   [2,2,0,0],
   [0,0,0,0],
   [0,0,0,0]
  ],
  [
   [2,2,0,0],
   [2,2,0,0],
   [0,0,0,0],
   [0,0,0,0]
  ],
  [
   [2,2,0,0],
   [2,2,0,0],
   [0,0,0,0],
   [0,0,0,0]
  ],
  [
   [2,2,0,0],
   [2,2,0,0],
   [0,0,0,0],
   [0,0,0,0]
  ]
 ];
};
square4.prototype = square.prototype;
 
var square5 = function(){
 //这样写 当我们实例化square1的时候 square中this引用的成员将会添加到square1上
 square.call(this);
 //四个不同的旋转方向 默认是0 也就是第一个
 this.rotate = [
  [
   [0,0,0,0],
   [2,2,0,0],
   [0,2,2,0],
   [0,0,0,0]
  ],
  [
   [0,0,2,0],
   [0,2,2,0],
   [0,2,0,0],
   [0,0,0,0]
  ],
  [
   [0,0,0,0],
   [0,2,2,0],
   [2,2,0,0],
   [0,0,0,0]
  ],
  [
   [2,0,0,0],
   [2,2,0,0],
   [0,2,0,0],
   [0,0,0,0]
  ]
 ];
};
square5.prototype = square.prototype;
 
var square6 = function(){
 //这样写 当我们实例化square1的时候 square中this引用的成员将会添加到square1上
 square.call(this);
 //四个不同的旋转方向 默认是0 也就是第一个
 this.rotate = [
  [
   [0,2,0,0],
   [0,2,2,2],
   [0,0,0,0],
   [0,0,0,0]
  ],
  [
   [0,0,2,0],
   [0,0,2,0],
   [0,2,2,0],
   [0,0,0,0]
  ],
  [
   [2,2,2,0],
   [0,0,2,0],
   [0,0,0,0],
   [0,0,0,0]
  ],
  [
   [0,2,2,0],
   [0,2,0,0],
   [0,2,0,0],
   [0,0,0,0]
  ]
 ];
};
square6.prototype = square.prototype;
 
var square7 = function(){
 //这样写 当我们实例化square1的时候 square中this引用的成员将会添加到square1上
 square.call(this);
 //四个不同的旋转方向 默认是0 也就是第一个
 this.rotate = [
  [
   [2,2,0,0],
   [2,2,0,0],
   [2,2,0,0],
   [2,2,0,0]
  ],
  [
   [0,0,0,0],
   [2,2,2,2],
   [2,2,2,2],
   [0,0,0,0]
  ],
  [
   [2,2,0,0],
   [2,2,0,0],
   [2,2,0,0],
   [2,2,0,0]
  ],
  [
   [0,0,0,0],
   [2,2,2,2],
   [2,2,2,2],
   [0,0,0,0]
  ]
 ];
};
square7.prototype = square.prototype;
 
var squareFactory = function(){};
squareFactory.prototype.make=function(index,dir){
 var s;
 index+=1;
 switch (index) {
  case 1:
   s = new square1();
   break;
  case 2:
   s = new square2();
   break;
  case 3:
   s = new square3();
   break;
  case 4:
   s = new square4();
   break;
  case 5:
   s = new square5();
   break;
  case 6:
   s = new square6();
   break;
  case 7:
   s = new square7();
   break;
  default:
   break;
 }
 //因为一来square中的data矩阵默认全是0 所以我们需要给它一个旋转方向
 //让它有一个形状
 console.log(index,s);
 s.origin.x = 0;
 s.origin.y = 3;
 s.onrotate(dir);
 return s;
};

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/tdl081071tdy/article/details/91043667

延伸 · 阅读

精彩推荐