HTML5 游戏开发实战 | 俄罗斯方块

news2024/11/14 21:48:33

 

俄罗斯方块是一款风靡全球的电视游戏机和掌上游戏机游戏,它曾经造成的轰动与造成的经济价值可以说是游戏史上的一件大事。这款游戏看似简单但却变化无穷,游戏过程仅需要玩家将不断下落的各种形状的方块移动、翻转,如果某一行被方块充满了,那就将这一行消掉;而当窗口中无法再容纳下落的方块时,就宣告游戏结束。

可见俄罗斯方块的需求如下。

(1) 由移动的方块和不能动的固定方块组成。

(2) 一行排满消除。

(3) 能产生多种方块。

(4) 玩家可以看到游戏的积分。

本文开发俄罗斯方块游戏程序,俄罗斯方块游戏的运行界面如上图所示。

01、俄罗斯方块游戏设计的思路

俄罗斯方块形状设计

游戏中下落的方块有着各种不同的形状,要在游戏中绘画不同形状的方块,就需要使用合理的数据表示方式。常见的俄罗斯方块拥有7种基本的形状以及它们旋转以后的变形体,具体的形状如图1所示。

■ 图1 俄罗斯方块形状

每种形状都是由不同的黑色小方格组成的,如图2所示,在屏幕上只需要显示必要的黑色小方格就可以表现出各种形状,每一形状都是由4个小方格组成的,完全可以用4个点来表示。

■ 图2 俄罗斯方块示意图

4个点的坐标分别是什么呢?每个形状都有一个自己的坐标系。例如,S形可以如图3表示。

■ 图3 S形形状坐标系

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

如图4所示,T形的数据模型可以表示为4个点组成的数组:[ [-1,0],[0,0],[1,0] ,[0,1] ]。

 

■ 图4 T形形状坐标系

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

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

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

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

//各种形状的编号,0 代表没有形状NoShape = 0;
//z形//s形
ZShape = 1;
SShape = 2;
LineShape = 3;
//竖条形//T形
T斤爱败化仓臂氨尺暗隘肮伴唉懊碍艾蔼巴艾菠蔼懊胺报稗氨= 4;
//正方形//L形//反L形
SquareShape = 5 ;
LShape = 6;
MirroredLShape = 7
//各种形状的颜色
Colors =("black""fuchsia""# cff""red""orange","agua","green","yellow"];
[1,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,21]
[-1,1],[ 0,1 ],[ 1,0 ],[ 0, 1]
[1, 1],[ 0,1 ],[ 0,0 ],[ 0,1 ]
[1,-1],[ 0,-1],[ 0,0],[ 0,1 ]

俄罗斯方块游戏面板屏幕

游戏的面板是由一定的行数和列数的单元格组成的,游戏窗口面板屏幕如图5所示。

■ 图5 屏幕网格

屏幕由20行10列的网格组成,为了存储游戏画面中的已固定方块采用二维数组lines,当相应的数组元素值非零(数组元素值为0,表示此单元格无方块),则绘制一个对应彩色小方块。在窗口面板中显示一个俄罗斯方块形状,只需要把面板中相应的单元格绘制为彩色方块即可,如图6所示的面板中显示一个L形方块,只需要按照L形方块形状数组定义,将它的数据用Paint()函数绘制到窗口面板即可。

而方块下落的基本处理方式就是当前方块下移一行,然后根据当前方块的数组的数据和存储的固定方块的面板二维数组lines,重新绘制一次屏幕即可,如图6所示。所以要使用一个坐标(row,col)记录当前方块形状所在的行号row和列号col。

 

■ 图6 L形方块下落前和下落后

定位和旋转形状

1. 定位

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

