HTML5边玩边学(8):俄罗斯方块就是这么简单 之 数据模型篇

2023-11-09

特别提示:
本文中的运行效果需要 Chrome 浏览器或者 Firefox 浏览器。

 

一、从数据出发还是从界面出发

要写一个俄罗斯方块小游戏,我们先来一块考虑一下下面几个问题:

1、用什么表示方块

2、怎么设置或者改变方块的颜色

3、怎么移动方块

4、怎么消除方块

请考虑一分钟后再继续向下看。。。。。。

 

如果你对上面几个问题思考,每一个答案都和界面、控件、平台有关的话,就是说假如你是用 .Net 的,你的每一个答案都是围绕着如何利用控件、如何使用窗体、在控件的哪个事件里面改变哪个属性等等,那么说明你被微软的 RAD 开发环境毒害的不浅,我建议你立刻扔掉 Visual Studio,改用其他轻量级的编程语言和开发平台,这样你可以更多的关注问题的本身,而不是控件。

记住:程序 = 数据结构 + 算法

 

界面只是数据的表象,而数据才是问题的本质。

下面,我们将一步一步建立一个俄罗斯方块小游戏的数据模型,当整个模型建立完毕后,我们会发现,虽然没有界面,仍然不妨碍这是一个功能完整的俄罗斯方块游戏,因为发生的每一件事情都很清楚,我们只是没把它画而已。当然,后面我们会给出一个操作简易的界面,等到下一篇,会专门探讨界面的问题。

 

二、“形状”的数据模型

俄罗斯方块是一个经久不衰的小游戏,最常见的版本中一般有七个形状,分别是:

直线型、S型、Z型、L型、反L型、T型、方形等,如下图:

那么我们在程序中如何表示这七个形状呢?我们发现每一形状都是四个小方块组成的,我们完全可以用四个点表示。

但是问题又来了,四个点的坐标分别是什么呢?我查到的方法是:每个形状都有一个自己的坐标系,比如S型,可以入下图表示:

这样,S型的数据模型可以表示为四个点组成的数组:[ [ 0, -1 ],  [ 0, 0 ],   [ -1, 0 ],  [ -1, 1 ] ] 。

我们可以用同样的方法建立其他形状的数组模型,然后再将这七个形状的数组模型合起来组成一个大的数组。

另外,每个形状可以是单色,也可以有自己的颜色。增加颜色会增加编程的复杂度,但是也增加不了多少,所以我们的模型中也会考虑颜色。

最后,我们最好给每个形状一个编号,这样方便在形状数组和颜色数组中应用他们。

完成上面的分析后,我们就可以给出形状数据模型的代码了:

形状模型的代码
// 各种形状的编号,0代表没有形状
NoShape = 0 ;
ZShape
= 1 ;
SShape
= 2 ;
LineShape
= 3 ;
TShape
= 4 ;
SquareShape
= 5 ;
LShape
= 6 ;
MirroredLShape
= 7

// 各种形状的颜色
Colors = [ " black " , " fuchsia " , " #cff " , " red " , " orange " , " aqua " , " green " , " yellow " ];

// 各种形状的数据描述
Shapes = [
    [ [ 
0 0  ],   [  0 0  ],   [  0 0  ],   [  0 0  ] ],
    [ [ 
0 - 1  ],  [  0 0  ],   [  - 1 0  ],  [  - 1 1  ] ],
    [ [ 
0 - 1  ],  [  0 0  ],   [  1 0  ],   [  1 1  ] ],
    [ [ 
0 - 1  ],  [  0 0  ],   [  0 1  ],   [  0 2  ] ],
    [ [ 
- 1 0  ],  [  0 0  ],   [  1 0  ],   [  0 1  ] ],
    [ [ 
0 0  ],   [  1 0  ],   [  0 1  ],   [  1 1  ] ],
    [ [ 
- 1 - 1  ], [  0 - 1  ],  [  0 0  ],   [  0 1  ] ],
    [ [ 
1 - 1  ],  [  0 - 1  ],  [  0 0  ],   [  0 1  ] ]
];

 

三、定位和旋转形状

 

1、定位

我们上面说到每个形状都是在自己的坐标系里面描述的,另外还有一个全局坐标系,用来给形状定位,这样我们就需要一个方法将形状的四个点从自身坐标系转换到全局坐标系,从而给形状定位。

