javascript实现俄罗斯方块游戏分析及源代码共享
看编程之美:程序很难写,但它是美妙的。为了写程序,我们需要写一些基础知识,包括编程语言,数据结构与算法,程序写的很好,需要缜密的逻辑思维和良好的梳理基础上,而熟悉与编程环境和编程工具。你已经爱上编程好几年了,你不想自己编写一个游戏,而不是喜欢编程。
俄罗斯方块已经引起了轰动,它的经济价值可以说是游戏历史上的一件大事,它看似简单却又让人沉迷于无数的变化。我相信大部分学生都痴迷于茶而不去想它。
游戏规则
1。一个平面虚拟场地,放置一个小正方形,它的标准尺寸为10行宽度和20列高度,每个小正方形作为一个单元。
2,一组由4个小正方形组成的规则图形。英语被称为构造,中国俗称钻石。他们有7种。它们分别以s、z、l、j、i、o和t 7个字母命名。
一次最多消除四层
J(左右):消除三层或至多消除两层
l:最大消除三层,或消除两层
o:消除一到两层
s(左右):最多两层,容易造成漏洞。
z(左右):最多两层,容易造成孔洞。
T:最多两层
块将开始慢慢地从区域上落。玩家可以旋转90度的平方在一个单元和移动方格子为单位减速块。当块移动到该区域的底部或当它移动到其他块,这将是固定的,和新的块将落在该地区的顶部。当区内柱横向网格充满了所有的方块,柱将消失,成为玩家的得分。同时,更列删除的号码,得分指数增加。
分析及解决方案
当每一个街区倒塌时,我们都能做到:
1)朝正确方向旋转
2)水平移动到某一列
3)垂直下降到末端
首先,你需要使用一个二维数组,其中地区{ 18 } { 10 }代表18×10.among他们游戏区,0空数组的中位数,而1是一个正方形。
有7种方块,每个都有4个方向。定义activeblock { 4 },在编制预计将好的数组的值,直接在程序中使用。
困难
1)边境检查。
检查左边界,尝试向左移动,看看是否合法。
功能checkleftborder(){
对于(var i = 0;i < activeblock.length;i++){
如果(activeblock {我},y = = 0){
返回false;
}
如果(!IsCellValid(activeblock {我},X,activeblock {我},y-1)){
返回false;
}
}
返回true;
类似地,需要检测正确的边界和底部边界。
2)旋转,对数学逻辑的需要,一个点相对于另一个点旋转90度。
3)计时和监控键盘事件机制,使游戏自动运行。
函数开始(e){
e.disabled =真;
状态= 1;
TBL = document.getelementbyid(地区);
如果(!GenerateBlock()){
警报(游戏结束)!;
状态= 2;
返回;
}
油漆();
定时器= setInterval(向下移动,1000);
}
文档化特点;
程序过程
1)开始>构建图形用户活动,设置计时器。
当前框的活动,可以是关于下一个移动,变量。当它触及底部时,区域将被更新。
无功activeblock;
生产盒形,有7种基本形状。
功能generateblock(){
activeblock = null;
activeblock =新阵(4);
/ / 0-6随机生成的阵列,7种具有代表性的。
var t =(math.floor(Math.random()* 20)+ 1)% 7;
开关(T){
案例0:{
activeblock { 0 } = { x 0,y 4 };
activeblock { 1 } = { x 1,y 4 };
activeblock { 2 } = { x 0,y 5 };
activeblock { 3 } = { x 1,y 5 };
打破;
}
/ /省略的代码..............................部分
案例6:{
activeblock { 0 } = { x 0,y 5 };
activeblock { 1 } = Y:4 },{ x:1;
activeblock { 2 } = { x 1,y 5 };
activeblock { 3 } = { x 1,y 6 };
打破;
}
}
四小框检查是否只需将生产放在初始化位置即可。
对于(var i = 0;i < 4;i + +){
如果(!IsCellValid(activeblock {我},X,activeblock {我},y)){
返回false;
}
}
返回true;
}
2)每次你向下移动时,检查一下你是否触到了底部。如果你摸到底部,试着消除它。
行/行
功能deleteline(){
var线= 0;
对于(var i = 0;i < 18;i + +){
var j=0;
用于((;j < 10;j + +){)
如果(区域{ = } = 0){
打破;
}
}
如果(j=10){
线条+;
如果(i)!= 0){
对于(VAR K = i-1;K>=0;K){
区域{ + 1 } =区域{ };
}
}
地区{ 0 } = generateblankline();
}
}
回归线;
}
3)完成一个活动图形后,再设置定时器。
设计素描
需要优化
1)设置不同形状正方形的颜色。
思路:在创建块的功能,设置activeblockcolor颜色,和七块不同形式有不同的颜色。除了修改generateblock方法,我们需要修改paintarea方法。因为最初的考虑是不完整的。删除一行后,油漆块和统一颜色的同时。因此,我们可以考虑删除N行,然后在顶部添加n行,以确保块完整性不被消除。
2)当当前块下降时,可以预先查看下一个块。
思路:这generateblock方法分为两部分。其中一部分用于随机尝试下一块,另一部分是缓存当前描述的块。当当前块固定在底部时,下一块开始描绘,新块又随机生成。
完整的HTML源代码:
俄罗斯方块
* {
字体微软雅黑;
}
tetriscontainer {。
宽度:230px;
身高:400px;
职位:相对;
左:50%;
margin-left: - 115px;
顶部:40%;
边距:- 200px;
}
#区TR TD {
宽度:20px;
身高:20px;
边境:1px solid # CCC;
}
得分:0
tetris.js完整源代码:
*俄罗斯方块俄罗斯方块游戏V 1
* /
表页,该表将显示主面板游戏。
VaR方法;
游戏没有启动0:1;2停止操作;
无功状态= 0;
会做 / /定时器,定时器向下移动
VaR的定时器;
分数
var得分= 0;
区域是一个18×10的数组,对应于页面表,开始时是0,如果占用的话是1。
var区域=新数组(18);
对于(var i = 0;i < 18;i + +){
区域{新数组}(10);
}
对于(var i = 0;i < 18;i + +){
对于(var j=0;j<10;j + +){
区域{ { } = 0;
}
}
当前框的活动,可以是关于下一个移动,变量。当它触及底部时,区域将被更新。
无功activeblock;
生产盒形,有7种基本形状。
功能generateblock(){
activeblock = null;
activeblock =新阵(4);
/ /随机0-6阵列,7种具有代表性的。
var t =(math.floor(Math.random()* 20)+ 1)% 7;
开关(T){
案例0:{
activeblock { 0 } = { x 0,y 4 };
activeblock { 1 } = Y:4 },{ x:1;
activeblock { 2 } = { x 0,y 5 };
activeblock { 3 } = { x 1,y 5 };
打破;
}
案例1:{
activeblock { 0 } = { x 0,y 3 };
activeblock { 1 } = { x 0,y 4 };
activeblock { 2 } = { x 0,y 5 };
activeblock { 3 } = { x 0,y 6 };
打破;
}
案例2:{
activeblock { 0 } = { x 0,y 5 };
activeblock { 1 } = { x 1,y 4 };
activeblock { 2 } = { x 1,y 5 };
activeblock { 3 } = { x 2,y 4 };
打破;
}
案例3:{
activeblock { 0 } = { x 0,y 4 };
activeblock { 1 } = { x 1,y 4 };
activeblock { 2 } = { x 1,y 5 };
activeblock { 3 } = { x 2,y 5 };
打破;
}
案例4:{
activeblock { 0 } = { x 0,y 4 };
activeblock { 1 } = { x 1,y 4 };
activeblock { 2 } = { x 1,y 5 };
activeblock { 3 } = { x 1,y 6 };
打破;
}
案例5:{
activeblock { 0 } = { x 0,y 4 };
activeblock { 1 } = { x 1,y 4 };
activeblock { 2 } = { x 2,y 4 };
activeblock { 3 } = { x 2,y 5 };
打破;
}
案例6:{
activeblock { 0 } = { x 0,y 5 };
activeblock { 1 } = Y:4 },{ x:1;
activeblock { 2 } = { x 1,y 5 };
activeblock { 3 } = { x 1,y 6 };
打破;
}
}
四小框检查是否只需将生产放在初始化位置即可。
对于(var i = 0;i < 4;i + +){
如果(!IsCellValid(activeblock {我},X,activeblock {我},y)){
返回false;
}
}
返回true;
}
向下移动
函数向下移动(){
检查底部边界。
如果(checkbottomborder()){
/不是底部,擦除当前图形,
擦除();
图形更新
对于(var i = 0;i < 4;i + +){
activeblock {我},{我} activeblock x = x + 1;
}
/ /重绘当前图形
油漆();
}
底部,
别的{
停止当前定时器自动停机。
ClearInterval(定时器);
更新区域数组。
Updatearea();
行/行
VaR线= deleteline();
如果有 /行。
如果(行)!= 0){
更新部分
得分=线+ 10;
UpdateScore();
擦除整个面板
Erasearea();
/ /重画面板
paintarea();
}
生成一个新的图形并确定它是否可以放在第一位。
如果(!GenerateBlock()){
警报(游戏结束)!;
状态= 2;
返回;
}
油漆();
/ /定时器,每隔一秒执行一个向下移动
定时器= setInterval(向下移动,1000)
}
}
向左移动
功能向左移动(){
如果(checkleftborder()){
擦除();
对于(var i = 0;i < 4;i + +){
activeblock {我},y = activeblock {我} Y - 1;
}
油漆();
}
}
右/莫比尔
函数向右移动(){
如果(checkrightborder()){
擦除();
对于(var i = 0;i < 4;i + +){
activeblock {我},{我activeblock Y = y + 1 };
}
油漆();
}
}
旋转,因为旋转后可能覆盖现有的网格正方形。
/ /一个tmpblock第一,activeblock的内容复制到tmpblock,
的tmpblock / /尝试旋转,如果经过测试没有发现网格旋转冲突。
旋转tmpblock /价值activeblock。
函数旋转(){
无功tmpblock =新阵(4);
对于(var i = 0;i < 4;i + +){
我tmpblock { } = { x 0,y 0 };
}
对于(var i = 0;i < 4;i + +){
tmpblock {我},x = activeblock {我} X;
tmpblock {我},y = activeblock {我};
}
中心点/前四点,围绕90度旋转中心的四点。
VaR CX = math.round((tmpblock { 0 }。x + tmpblock { 1 }。x + tmpblock { 2 }。x + tmpblock { 3 }。x) / 4);
VaR CY = math.round((tmpblock { 0 }。Y + tmpblock { 1 }。Y + tmpblock { 2 }。Y + tmpblock { 3 }。y) / 4);
主算法旋转。它可以被分解来理解。
围绕源旋转/第一个假设,然后添加中心点坐标。
对于(var i = 0;i < 4;i + +){
tmpblock {我},x = cx +环磷酰胺activeblock {我};
tmpblock {我},y = CY CX + activeblock {我} X;
}
检查旋转网格后是否合法。
对于(var i = 0;i < 4;i + +){
如果(!IsCellValid(tmpblock {我},X,tmpblock {我},y)){
返回;
}
}
如果合法的,擦除
擦除();
的activeblock /重新分配。
对于(var i = 0;i < 4;i + +){
activeblock {我},x = tmpblock {我} X;
activeblock {我},y = tmpblock {我};
}
/ /重绘。
油漆();
}
检查左边界,尝试向左移动,看看是否合法。
功能checkleftborder(){
对于(var i = 0;i < activeblock.length;i++){
如果(activeblock {我},y = = 0){
返回false;
}
如果(!IsCellValid(activeblock {我},X,activeblock {我},y-1)){
返回false;
}
}
返回true;
}
检查右边界,试着向右边移动,是否合法。
功能checkrightborder(){
对于(var i = 0;i < activeblock.length;i++){
如果(activeblock {我},y = = 9){
返回false;
}
如果(!IsCellValid(activeblock {我},X,activeblock {我},y + 1)){
返回false;
}
}
返回true;
}
检查底部边界,试着向底部移动,看看是否合法。
功能checkbottomborder(){
对于(var i = 0;i < activeblock.length;i++){
如果(activeblock {我},x = = 17){
返回false;
}
如果(!IsCellValid(activeblock {我}。x + 1,activeblock {我},y)){
返回false;
}
}
返回true;
}
检查坐标(x,y),如果该区域已经存在,则该正方形不合法。
功能iscellvalid(x,y){
如果(x > 17 | | X9 | | y<0){
返回false;
}
如果(区域{ = } = 1){
返回false;
}
返回true;
}
擦除
函数擦除(){
对于(var i = 0;i < 4;i + +){
Tbl。行activeblock { } { }。X。细胞activeblock { } { }。Y。风格。背景颜色为白色;
}
}
绘制活动图
功能漆(){
对于(var i = 0;i < 4;i + +){
Tbl。行activeblock { } { }。X。细胞activeblock { } { }。Y。风格。背景颜色=# cc3333 ;
}
}
更新区域数组
功能updatearea(){
对于(var i = 0;i < 4;i + +){
地区activeblock {我} { } { x activeblock {我} Y } = 1;
}
}
行/行
功能deleteline(){
var线= 0;
对于(var i = 0;i < 18;i + +){
var j=0;
用于((;j < 10;j + +){)
如果(区域{ = } = 0){
打破;
}
}
如果(j=10){
线条+;
如果(i)!= 0){
对于(VAR K = i-1;K>=0;K){
区域{ + 1 } =区域{ };
}
}
地区{ 0 } = generateblankline();
}
}
回归线;
}
擦除整个面板
功能erasearea(){
对于(var i = 0;i < 18;i + +){
对于(var j=0;j<10;j + +){
Tbl。行{ } { }。细胞J。style.backgroundcolor =白色;
}
}
}
/ /重画整个面板
功能paintarea(){
对于(var i = 0;i < 18;i + +){
对于(var j=0;j<10;j + +){
如果(区域{ = } = 1){
Tbl。行{ } { }。细胞J。style.backgroundcolor =# cc3333 ;
}
}
}
}
有空行。
功能generateblankline(){
var =新数组(10);
对于(var i = 0;i < 10;i + +){
行{ }=0;
}
回归线;
}
更新部分
功能updatescore(){
document.getelementbyid(得分)。innerText = +分数;
}
键盘控制
功能键控(){
如果(状态)!= 1){
返回;
}
VaR的代码的情况下;
开关(代码){
案例37:{
向左移动();
打破;
}
案例38:{
旋转();
打破;
}
案例39:{
MoveRight();
打破;
}
案例40:{
向下移动();
打破;
}
}
}
函数开始(e){
e.disabled =真;
状态= 1;
TBL = document.getelementbyid(地区);
如果(!GenerateBlock()){
警报(游戏结束)!;
状态= 2;
返回;
}
油漆();
定时器= setInterval(向下移动,1000);
}
文档化特点;