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):俄罗斯方块就是这么简单 之 数据模型篇 的相关文章

  • WebGL 实践篇(五)三维图形的绘制及矩阵变换、正射投影

    一 三维 F 的绘制 1 着色器 按照上一篇提到的矩阵变换 我们可以直接在顶点着色器中加入相应的矩阵变换 这样就可以简化着色器代码 通过变量传入矩阵的值也便于之后矩阵变换的修改 三维图形的绘制相比于二维图形只在参数类型上有一些变化 注意ve
  • 兼容ios不支持的日期格式

    前段时间开发了一个关于订单展示的页面 要求根据时间筛选出离当前时间最近的订单信息进行展示 因为服务器返回的时间格式都是 YYYY MM DD 也没想那么多 直接拿过来就用了 在安卓上排序都很正常 在测试的时候发现苹果手机展示的订单根本就没有
  • Uncaught SyntaxError: Unexpected end of input

    Uncaught SyntaxError Unexpected end of input 最近做项目遇到这样一个问题Uncaught SyntaxError Unexpected end of input Unexpected end of
  • 在react中如何结合antd实现分页功能

    在react中如何结合antd实现分页功能 步骤如下 1安装antd npm i antd s 2在 src App css中引入 antd dist antd css import antd dist antd css 3在需要用分页器的
  • navigator.mediaDevices.getUserMedia()出现NotReadableError Could not start audio source错误的解决办法

    问题是 支持了navigator mediaDevices getUserMedia 的方法 但没有权限去调起麦克风导致的问题 解决方案 手动到手机 设置 隐私 授权录音或者麦克风对该app的使用权限
  • HTML5编程简介及示例代码

    HTML5是一种用于构建网页和Web应用程序的标准 它引入了许多新的元素 属性和API 为开发者提供了更多的功能和灵活性 在本文中 我们将探讨HTML5编程的一些不同方面 并提供相应的示例代码 标题 Headings HTML5引入了新的标
  • 【HTML】用户名、身份证号、邮箱、验证

    为了使页面不是那么突兀 特地导入了这俩个bootstrap框架相关的包
  • innerHTML与XSS攻击

    HTML5为所有元素提供了一个innerHTML属性 既能获取对象的内容又能向对象插入内容 属性值 HTML标签 文本 浏览器会将属性值解析为相应的DOM树 HTML解析器在浏览器中是底层代码比JavaScript方法快很多 同时意味着替换
  • 移动端页面禁止放大缩小

    安卓 在index html文件中添加meta标签 IOS 在 src app vue 中 script 标签内添加代码
  • 【H5】 svg动画 旋转属性与虚线属性

    svg 动画 旋转 transform rotate angle x y 不要写在style里面 angle 旋转角度 x y旋转中心 绘制虚线 stroke dasharray a b a b c d 旋转属性 transform rot
  • 第八站:JavaScript的数据类型、运算符、流程控制语句

    第八站 JavaScript的数据类型 运算符 流程控制语句 欢迎来到第八站 JavaScript的数据类型 运算符 流程控制语句 在这一站 我们将深入探索JavaScript中的核心概念 为你揭示这个语言的奇妙之处 准备好继续冒险了吗 让
  • 前端学习——JavaScript原生实现购物车案例

    一 购物车案例 1 1 案例介绍 今天我们来写另外一个购物车案例 说实话对于我来说这个是花了将近三个小时的时间然后才做出来的 里面可能还存在一些我没有发现的问题 但是能完成基本的功能 对于一些基本的需求都是可以完成的 下面照旧是案例实现的g
  • 如何给证件照换一个背景颜色

    我们在考试报名的时候 经常是不同的考试需要不同的登记照尺寸和背景颜色 但是我们基本上不可能每种颜色的证件照都去拍一张吧 那样也太麻烦成本也太高 所以通过前端实现了一个改变证件照背景颜色的方法 他可以将证件照的背景颜色修改为任意的颜色 而不局
  • Web前端开发概述

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

    第一关 A D B B 第二关 strong 重要通知 strong
  • ElementUi常用组件创建前端页面

    elementui 创建前端页面
  • JS有小数保留两位,整数不显示小数

    在很多时候要展示数据 会有各种小数处理 碰到页面的数据要根据不同的情况展示不同格式的数据 比如得到的数据是一个小数 现在要将小数保留两位 而整数则不显示小数点 显示整数格式 使用toFixed n 方法 toFixed 2 里面的2表示保留
  • elementui 禁止浏览器自动填充用户名密码

    浏览器这功能在登录的时候挺好用的 但是在注册和管理的时候就很难受了 所以 在普通的input上直接off就行了
  • 移动端适配-01-百分比宽度

    1 图片可以在parent中使用 1 line heigh和text align使水平和竖直居中 2 在img标签中加vertical align middle 2 3 background size 1 两个参数 background s
  • 测试基础知识

    常见测试分类 按测试阶段划分 单元测试 针对程序源码进行测试 国内是开发自测 集成测试 又称接口测试 针对模块间的访问地址进行测试 系统测试 对整个系统进行测试 包括功能 兼容性 文档等 验收测试 分为内测和公测 按代码可见度划分 黑盒测试

随机推荐

  • 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