假如S型在自身坐标系中四个点的坐标为:[ [ 0, -1 ],  [ 0, 0 ],   [ -1, 0 ],  [ -1, 1 ] ]

它当前在全局坐标系位置为:[12,8]

则,四个点转换为全局坐标系的坐标为:[ [ 0+12, -1+8 ],  [ 0+12, 0+8 ],   [ -1+12, 0+8 ],  [ -1+12, 1+8 ] ]

这样,我们就完成了 S型 的全局坐标转换。

这里需要注意一个问题,形状自身坐标系是用 (x,y) 描述的,而全局坐标系为了逻辑上更直观,是用 (row,col) 描述的,所以我们在实际编程中并不是向上面那样转换的,而是:

[ [ -1+12, 0+8 ],  [ 0+12, 0+8 ],   [ 0+12, -1+8 ],  [ 1+12, -1+8 ] ]

即:先将 x 变为 col ,y 变为 row ,再转换为全局坐标系。

 

2、旋转

旋转是在形状的自身坐标系中,并围绕形状的原点完成的,公式很简单,每个点旋转后的坐标与旋转前坐标的关系如下(向右旋转):

x' = y

y' = -x 

注意:方块形状不发生旋转。

有了上面的分析,我们就可以给出两个全局方法,他们用来对形状进行全局定位和旋转:

全局定位和旋转的代码
// 将形状自身的坐标系转换为  Map 的坐标系,row col 为当前形状原点在 Map 中的位置
function translate(data,row,col){
    var copy
= [];
    
for (var i = 0 ;i < 4 ;i ++ ){
        var temp
= {};
        temp.row
= data[i][ 1 ] + row;
        temp.col
= data[i][ 0 ] + col;
        copy.push(temp);
    }
    
return  copy;
}

// 向右旋转一个形状:x'=y, y'=-x
function rotate(data){
    var copy
= [[],[],[],[]];
    
for (var i = 0 ;i < 4 ;i ++ ){
        copy[i][
0 ] = data[i][ 1 ];
        copy[i][
1 ] =- data[i][ 0 ];
    }
    
return  copy;
}

 

四、移动空间

前面我们说过,形状是由四个点组成的,而形状的移动空间也是由 m * n 个点组成的一个二维数组。

这里为了更直观的描述,我将 n 个点组成一条线 Line,再将 m 条 Line 组成形状的移动空间,我把它叫做 Map 。

我们有了这 m * n 个点有什么用呢?用处很简单,就是保存形状的编号,如果一个点没有被形状占用,则编号为 NoShape。这就是前面给出形状编号的用处,同时也是为什么要有一个 NoShape 编号的原因。

Map 应该具有什么功能呢?下面我列举了一些:

1、构造函数:这不用说了,n 个点组成一行 Line, m 行 Line 组成Map,每个点初始化成 NoShape

2、newLine:生成新的一行。为什么需要这个方法呢,因为除了构造函数中,游戏运行过程中我们也需要用到它,当一行或者几行被消除以后,我们需要在顶部假如一行或者几行新的Line

3、isFullLine(row):这个方法用来判断第 row 行是否满了,每次一个形状落地后,就需要对每一行进行这个判断,满了当然是消除了。

4、isCollide(data): data 是一个定位后的形状数据,这样我们就可以检查这些数据是否超出移动空间的上下左右边界,另外还检查数据的四个点是否已经被占用,这就是碰撞检测。

5、appendShape(shape_id,data):当一个形状落地以后,我们就应该将运行空间中某些点的值改变为这个形状的编号,我把这称为占用。

6、消除操作:这个功能没有单独列为一个方法,我把它放在 appendShape 方法中了。消除操作也很简单,发现某一行 isFullLine 了以后,在 lines 数组中移除这一行,并在 lines 数组的顶部加入一个空行即可。

有了上面的分析,我们就可以给出移动空间的代码了:

移动空间的代码
/*
 * 说明:由 m 行 Line 组成的格子阵
 
*/
function  Map(w,h){
    
// 游戏区域的长度和宽度
     this .width = w;
    
this .height = h;
    
// 生成 height 个 line 对象,每个 line 宽度为 width
     this .lines = [];
    
for (var row = 0 ;row < h;row ++ )
        
this .lines[row] = this .newLine();
}