假如S形在自身坐标系中4个点的坐标为:[[0,-1],[0,0],[-1,0],[-1,1]]。它当前在屏幕上全局坐标系位置为:[12,8],则4个点转换为全局坐标系的坐标为:[[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

注意,正方形形状不发生旋转。

根据上面的分析,可以使用两个全局方法,用来对形状进行全局定位和旋转。

translate(data.row.col)函数将形状自身的坐标系转换为屏幕的全局坐标系,(row,col)为当前形状原点在屏幕中的位置。

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;

每种形状向右旋转就会形成一个新的形状,rotate(data)函数可以得到当前形状的方块旋转后的坐标数组。

//向右旋转形状:x'= y,y'= -xfunction rotate(data)!
var copy=[[],[],[][]];for(var i= 0;i<4;i++)
copy[i][0]= data[i][1];copyl[i][1]= -data[i][0];
return copy;

3. 游戏流程

俄罗斯方块游戏就是用一个定时器控制方块下落并重绘的过程,用户可以利用键盘输入改变方块状态。每隔一定的时间就重画当前下落方块和lines存储的固定方块,从而看到动态游戏效果。

俄罗斯方块下落过程中可能遇到种种情况。例如,是否需要消行,是否需要终止下落并且产生新的形状的方块等。具体的判断流程如下:首先判断是否可以继续下落,可以下落则row++即可;如果方块不能够继续下落,则将当前形状的方块添加到面板二维数组lines中,界面产生新的形状的方块。然后,判断是否需要消行。最后,请求重新绘制屏幕。

 02、俄罗斯方块游戏设计的步骤

 

游戏页面index.html

<html>
< head >
< title></title><meta http - equiv= "Content - Type" content = "text/html; charset = UTF - 8">< script type = "text/javascript" language = "javascript" src = "jsgame. js"> </script></head >
< body >
<audio src ="Kalimba.mp3” id = "snd">你的浏览器不支持 audio 标记
</audio >
<canvas id= "html5 09 1"width= "260"heght = "400"style= "background- color: Black">你的浏览器不支持 Canvas 标记,请使用 Chrome 览器或者 Eirefox 浏览器/canvas>
<canvas id= "html5 09 2"width= "100"height = "100" style = "background- color: red">你的浏览器不支持 Canvas 标记,请使用 Chrome 浏览器或者 Erefox 浏览器/canvas><p /
<div id="textmsg">分数</div>
<input type ="button"value ="开始”onclick ="start()”/><input type ="button”id="btnPause"value="暂停"onclick = "pause()"/>< script type ="text/javascript">

设计脚本

1. 设计方块类Block

方块类Block中定义方块的类型ID,存储方块的形状二维数组data以及颜色。设计了将形状自身的坐标系转换为屏幕的坐标系的translate(row,col)函数,参数(row,col)为当前形状方块的原点在屏幕Map中的位置。rotate()函数可以获取当前形状方块旋转后的坐标数组。

x
*方块类
*说明:各种形状的方块
function Block(
//this.data=[[],[],[],[]];
Block.prototype.Block = function ()this.born();
//产生一个新的形状方块Block.prototype.born = function () //随机选择一个形状this.shape id = Math.floor(Math.random() * 7)+1;this.data = Shapes[ this.shape id];this.color = Colors[ this.shape id];console.log(this.data);
//产生1~7的数
//存储方块部件的形状
//存储方块部件的颜色
//将形状自身的坐标系转换为屏幕 Map 的坐标系//(row,col)为当前形状的方块的原点在 Map 中的位置Block.prototype.translate = function (row,col)var copy=[l;
for(var i=0;i<4;i++) (
var temp =;
temp.row = this.datali][1] + row;
temp.col = this.datalill0]+ col;
copy.push(temp)
return copy;
//向右旋转一个形状:x'= y,y'= -x,得到旋转后的 dataBlock.prototype.rotate = function (){var copy=[[],[],[],[]];for(var i=0;i<4; i++) !copy[i][0]= this.datal i][1];copy[ i][1]=- this.datailol;
return copy;

另外,程序中将各方块形状编号:Z形编号1,S形编号2,竖条形编号3,T形编号4,正方形编号5,L形编号6,反L形编号7。所有方块的形状采用数组Shapes存储。通过编号从数组Shapes中获取方块的形状信息。

//每一格的间距,即一个小方块的尺寸Spacing=20;
//各种形状的编号,0 代表没有形状
NoShape = 0;
ZShape = 1;
SShape = 2;
LineShape = 3;
IShape = 4;
SquareShape = 5;
LShape = 6;
MirroredLShape = 7
//各种形状的数据描述
Shapes =
[[O,0],[0,0],[0,0],[0,0]],[[O,-1],[0,0],[-1,0],[-1,1]],
[[o,-1],[0,0],[1,0],[1,1]],[[O,-1],[0,0],[0,1],[0,2]][[-1,0],[0,0],[1,0],[0,1]],[[O,0],[1,0],[0,1],[1,1]],[[-1,-1],[0,-1],[0,0],[0,1]],[[1,-1],[0,-1],[0,0],[0,1]]
//各种形状的颜色
Colors =["black""fuchsia","#cff","red","orange","aqua","green","yellow"l;

2. 设计游戏容器Map类

游戏容器Map类是游戏实例,应先定义游戏面板大小,在游戏面板中存储所有方块的“容器”——二维数组lines,初始时每个元素存储为NoShape(0),表示此格子处无方块。

*
* Map类说明:由m行 Line 组成的格子阵*
function Map(w,h) [
//游戏区域的长度和宽度
this.width = w;
this.height = h;
//生成 height 个 line 对象,每个 line 宽度为 widththis.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;

isFullLine (row)函数判断一行是否全部被占用(满行),如果有一个格子为 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;

预先移动或者旋转形状,调用isCollide(data)函数分析形状中的4个点是否有以下碰撞情况。

(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++)fvar row = data il.row;var col = data[i].col;//console.log(row,col);if(col < 0col== this.width) return true;if(row == this.height) return true;
if(row <0) continue;
else
if(this.lines[row][col  != 0)//NoShapereturn true;
return false;

形状在向下移动的过程中发生碰撞,appendShape=function (shape_id,data)则将形状加入lines容器中固定下来。

Map.prototype.appendShape = function( shape id,data)
//对于形状的 4个点
for(var i=0;i<4;i++)/
var row = datai].row;
var col = datalil.col;
//找到所在的格子,将格子的颜色改为形状的颜色
this.lines[row][col]= shape id;
//形状被加入 lines 容器中后,要进行逐行检测,发现满行则消除for(var row = 0; row < this.height; row++)
if(this.isFullLine(row)) 
//绘制消除效果
onClearRow(row);
/将满行删除
this.lines.splice(row,1);
//第一行添加新的一行
this.lines.unshift(this.newLine());

3. 设计游戏逻辑类GameModel

游戏逻辑类GameModel实现游戏控制,首先定义游戏面板map、当前的俄罗斯方块currentBlock、下一个的俄罗斯方块nextBlock以及当前的俄罗斯方块所在位置等。

function GameModel(w,h)
this.map = new Map(w,h);
this.currentBlock = new Block();
this.currentBlock.Block();
this.row = 1;
this.col= Math.floor(this.map.width / 2);this.nextBlock = new Block();
//当前的俄罗斯方块
//当前的俄罗斯方块所在位置(顶端中央)
//下一个俄罗斯方块
this.nextBlock.Block();

其次调用CreateNewBlock()函数产生新的俄罗斯方块。它先复制下一个形状this.nextBlock,再产生下一个俄罗斯方块。

GameModel.prototype.CreateNewBlock = function()
this.currentBlock = this.nextBlock;
this.row = 1;
this.col = Math.floor(this.map.width / 2);
//复制预览区形状
//重置形状的位置为出生地点(顶端中央)
this.nextBlock = new Block();
this.nextBlock.Block();

以下是控制形状方块左右移动、旋转和下移,并且保证左右移动时和lines中存储的固定方块、边界不碰撞。如果碰撞则恢复数据放弃移动。

//向左移动
GameModel.prototype.left = function()
this.col-- ;var temp = this.currentBlock.translate(this.row,this.col);if(this.map.isCollide(temp))
//发生碰撞则放弃移动
this.col++;
//通知数据发生了更新
else
onUpdate();
//向右移动
GameModel.prototype.right = function()this.col++;
var temp= this.currentBlock.translate(this.row,this.col);if(this.map.isCollide(temp))this.col-- ;
else
onUpdate();

同样保证旋转时和lines中存储的固定方块、边界不碰撞。如果碰撞则恢复数据放弃旋转。

//旋转
GameModel.prototype.rotate = function()
//正方形不旋转
if(this.currentBlock.shape id== SquareShape) return;//获得旋转后的数据
var copy = this.currentBlock.rotate();
//转换坐标系
var temp = this.currentBlock.translate(this.row, this.col);//发生碰撞则放弃旋转
if(this.map.isCollide(temp))
return;
//将旋转后的数据设为当前数据this.currentBlock.data = copy;//通知数据发生了更新

方块下落需判断是否“触底”或接触到其他已落方块。如果“触底”则固定到游戏面板上,此时要处理满行和游戏结束的判断,同时产生新的俄罗斯方块。

//下落
GameModel.prototype.down = function()
var old= this.currentBlock.translate(this.row,this.col);this.row++ ;
var temp= this.currentBlock.translate(this.row,this.col);if(this.map.isCollide(temp)) //发生碰撞则放弃下落this.row-- ;//如果在 1 也无法下落,则说明游戏结束if(this.row== 1)(
//通知游戏结束
onGameOver();
return;
//无法下落则将当前形状加入 Map 中this.map.appendShape(this.currentBlock.shape id,old);this.CreateNewBlock();
//产生新的俄罗斯方块
//通知数据发生了更新
onUpdate();

4. 游戏主程序

在定时事件中,完成下落功能。

var display = document.getElementById("htm15 09 1");var display2 = document.getElementById("htm15_09 2");
var model = null;
//游戏面板//预览区域
var loop interval= null;
var tick interval = null:
var waiting = false;
var speed = 500;
v珠跋糊傲安把奥樊喽唉哎啊爱碍暗跋拔敖稗傲八core = 0;
var textmsg = document.getElementById("textmsg”);function start)!
model = new GameModel(display.width / Spacing,display.height / Spacing);loop(;
function pause()waiting =!waiting;if(waiting)document.getElementById("btnPause").value ="继续”;else
document.getElementById("btnPause").value ="暂停”;
//消息循环function loop(){tick interval= setInterval(function()if(waiting) return;onTick() ;
//时钟事件即下落

以下是消息事件处理。

//消息处理//更新事件
function onUpdate() {
   paint();
//清除行事件
function onClearRow(row) !clearline(row);
score = score +10:
textmsq.innerHTML = score +“分”
/游戏结束事件function onGameOver()alert("Game Over");clearInterval(tick interval);
//时钟事件function onTick()model.down();
//按键事件
function onKevPress(evt) evt.preventDefault():move(evt.which);
function move(which) !

switch(which)
case 37: model.left(); break;
case 39: model.right(); break;
case 38: model.rotate(); break;
case 40: model.down(); break;

以下才是真正的绘制代码,调用clearline(row)函数绘制清除行的暂停效果。

function clearline(row)
//增加速度
clearInterval(tick interval);
speed = speed -10;
loop();
//音效
document.getElementById("snd").play()//停顿效果
waiting = true;
var ctx = display.getContext("2d");
ctx.fillRect(0,row * Spacing,display.width,Spacing,"black");setTimeout("waiting = false;",50);

调用paint()函数绘制游戏屏幕。它将lines存储的所有固定方块画到游戏面板中,同时当前方块画到游戏面板中和下一个方块画到游戏面板右侧提示预览区中。

function paint()
var map = model.map;
var data = model.currentBlock.translate(model.row,model.col);var nextdata = model.nextBlock.translate(1,2);//在预览区(1,2)处位置//清屏
var ctx = display.getContext("2d");
ctx.clearRect(0,0,display.width,display.height);
var ctx2 = display2.getContext("2d");ctx2.clearRect(0,0,display2.width,display2.height);
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] coll;if(shape id != NoShape) {
   var y=row * Spacing;var x=col * Spacing;
var color = Colors[ shape id];
var ctx = display.getContext("2d");
ctx.fillStyle ="rgba(255,255,255,0.2)";
ctx.fillRect(x,y,Spacing,Spacing);
//形状前景色
ctx.fillStyle= color;
ctx.fillRect(x+1,y+1,Spacing - 2,Spacing - 2);
//绘制当前的方块  

for(var i=0;i<4;i++)
var y=datalil.row * Spacing;
var x= data[i].col * Spacing;
var color = model.currentBlock.color:
var ctx = display.getContext("2d");
ctx.fillStyle="rgba(255,255,255,0.2)";
/Colors[model. currentBlock. shape id];
ctx.fillRect(x,y,Spacing,Spacing);
//形状前景色ctx.fillRect(x+1,y+1,Spacing -2,Spacing - 2);
ctx.fillStyle = color;
//绘制预览区中下个方块
for(var i=0;i<4;i++) !
var y= nextdatali].row * Spacing;
var x= nextdatali].col * Spacing;
/display2.draw( Rects[model.nextshape id],x,y);//Colors[model.nextBlock.shape id];
var color = model.nextBlock.color;
var ctx2 = display2.getContext("2d");
ctx2.fillStyle="rqba(255,255,255,0.2)"
ctx2.fillRect(x,y,Spacing,Spacing);
ctx2.fillStyle= color;
//形状前景色
ctx2.fillRect(x+1,y+1,Spacing - 2,Spacing - 2);

至此,俄罗斯方块游戏编写完成。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/710210.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

发送邮箱验证码【spring boot】

⭐前言⭐ ※※※大家好&#xff01;我是同学〖森〗&#xff0c;一名计算机爱好者&#xff0c;今天让我们进入学习模式。若有错误&#xff0c;请多多指教。更多有趣的代码请移步Gitee &#x1f44d; 点赞 ⭐ 收藏 &#x1f4dd;留言 都是我创作的最大的动力&#xff01; 1. 思维…

Redis6之穿透、击穿、雪崩

大量的高并发的请求打在Redis上&#xff0c;但是发现Redis中并没有请求的数据&#xff0c;redis的命令率降低&#xff0c;所以这些请求就只能直接打在DB&#xff08;数据库服务器&#xff09;上&#xff0c;在大量的高并发的请求下就会导致DB直接卡死、宕机。 缓存穿透 当客户端…

一例Phorpiex僵尸网络样本分析

本文主要分析Phorpiex僵尸网络的一个变种&#xff0c;该样本通常NSIS打包&#xff0c;能够检测虚拟机和沙箱。病毒本体伪装为一个文件夹&#xff0c;通过U盘来传播&#xff0c;会隐藏系统中各盘符根目录下的文件夹&#xff0c;创建同名的lnk文件&#xff0c;诱导用户点击。 病…

TF卡/U盘系统备份

Jetson nano使用TF卡/U盘来装载系统&#xff0c;如果TF卡/U盘丢失或者损坏&#xff0c;那么Jetson nano上的数据都会丢失&#xff0c;所以一定要备份好TF卡/U盘。这篇文章可以帮你备份你的Jetson nano系统。主要内容为备份TF卡/U盘&#xff0c;制作Jetson nano系统镜像以及在需…

Java——《面试题——ElasticSearch篇》

目录 1、谈谈分词与倒排索引的原理 2、说说分段存储的思想 3、谈谈你对段合并的策略思想的认识 4、了解文本相似度 TF-IDF吗 5、能说说ElasticSearch 写索引的逻辑吗&#xff1f; 6、熟悉ElasticSearch 集群中搜索数据的过程吗&#xff1f; 7、了解ElasticSearch 深翻页的…

vsCode 创建新java项目(创建一个新java项目测试方法)

VSCODE环境配置-java之项目建立&#xff0c;非常适合刚准备使用VSCODE开发JAVA的人_vscode创建java项目_rainmenzhao的博客-CSDN博客 1 按 ctrl shift p 2 输入 create Java project 3 选 no build tools 4 选择 一个文件夹 存放 之后要 新建的文件 5 选完之后 自动返回主页…

获得Jolt 大奖的《持续交付》作者David Farley又一新作《现代软件工程》

戴维 法利 (David Farley) 是持续交付的先驱、思想领袖&#xff0c; 也是持续交付、 DevOps、 测试驱动开发和软件开发领域的专家。 从现代计算的早期开始&#xff0c;戴维曾担任过程序员、软件工程师、系统架构师和成功团 队的领导者&#xff0c;他掌握了计算机和软件开发的基…

ES基本操作(postman篇)

关系型数据库 -> Databases(库) -> Tables(表) -> Rows(行) -> Columns(列)。Elasticsearch -> Indeces(索引) -> Types(类型) -> Documents(文档) -> Fields(属性)。 需要注意的是&#xff1a;type的概念在es7.0之后已经删除了。 以下仅做刚入门学习…

矩阵对角线元素的和:揭秘数学之美,解密矩阵的隐秘密码

本篇博客会讲解力扣“1572. 矩阵对角线元素的和”的解题思路&#xff0c;这是题目链接。 本题的思路是&#xff1a;主对角线的下标满足i j&#xff0c;副对角线的下标满足i j size - 1&#xff0c;故只需要使用i遍历每一行&#xff0c;把(i, i)和(i, size - i - 1)的元素求和…

探索 Spring Boot 项目全过程

文章目录 &#x1f387;前言1.Spring Boot 所需环境2.Spring Boot 项目创建2.1 安装插件2.2 创建新项目2.3 项目属性配置2.4添加依赖2.4 修改项目名称2.5 添加框架支持2.6 目录介绍 3.判断Spring Boot 创建项目是否成功&#x1f386;总结 &#x1f387;前言 在 Java 这个圈子&…

1. Except

文章目录 Except前言Except 语法Except 使用举例结合其他关键字使用EXCEPT with BETWEEN operatorExcept with IN operatorEXCEPT with LIKE operator 文章参考 Except 前言 SQL中&#xff0c;EXCEPT 操作用于检索存在于第一个表中的唯一记录&#xff0c;而不是两个表中共有的…

python3GUI--网速内存小工具By:PyQt5(附源码)

文章目录 一&#xff0e;前言二&#xff0e;预览1.主界面2.动图演示3.内存详细信息查看4.自定义界面 三&#xff0e;源代码1.tool_god_GUI.py2.tool_god_ui.py3.engine.py4.CWidgets.py 四&#xff0e;总结五&#xff0e;参考 一&#xff0e;前言 本次使用PyQt5进行开发一款网…

(并查集) 685. 冗余连接 II ——【Leetcode每日一题】

并查集基础 并查集&#xff08;Union-find Sets&#xff09;是一种非常精巧而实用的数据结构&#xff0c;它主要用于处理一些不相交集合的合并问题。一些常见的用途有求连通子图、求最小生成树的Kruskal算法和求最近公共祖先&#xff08;LCA&#xff09;等。 并查集的基本操作主…

MySQL 分库分表实战之ShardingSpare

文章目录 概要一、安装二、配置2.1、 通用配置2.2、 分片配置2.3、读写分离 三、演练3.1、读写分离3.2、分库分表3.3、分库分表读写分离 4、总结 概要 市面上MySQL分库分表中间件还是很多的&#xff0c;主要分为两大类&#xff1a;应用层依赖类中间件&#xff08;比如sharding…

【学习周报】

最近看过的几篇论文里&#xff0c;VALOR和InstructBLIP模型使用了cross-attention机制&#xff0c;以这两篇论文为基础着重学习cross-attention相关的代码和思路。 学习内容&#xff1a; cross-attention机制学习lstm与transformer 学习时间&#xff1a; 6.26 ~ 7.1 学习笔记…

Linux--重定向:> >> <

输出重定向&#xff1a;> a.如果目标文件不存在&#xff0c;则创建文件。反之 b.本来应该显示到显示器的内容&#xff0c;被写入到了文件中 示例&#xff1a; 追加重定向: >> 示例&#xff1a; 输入重定向&#xff1a;< 本来应该从键盘中读取的内容&#xff0c;变…

分布式锁的实现方案(免费gpt4分享)

1.1基于数据库 有两个方案&#xff1a;依赖数据库排他锁以及表主键的唯一。 依赖数据库排他锁&#xff1a; 在查询语句后面增加for update&#xff0c;数据库会在查询过程中给数据库表增加排他锁 (注意&#xff1a; InnoDB 引擎在加锁的时候&#xff0c;只有通过索引进行检索…

SpringBoot扩展机制

启动生命周期 一.Spring boot初始化器扩展 package com.lx.conmon.extend.intializer;import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext;/*** Spring boot初始化器扩展* author liu we…

AIPRM for ChatGPT 提示词模板扩展工具实践

&#xff08;1&#xff09;基本介绍 AIPRM for ChatGPT是一个Chrome浏览器扩展程序&#xff0c;基于Chromium内核开发的浏览器都可以使用该扩展&#xff0c;比如微软的Edge浏览器等。 在AIPRM的帮助下&#xff0c;我们可以在ChatGPT中一键使用各种专门为网站SEO、SaaS、营销、…

超详细,Python自动化测试 Allure报告参数化动态生成标题(实战)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 默认 allure 报告…