// 说明:间由 n 个格子组成的一行
Map.prototype.newLine = function(){
    var shapes
= [];
    
for (var col = 0 ;col < this .width;col ++ )
        shapes[col]
= NoShape;
    
return  shapes;
}

// 判断一行是否全部被占用
// 如果有一个格子为 NoShape 则返回 false
Map.prototype.isFullLine = function(row){
    var line
= this .lines[row];
    
for (var col = 0 ;col < this .width;col ++ )
        
if (line[col] == NoShape)
            
return   false
    
return   true ;
}
/*
 * 预先移动或者旋转形状,然后分析形状中的四个点是否有碰撞情况:
 *      1:col<0 || col>this.width 超出左右边界
 *      2:row==this.height ,说明形状已经到最底部
 *      3:任意一点的 shape_id 不为 NoShape ,则发生碰撞
 *  如果发生碰撞则放弃移动或者旋转
 
*/
Map.prototype.isCollide
= function(data){
    
for (var i = 0 ;i < 4 ;i ++ ){
        var row
= data[i].row;
        var col
= data[i].col;
        
if (col < 0   ||  col == this .width)  return   true ;
        
if (row == this .height)  return   true ;
        
if (row < 0 continue ;
        
else
            
if ( this .lines[row][col] != NoShape)
                
return   true ;
    }
    
return   false ;
}

// 形状在向下移动过程中发生碰撞,则将形状加入到 Map 中
Map.prototype.appendShape = function(shape_id,data){
    
// 对于形状的四个点:
     for (var i = 0 ;i < 4 ;i ++ ){
        var row
= data[i].row;
        var col
= data[i].col;
        
// 找到所在的格子,将格子的颜色改为形状的颜色
         this .lines[row][col] = shape_id;
    }
    
// ========================================
    
// 形状被加入到 Map 中后,要进行逐行检测,发现满行则消除
     for (var row = 0 ;row < this .height;row ++ ){
        
if ( this .isFullLine(row)){
            
// 将满的那一行替换成新的空,这一步主要是为了显示效果,可以不要!
            
// this.lines[row]=null;
            
// 重绘 Map 消除效果
            
// onClearLine(row);
            
// 将满行删除
             this .lines.splice(row, 1 );
            
// 第一行添加新的一行
             this .lines.unshift( this .newLine());
            
// 重绘 Map 整行下落效果
            onDraw( this .lines);
        }
    }
}

 

 

五、游戏模型

我们有了游戏的数据模型,我们就可以读写他们了。所谓读好理解,所谓写就是改变他们,改变的方法当然是用户的操作了。

下面给出 GameModel 类,他维护三个主要的数据:

1、一个形状的编号,就是用户可以操作移动的那个形状

2、形状的全局位置,用 row col 表示

3、一个 Map,用它完成碰撞检测,添加等操作

另外,还抽象出几个用户的操作动作:

1、left:左移。将形状的全局坐标 col  减少 1 。请思考一下,这样就可以了吗?当然不行,我们还需要进行碰撞检测,如果已经在最左边,则放弃处理。

2、right:右移。同上。

3、rotate:旋转。同上。

4、down:下落。同上。下落过程中的碰撞检测有所不同,一旦发生碰撞,我们不能再放弃处理了,而是要将当前形状加入到空间中。

5、GameOver:下落过程中还需要进行一个检测就是游戏是否结束。如果当前形状在出生地点刚一下落就发生碰撞,说明已经到顶部了,则游戏结束。

有了上面的分析,我们就可以给出 GameModel 的代码:

GameModel 代码
/*
 * 说明:GameModel 类
 
*/
function GameModel(w,h){
    
this .map = new  Map(w,h);
    
this .born();
}

// 出生一个新的形状
GameModel.prototype.born = function(){
    
// 随机选择一个形状
     this .shape_id = Math.floor(Math.random() * 7 ) + 1 ;
    
this .data = Shapes[ this .shape_id];
    
// 重置形状的位置为出生地点
     this .row = 1 ;
    
this .col = Math.floor( this .map.width / 2 );
    
// 通知绘制移动效果,传回数据为形状的四个点在 Map 中的位置
    onMove( this .shape_id, this .map,translate( this .data, this .row, this .col));
}

// 向左移动
GameModel.prototype.left = function(){
    
this .col -- ;
    var temp
= translate( this .data, this .row, this .col);
    
if ( this .map.isCollide(temp))
    
// 发生碰撞则放弃移动
         this .col ++ ;
    
else
    
// 通知绘制移动效果,传回数据为形状的四个点在 Map 中的位置
        onMove( this .shape_id, this .map,temp);
}

// 向右移动
GameModel.prototype.right = function(){
    
this .col ++ ;
    var temp
= translate( this .data, this .row, this .col);
    
if ( this .map.isCollide(temp))
        
this .col -- ;
    
else
        onMove(
this .shape_id, this .map,temp);
}

// 旋转
GameModel.prototype.rotate = function(){
    
// 正方形不旋转
     if ( this .shape_id == SquareShape)  return ;
    
// 获得旋转后的数据
    var copy = rotate( this .data);
    
// 转换坐标系
    var temp = translate(copy, this .row, this .col);
    
// 发生碰撞则放弃旋转
     if ( this .map.isCollide(temp))
        
return ;
    
// 将旋转后的数据设为当前数据
     this .data = copy;
    
// 通知绘制移动效果,传回数据为形状的四个点在 Map 中的位置
    onMove( this .shape_id, this .map,translate( this .data, this .row, this .col));
}

// 下落
GameModel.prototype.down = function(){
    var old
= translate( this .data, this .row, this .col);
    
this .row ++ ;
    var temp
= translate( this .data, this .row, this .col);
    
if ( this .map.isCollide(temp)){
        
// 发生碰撞则放弃下落
         this .row -- ;
        
// 如果在 1 也无法下落,说明游戏结束
         if ( this .row == 1 ) {
            
// 通知游戏结束
            
// onGameOver();
            alert( " Game Over " )
            
return ;
        }
        
// 无法下落则将当前形状加入到 Map 中
         this .map.appendShape( this .shape_id,old);
        
// 出生一个新的形状
         this .born();
    }
    
else
    
// 通知绘制移动效果,传回数据为形状的四个点在 Map 中的位置
        onMove( this .shape_id, this .map,temp);
}

 

 

六、一个简单的操作界面

虽然到现在为止,我们没有给出一行和界面有关的代码,但是整个游戏在逻辑上已经完全可以运行起来了,只是我们没有把他画出来而已,要想把他画出来也很简单。

注意上面给出的代码中很多地方调用了两个全局函数:onDraw 和 onMove ,这两个函数就是用来进行绘制的。

绘制的代码其实只占很少的一部分,其中一些绘图函数我为了方便对 HTML5 的 2D 函数进行了简单的封装,您完全可以用原生的 HTML5 函数,或者用您自己平台的绘图函数,因为他们本身不是太复杂。

另外有一个全局变量 Spacing ,他表示一个格子的宽度。

下面给出操作界面的代码:

界面操作代码
// 每一格的间距,也即一个小方块的尺寸
Spacing = 20 ;

// 在内存中绘制一个小方块
function drawRect(color){
    var temp
= new  Surface(Spacing,Spacing, " rgba(255,255,255,0.2) " ); // 背景色
    temp.fillRect( 1 1 , Spacing - 2 , Spacing - 2 , color); // 前景色
     return  temp;
}

var display
=  Display.attach(document.getElementById( " html5_09_1 " ));
var model 
=   new  GameModel(display.width / Spacing,display.height / Spacing);


function onDraw(map){
    
// 清屏
    display.clear();
    var lines
= map.lines;
    
// 依次绘制每一个非空的格子
     for (var row = 0 ;row < map.height;row ++ )
        
for (var col = 0 ;col < map.width;col ++ ){
            var shape_id
= lines[row][col];
            
if (shape_id != NoShape){
                var rect 
=  drawRect(Colors[shape_id]);
                var y
= row  *  Spacing;
                var x
= col  *  Spacing;
                display.draw(rect, x, y);
            }
    }
}

function onMove(shape_id,map,data){
    onDraw(map);
    
// 绘制当前的形状
     for (var i = 0 ;i < 4 ;i ++ ){
        var y
= data[i].row  *  Spacing;
        var x
= data[i].col  *  Spacing;
        var rect 
=  drawRect(Colors[shape_id]);
        display.draw(rect, x, y);
    }
}

function down(){
    model.down();
}

function left(){
    model.left();
}

function right(){
    model.right();
}

function rotate_click(){
    model.rotate();
}

 

 

HTML 代码很简单,也给出来吧,就一块画布和四个按钮,如下:

HTML 代码
< canvas  id ="html5_09_1"  width ="260"  height ="400"  style =" background-color: black " >
    你的浏览器不支持 Canvas 标签,请使用 Chrome 浏览器 或者 FireFox 浏览器
</ canvas >< p />
< input  type ="button"  value ="向下"  onclick ="down()" />
< input  type ="button"  value ="向左"  onclick ="left()" />
< input  type ="button"  value ="向右"  onclick ="right()" />
< input  type ="button"  value ="旋转"  onclick ="rotate_click()" />

 

 

七、运行效果

{{{{{{

}}}}}}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HTML5边玩边学(8):俄罗斯方块就是这么简单 之 数据模型篇 的相关文章

  • 实战: 跨年烟花代码的实现(附源码)

    目录 前言 一 pandas是什么 二 代码结构 1 介绍主html代码 2 js文件介绍 GameCanvas js script js 运行效果 前言 本文章将介绍跨年烟花代码的实现以及源代码 提示 以下是本篇文章正文内容 一 pand
  • HTML5本地存储

    1 背景 在HTML4 01中 想要在浏览器中存储用户的数据时 我们一般只能用Cookie来实现 不过Cookie有很多限制 大小限制 最大4KB 数量限制 每个站点只允许存储20个Cookie 如果想要存储更多Cookie 则要把旧的Co
  • 【H5】 svg内text、image、path标签的使用

    H5 svg内text image path标签的使用 text标签 div style width 500px height 500px border 2px solid pink margin 50px auto 0 div
  • 基于SSM 和 layui 的增删查改

    开发工具 IDEA 2021 WebStorm 2021 Mysql 8 0 开发环境 JDK 8 TomCat 8 5 81 apache maven 3 6 1 技术点 Spring SpringMVC Mybatis Mysql Ht
  • 前端学习之常见标签的使用(2)

    目录 h标签 p标签 br标签 字符实体 img标签 a标签 mailto链接 base标签 锚点 div span video H5新增 audio H5新增 h标签 h标签 标题标签 在HTML中 一共有六级标题标签 h1 h6 在显示
  • 动态一键换肤实现思路和demo

    前言 浏览器切换样式无非是通过css 总共有以下三种方法 内联style 注入style 注入link 那么我们想要实现一键换肤 那么我们为了剥离干净dom和css 我们只能选择style和link这两种方法 核心思路 在html的head
  • 前端学习——JavaScript原生实现购物车案例

    一 购物车案例 1 1 案例介绍 今天我们来写另外一个购物车案例 说实话对于我来说这个是花了将近三个小时的时间然后才做出来的 里面可能还存在一些我没有发现的问题 但是能完成基本的功能 对于一些基本的需求都是可以完成的 下面照旧是案例实现的g
  • CSS 浏览器缩小之后页面错乱 块不见问题

    问题1 浏览器正常100 显示的时候 今日推荐是看得见的 浏览器缩小 小于100 之后 今日推荐被挤不见了 今日推荐块的DIV的CSS原配置是 today recommend py container width 1200px margin
  • 修改网页logo

    在用浏览器打开网站的时候 浏览器标签页上面有网站的图标 类似于logo小图标 如下图 步骤1 打开你的tomcat的安装目录 我的目录实在G盘 G apache tomcat 7 0 53 windows x64 apache tomcat
  • JavaScript基础Day02:流程控制

    文章目录 1 顺序结构 2 分支结构 1 if语句 2 switch语句 3 循环结构 1 while语句 2 do while语句 3 for循环 1 顺序结构 2 分支结构 1 if语句 if 条件表达式 执行语句 if 条件表达式 成
  • Vue中鼠标悬停更换图片/文字内容,动态展示/修改某些属性

    Vue中鼠标悬停更换图片 文字内容 动态展示 修改某些属性 鼠标悬停时 mouseenter 鼠标离开时 mouseleave 利用以上来绑定相应方法 例如 div 分别为鼠标悬停时和离开时绑定方法changeImageSrc 并传递参数
  • Web前端开发概述

    Web World Wide Web 全球广域网 是指一种基于互联网的信息系统 通过超文本链接将全球各地的文档 图像 视频等资源相互关联起来 并通过Web浏览器进行交互浏览和访问 Web的发展使得人们可以方便地获取和共享各种类型的信息 成为
  • HTML学习

    HTML 我的第一个网页 基本标签 图片标签 链接标签 列表 表格 媒体元素 页面结构分析 iframe内联框架 表单 我的第一个网页
  • c语言药房管理系统

    include
  • angular:路径找不到时会跳回主页

    本地起服时 如果输入的路径无法匹配现有规则 则会跳转至主页 带来一定困扰 最好是统一显示或者导航至特定页面 以便debug const routes Routes path component PageNotFoundComponent
  • jquery attr()方法 添加,修改,获取对象的属性值

    转自 http hi baidu com 0701u item b8ec62c1daba973eef466524 jquery中用attr 方法来获取和设置元素属性 attr是attribute 属性 的缩写 在jQuery DOM操作中会
  • 12.HTML5下一代的HTML标准介绍与初识尝试

    关注回复 学习交流群 加入 安全开发运维 答疑交流群 请朋友们 多多点击文中的广告 支持作者更新更多文章 目录 本文为作者原创文章 为尊重作者劳动成果禁止非授权转载 若需转载请在 全栈工程师修炼指南 公众号留言 或者发送邮件到 master
  • align-content 设置多行下的子元素排列方式 代码和图片展示

    align content 适用于 换行 多行 的情况下 单行无效 可以设置上对齐 居中拉伸和平均分配剩余空间等属性值 属性值 flex start 默认值 在侧轴头部开始排列 flex end 在侧轴尾部开始排列 center 在侧轴中间
  • HTML5学习(三):布局标签、列表、超链接和id

    1 布局标签 header表示网页的头部 页眉 main表示网页的主体部分 一个页面中只会有一个main footer表示网页的底部 页脚 nav表示网页中的导航 aside和主体相关的其他内容 侧边栏 article表示一个独立的文章 s
  • 第8章 多媒体嵌入

    学习目标 了解视频 音频嵌入技术 能够总结HTML5视频 音频嵌入技术的优点 了解常用的视频文件格式和音频文件格式 能够归纳HTML5支持的视频和音频格式 掌握HTML5中视频的嵌入方法 能够在HTML5页面中添加视频文件 掌握HTML5中

随机推荐

  • SpringCloudAlibaba - Seata (1) 各模式详解、微服务集成、集群搭建

    文章目录 分布式事务模型 Seata 架构 部署 TC 服务 微服务集成 Seata XA 模式 Seata 实现的 XA 模式 XA 模式的具体实践 AT 模式 AT 模式与 XA 模式最大的区别 AT 模式下的脏写问题 AT 模式的具体
  • 非常详细的Django使用Token(转)

    基于Token的身份验证 在实现登录功能的时候 正常的B S应用都会使用cookie session的方式来做身份验证 后台直接向cookie中写数据 但是由于移动端的存在 移动端是没有cookie机制的 所以使用token可以实现移动端和
  • C#添加配置文档基础

    程序编译后在日常使用中是无法更改固定参数的 如果需要更改里面的参数每次都要改动源代码这将变得非常麻烦 所以我们可以使用到配置文档 这里将介绍配置文档最基础的使用方法 1 新建一个App config文件 在项目中新建一个App config
  • DETR系列大盘点

    点击下方卡片 关注 自动驾驶之心 公众号 ADAS巨卷干货 即可获取 点击进入 自动驾驶之心 目标检测 技术交流群 后台回复 2D检测综述 获取鱼眼检测 实时检测 通用2D检测等近5年内所有综述 自从VIT横空出世以来 Transforme
  • cookie设置为关闭浏览器后清除,打开后cookie还是没有清除

    今天踩了几个cookie的坑 花了我2小时 问题是这样的 我给aaa域名下的a html页面设置了一条很简单的cookie document cookie name abc 这样设置后默认为关闭浏览器后清除该cookie 可是关闭后打开co
  • vue elementUI 之 this.$confirm 的使用

    当进行一些操作时 有时需要弹出一些确定信息 一般有两种形式 提示框和确认框 通常为一个确定动操作 一个取消操作 如下 this confirm 您确定删除吗 提示 confirmButtonText 确定 cancelButtonText
  • Windows 系统下常用的八个网络配置命令

    一 ipconfig ipconfig 是 Windows 网络中最常使用的命令 用于显示计算机中网络适配器的 IP 地址 子网掩码及默认网关等信息 命令基本格式 ipconfig all renew adapter release ada
  • Modbus RTU简介(上)

    1 前言 1 1 什麽是Modbus Modbus是一种用于工业控制的标准通信协议 它定义了装置之间在应用层的消息封装模式 沟通方法 沟通顺序 Modbus的优势 Modbus协议是开源免费的 Modbus支援多种常见工控接口 RS232
  • 服务器里修改登录密码,云服务器修改登录密码

    云服务器修改登录密码 内容精选 换一换 如果密码丢失 或创建时未设置密码 推荐您在控制台设置登录密码 如果密码丢失 或创建时未设置密码 推荐您在控制台设置登录密码 云服务器修改登录密码 相关内容 当云服务器密码即将过期 密码泄露或首次登录时
  • #关于pytorch和torchvision对应版本#

    pytorch和torchvision对应版本记录 进入pytorch官网查看历史版本 有对应信息pytorch历史版本 比如pytorch1 5 1对应torchvision0 6 1 CUDA 9 2 conda install pyt
  • LVGL v7 使用心得及工具分享

    1 v7与v8的区别 对于v7来说 并没有v8优化的那么全面和完善 有些好用的功能在v7中也并未实现 但这并不代表v7就不好 在稳定性和兼容性这方面v7做的比v8好很多 虽然现在大多数都能上v8 其次v7与v8是两个大版本变动 很多API都
  • SQLServer与MySQL的一些常用操作加字段、修改字段、重置自增ID

    SQLServer与MySQL的一些常用操作 总结一些SQLServer与MySQL的一些常用操作 添加字段 修改字段 重置自增ID 添加字段 SQLServer 在SQLServer中 我们可以使用ALTER TABLE命令来添加表字段
  • UE4 禁用引擎Runtime模式下的引擎内置按键

    本文内容主要讲解在开发过程中 不想用引擎自带的按键如何禁用它 这些按键类似于一个快捷键工具例如F1 F5之类的按键 但最终打包成发行版的项目会自动禁用这些按键 所以不用担心用户会误触这些按键 1 找到引擎目录下的BaseInput ini文
  • sql中的coalesce函数

    COALESCE函数是一个SQL中的标准函数 它用于返回多个表达式中的第一个非NULL值 它的通常用途是在查询中提供默认值以避免NULL值 COALESCE函数的语法如下 COALESCE expression1 expression2 e
  • Elementui的select怎么获取选中的对象

    今天在开发中碰到了这样一个问题 平常使用select只是获取到他的值就可以了 突然需要获取选中的对象 倒是一下有些无从下手 也看了一些别人的文章 基本都没有很清晰的指出方法 我在这里做一个备注
  • 网站服务器速度快取决于,建站经验 网站打开速度快慢的因素

    判断一个网站打开速度快或者是慢主要取决于以下一些因素 一 网页内容的大小 网页内容所包括的文本 产品的图片 静态的 动态的 视频 flash文件等 这里涉及到浏览器的原理 浏览器的技术原理就是将网页下载到客户本地缓存 然后通过浏览器解析源码
  • 网易2018校园招聘编程题真题集合 (部分)

    第一题 小易准备去魔法王国采购魔法神器 购买魔法神器需要使用魔法币 但是小易现在一枚魔法币都没有 但是小易有两台魔法机器可以通过投入x x可以为0 个魔法币产生更多的魔法币 魔法机器1 如果投入x个魔法币 魔法机器会将其变为2x 1个魔法币
  • hive报metadata.HiveException: Hive Runtime Error while processing row (tag=0)错误

    今天跑一条统计的SQL出现Caused by org apache hadoop hive ql metadata HiveException Hive Runtime Error while processing row tag 0 ke
  • android -------- AES加密解密算法

    AES加密标准又称为高级加密标准Rijndael加密法 是美国国家标准技术研究所NIST旨在取代DES的21世纪的加密标准 AES的基本要求是 采用对称分组密码体制 密钥长度可以为128 192或256位 分组长度128位 算法应易在各种硬
  • HTML5边玩边学(8):俄罗斯方块就是这么简单 之 数据模型篇

    HTML5边玩边学 8 俄罗斯方块就是这么简单 之 数据模型篇 特别提示 本文中的运行效果需要 Chrome 浏览器或者 Firefox 浏览器 一 从数据出发还是从界面出发 要写一个俄罗斯方块小游戏 我们先来一块考虑一下下面几个问题 1