俄罗斯方块游戏代码
♥️作者:小刘在C站
♥️个人主页:小刘主页
♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生!
♥️夕阳下,是最美的,绽放,愿所有的美好,再疫情结束后如约而至。
目录
一.什么是python
二.游戏代码效果呈现
三.游戏主代码二
1.shapes
2.misc
3.gameboard
4.__init__
5.README
一.什么是python
Python由荷兰数学和计算机科学研究学会的吉多·范罗苏姆于1990年代初设计,作为一门叫做ABC语言的替代品。 Python提供了高效的高级数据结构,还能简单有效地面向对象编程。Python语法和动态类型,以及解释型语言的本质,使它成为多数平台上写脚本和快速开发应用的编程语言, [ 随着版本的不断更新和语言新功能的添加,逐渐被用于独立的、大型项目的开发。
Python解释器易于扩展,可以使用C语言或C++(或者其他可以通过C调用的语言)扩展新的功能和数据类型。Python也可用于可定制化软件中的扩展程序语言。Python丰富的标准库,提供了适用于各个主要系统平台的源码或机器码
二.游戏代码效果呈现

三.游戏主代码
'''
'''
import os
import sys
import random
from modules import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
'''定义俄罗斯方块游戏类'''
class TetrisGame(QMainWindow):
def __init__(self, parent=None):
super(TetrisGame, self).__init__(parent)
# 是否暂停ing
self.is_paused = False
# 是否开始ing
self.is_started = False
self.initUI()
'''界面初始化'''
def initUI(self):
# icon
self.setWindowIcon(QIcon(os.path.join(os.getcwd(), 'resources/icon.jpg')))
# 块大小
self.grid_size = 22
# 游戏帧率
self.fps = 200
self.timer = QBasicTimer()
# 焦点
self.setFocusPolicy(Qt.StrongFocus)
# 水平布局
layout_horizontal = QHBoxLayout()
self.inner_board = InnerBoard()
self.external_board = ExternalBoard(self, self.grid_size, self.inner_board)
layout_horizontal.addWidget(self.external_board)
self.side_panel = SidePanel(self, self.grid_size, self.inner_board)
layout_horizontal.addWidget(self.side_panel)
self.status_bar = self.statusBar()
self.external_board.score_signal[str].connect(self.status_bar.showMessage)
self.start()
self.center()
self.setWindowTitle('俄罗斯方块儿 —— 源码基地:959755565')
self.show()
self.setFixedSize(self.external_board.width() + self.side_panel.width(), self.side_panel.height() + self.status_bar.height())
'''游戏界面移动到屏幕中间'''
def center(self):
screen = QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width() - size.width()) // 2, (screen.height() - size.height()) // 2)
'''更新界面'''
def updateWindow(self):
self.external_board.updateData()
self.side_panel.updateData()
self.update()
'''开始'''
def start(self):
if self.is_started:
return
self.is_started = True
self.inner_board.createNewTetris()
self.timer.start(self.fps, self)
'''暂停/不暂停'''
def pause(self):
if not self.is_started:
return
self.is_paused = not self.is_paused
if self.is_paused:
self.timer.stop()
self.external_board.score_signal.emit('Paused')
else:
self.timer.start(self.fps, self)
self.updateWindow()
'''计时器事件'''
def timerEvent(self, event):
if event.timerId() == self.timer.timerId():
removed_lines = self.inner_board.moveDown()
self.external_board.score += removed_lines
self.updateWindow()
else:
super(TetrisGame, self).timerEvent(event)
'''按键事件'''
def keyPressEvent(self, event):
if not self.is_started or self.inner_board.current_tetris == tetrisShape().shape_empty:
super(TetrisGame, self).keyPressEvent(event)
return
key = event.key()
# P键暂停
if key == Qt.Key_P:
self.pause()
return
if self.is_paused:
return
# 向左
elif key == Qt.Key_Left:
self.inner_board.moveLeft()
# 向右
elif key == Qt.Key_Right:
self.inner_board.moveRight()
# 旋转
elif key == Qt.Key_Up:
self.inner_board.rotateAnticlockwise()
# 快速坠落
elif key == Qt.Key_Space:
self.external_board.score += self.inner_board.dropDown()
else:
super(TetrisGame, self).keyPressEvent(event)
self.updateWindow()
'''run'''
if __name__ == '__main__':
app = QApplication([])
tetris = TetrisGame()
sys.exit(app.exec_())
三.游戏主代码二
1.shapes
'''
Function:
定义俄罗斯方块的形状
'''
'''定义一个俄罗斯方块的形状'''
class tetrisShape():
def __init__(self, shape=0):
# 空块
self.shape_empty = 0
# 一字型块
self.shape_I = 1
# L型块
self.shape_L = 2
# 向左的L型块
self.shape_J = 3
# T型块
self.shape_T = 4
# 田字型块
self.shape_O = 5
# 反向Z型块
self.shape_S = 6
# Z型块
self.shape_Z = 7
# 每种块包含的四个小方块相对坐标分布
self.shapes_relative_coords = [
[[0, 0], [0, 0], [0, 0], [0, 0]],
[[0, -1], [0, 0], [0, 1], [0, 2]],
[[0, -1], [0, 0], [0, 1], [1, 1]],
[[0, -1], [0, 0], [0, 1], [-1, 1]],
[[0, -1], [0, 0], [0, 1], [1, 0]],
[[0, 0], [0, -1], [1, 0], [1, -1]],
[[0, 0], [0, -1], [-1, 0], [1, -1]],
[[0, 0], [0, -1], [1, 0], [-1, -1]]
]
self.shape = shape
self.relative_coords = self.shapes_relative_coords[self.shape]
'''获得该形状当前旋转状态的四个小方块的相对坐标分布'''
def getRotatedRelativeCoords(self, direction):
# 初始分布
if direction == 0 or self.shape == self.shape_O:
return self.relative_coords
# 逆时针旋转90度
if direction == 1:
return [[-y, x] for x, y in self.relative_coords]
# 逆时针旋转180度
if direction == 2:
if self.shape in [self.shape_I, self.shape_Z, self.shape_S]:
return self.relative_coords
else:
return [[-x, -y] for x, y in self.relative_coords]
# 逆时针旋转270度
if direction == 3:
if self.shape in [self.shape_I, self.shape_Z, self.shape_S]:
return [[-y, x] for x, y in self.relative_coords]
else:
return [[y, -x] for x, y in self.relative_coords]
'''获得该俄罗斯方块的各个小块绝对坐标'''
def getAbsoluteCoords(self, direction, x, y):
return [[x + i, y + j] for i, j in self.getRotatedRelativeCoords(direction)]
'''获得相对坐标的边界'''
def getRelativeBoundary(self, direction):
relative_coords_now = self.getRotatedRelativeCoords(direction)
xs = [i[0] for i in relative_coords_now]
ys = [i[1] for i in relative_coords_now]
return min(xs), max(xs), min(ys), max(ys)
2.misc
'''
Function:
其他工具函数
'''
from PyQt5.QtGui import *
'''给板块的一个Cell填色'''
def drawCell(painter, x, y, shape, grid_size):
colors = [0x000000, 0xCC6666, 0x66CC66, 0x6666CC, 0xCCCC66, 0xCC66CC, 0x66CCCC, 0xDAAA00]
if shape == 0:
return
color = QColor(colors[shape])
painter.fillRect(x + 1, y + 1, grid_size - 2, grid_size - 2, color)
painter.setPen(color.lighter())
painter.drawLine(x, y + grid_size - 1, x, y)
painter.drawLine(x, y, x + grid_size - 1, y)
painter.setPen(color.darker())
painter.drawLine(x + 1, y + grid_size - 1, x + grid_size - 1, y + grid_size - 1)
painter.drawLine(x + grid_size - 1, y + grid_size - 1, x + grid_size - 1, y + 1)
3.gameboard
'''
Function:'''
import random
from .misc import *
from .shapes import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QFrame'''内部板块'''
class InnerBoard():def __init__(self, width=10, height=22):# 宽和长, 单位长度为小方块边长self.width = widthself.height = heightself.reset()'''判断当前俄罗斯方块是否可以移动到某位置'''def ableMove(self, coord, direction=None):assert len(coord) == 2if direction is None:direction = self.current_directionfor x, y in self.current_tetris.getAbsoluteCoords(direction, coord[0], coord[1]):# 超出边界if x >= self.width or x < 0 or y >= self.height or y < 0:return False# 该位置有俄罗斯方块了if self.getCoordValue([x, y]) > 0:return Falsereturn True'''向右移动'''def moveRight(self):if self.ableMove([self.current_coord[0] + 1, self.current_coord[1]]):self.current_coord[0] += 1'''向左移动'''def moveLeft(self):if self.ableMove([self.current_coord[0] - 1, self.current_coord[1]]):self.current_coord[0] -= 1'''顺时针转'''def rotateClockwise(self):if self.ableMove(self.current_coord, (self.current_direction - 1) % 4):self.current_direction = (self.current_direction-1) % 4'''逆时针转'''def rotateAnticlockwise(self):if self.ableMove(self.current_coord, (self.current_direction + 1) % 4):self.current_direction = (self.current_direction+1) % 4'''向下移动'''def moveDown(self):removed_lines = 0if self.ableMove([self.current_coord[0], self.current_coord[1] + 1]):self.current_coord[1] += 1else:x_min, x_max, y_min, y_max = self.current_tetris.getRelativeBoundary(self.current_direction)# 简单起见, 有超出屏幕就判定游戏结束if self.current_coord[1] + y_min < 0:self.is_gameover = Truereturn removed_linesself.mergeTetris()removed_lines = self.removeFullLines()self.createNewTetris()return removed_lines'''坠落'''def dropDown(self):removed_lines = 0while self.ableMove([self.current_coord[0], self.current_coord[1] + 1]):self.current_coord[1] += 1x_min, x_max, y_min, y_max = self.current_tetris.getRelativeBoundary(self.current_direction)# 简单起见, 有超出屏幕就判定游戏结束if self.current_coord[1] + y_min < 0:self.is_gameover = Truereturn removed_linesself.mergeTetris()removed_lines = self.removeFullLines()self.createNewTetris()return removed_lines'''合并俄罗斯方块(最下面定型不能再动的那些)'''def mergeTetris(self):for x, y in self.current_tetris.getAbsoluteCoords(self.current_direction, self.current_coord[0], self.current_coord[1]):self.board_data[x + y * self.width] = self.current_tetris.shapeself.current_coord = [-1, -1]self.current_direction = 0self.current_tetris = tetrisShape()'''移出整行都有小方块的'''def removeFullLines(self):new_board_data = [0] * self.width * self.heightnew_y = self.height - 1removed_lines = 0for y in range(self.height - 1, -1, -1):cell_count = sum([1 if self.board_data[x + y * self.width] > 0 else 0 for x in range(self.width)])if cell_count < self.width:for x in range(self.width):new_board_data[x + new_y * self.width] = self.board_data[x + y * self.width]new_y -= 1else:removed_lines += 1self.board_data = new_board_datareturn removed_lines'''创建新的俄罗斯方块(即将next_tetris变为current_tetris)'''def createNewTetris(self):x_min, x_max, y_min, y_max = self.next_tetris.getRelativeBoundary(0)# y_min肯定是-1if self.ableMove([self.init_x, -y_min]):self.current_coord = [self.init_x, -y_min]self.current_tetris = self.next_tetrisself.next_tetris = self.getNextTetris()else:self.is_gameover = Trueself.shape_statistics[self.current_tetris.shape] += 1'''获得下个俄罗斯方块'''def getNextTetris(self):return tetrisShape(random.randint(1, 7))'''获得板块数据'''def getBoardData(self):return self.board_data'''获得板块数据上某坐标的值'''def getCoordValue(self, coord):return self.board_data[coord[0] + coord[1] * self.width]'''获得俄罗斯方块各个小块的绝对坐标'''def getCurrentTetrisCoords(self):return self.current_tetris.getAbsoluteCoords(self.current_direction, self.current_coord[0], self.current_coord[1])'''重置'''def reset(self):# 记录板块数据self.board_data = [0] * self.width * self.height# 当前俄罗斯方块的旋转状态self.current_direction = 0# 当前俄罗斯方块的坐标, 单位长度为小方块边长self.current_coord = [-1, -1]# 下一个俄罗斯方块self.next_tetris = self.getNextTetris()# 当前俄罗斯方块self.current_tetris = tetrisShape()# 游戏是否结束self.is_gameover = False# 俄罗斯方块的初始x位置self.init_x = self.width // 2# 形状数量统计self.shape_statistics = [0] * 8'''外部板块'''
class ExternalBoard(QFrame):score_signal = pyqtSignal(str)def __init__(self, parent, grid_size, inner_board):super(ExternalBoard, self).__init__(parent)self.grid_size = grid_sizeself.inner_board = inner_boardself.setFixedSize(grid_size * inner_board.width, grid_size * inner_board.height)self.initExternalBoard()'''外部板块初始化'''def initExternalBoard(self):self.score = 0'''把内部板块结构画出来'''def paintEvent(self, event):painter = QPainter(self)for x in range(self.inner_board.width):for y in range(self.inner_board.height):shape = self.inner_board.getCoordValue([x, y])drawCell(painter, x * self.grid_size, y * self.grid_size, shape, self.grid_size)for x, y in self.inner_board.getCurrentTetrisCoords():shape = self.inner_board.current_tetris.shapedrawCell(painter, x * self.grid_size, y * self.grid_size, shape, self.grid_size)painter.setPen(QColor(0x777777))painter.drawLine(0, self.height() - 1, self.width(), self.height() - 1)painter.drawLine(self.width() - 1, 0, self.width() - 1, self.height())painter.setPen(QColor(0xCCCCCC))painter.drawLine(self.width(), 0, self.width(), self.height())painter.drawLine(0, self.height(), self.width(), self.height())'''数据更新'''def updateData(self):self.score_signal.emit(str(self.score))self.update()'''侧面板, 右边显示下一个俄罗斯方块的形状'''
class SidePanel(QFrame):def __init__(self, parent, grid_size, inner_board):super(SidePanel, self).__init__(parent)self.grid_size = grid_sizeself.inner_board = inner_boardself.setFixedSize(grid_size * 5, grid_size * inner_board.height)self.move(grid_size * inner_board.width, 0)'''画侧面板'''def paintEvent(self, event):painter = QPainter(self)x_min, x_max, y_min, y_max = self.inner_board.next_tetris.getRelativeBoundary(0)dy = 3 * self.grid_sizedx = (self.width() - (x_max - x_min) * self.grid_size) / 2shape = self.inner_board.next_tetris.shapefor x, y in self.inner_board.next_tetris.getAbsoluteCoords(0, 0, -y_min):drawCell(painter, x * self.grid_size + dx, y * self.grid_size + dy, shape, self.grid_size)'''更新数据'''def updateData(self):self.update()
4.__init__
'''初始化'''
from .shapes import tetrisShape
from .gameboard import InnerBoard, ExternalBoard, SidePanel
5.README
requirements
♥️关注,就是我创作的动力
♥️点赞,就是对我最大的认可
♥️这里是小刘,励志用心做好每一篇文章,谢谢大家
相关文章:
俄罗斯方块游戏代码
♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️夕阳下,是最美的,绽…...
设计模式相关面试题
文章目录面向对象编程中,都有哪些设计原则?设计模式的分类 ?单例模式的特点是什么?单例模式有哪些实现?什么是简单⼯⼚模式什么是抽象⼯⼚模式?什么是⼯⼚⽅法模式?什么是代理模式?S…...
构建Jenkins 2.340持续集成环境
一、前言 本文学习自:2022版Jenkins教程(从配置到实战) 如有不妥,欢迎指正 二、构建资料 已经包括了本文档使用的所有所需的安装包 三、安装docker 1、解压docker docker-20.10.10.tgz2、复制文件 cp docker/* /usr/bin/3、编写启动文…...
Ubuntu/Centos下OpenJ9 POI输出Excel的Bug
项目更换 JDK为 OpenJ9 后, 使用 POI 导出 Excel 遇到的问题 OpenJ9 版本信息 /opt/jdk/jdk-11.0.178/bin/java -version openjdk version "11.0.17" 2022-10-18 IBM Semeru Runtime Open Edition 11.0.17.0 (build 11.0.178) Eclipse OpenJ9 VM 11.0.17.0 (build …...
链接脚本学习笔记
IAR 一般步骤 链接器用于链接过程。它通常执行以下过程(请注意,某些步骤可以通过命令行选项或链接器配置文件中的指令关闭): 1.确定应用程序中要包含哪些模块。始终包含对象文件中提供的模块。仅当库文件中的模块为从包含的模块…...
NLP顶会近三年小众研究领域
ACL 2022 编码器和解码器框架、自然语言生成、知识i神经元、抽取式文本摘要、预训练语言模型、零样本神经机器翻译等。 2021 新闻标题生成任务等。跨语言命名实体识别、代码搜索、音乐生成、Hi-Transformer、预训练语言模型、语义交互等。 EMNLP 2021 代码摘要生成、隐私…...
[electron] 一 vue3.2+vite+electron 项目集成
一 开发环境系统:windows开发工具: git , vscode,termial环境依赖: node, npm 二 步骤2.1 通过vite 创建vue项目通过 终端执行命令,选择 模板 vuenpm init vite cd 项目目录 npm install npm run dev2.2 集成 electro…...
ESP32 Arduino(十二)lvgl移植使用
一、简介LVGL全程LittleVGL,是一个轻量化的,开源的,用于嵌入式GUI设计的图形库。并且配合LVGL模拟器,可以在电脑对界面进行编辑显示,测试通过后再移植进嵌入式设备中,实现高效的项目开发。SquareLine Studi…...
js一数组按照另一数组进行排序
有时我们需要一个数组按另一数组的顺序来进行排序,总结一下方法,同时某些场景也会用到。 首先一个数组相对简单的情况: var arr1 [52,23,36,11,09]; var arr2 [23,09,11,36,52]; // 要求arr1按照arr2的顺序来排序,可以看到两个…...
JavaScript 类继承
JavaScript 类继承是面向对象编程的一个重要概念,它允许一个类从另一个类继承属性和方法。通过使用继承,可以避免代码重复,并可以在现有类的基础上扩展新功能。 在 JavaScript 中,您可以使用关键字 extends 来实现类继承。例如&a…...
MySQL相关面试题
文章目录union 和 unionAll 的区别?drop、delete与truncate的区别 ?sql 语句如何优化 ?什么是事务 ?事务的四个特性(ACID) ?事务的隔离级别?索引主要有哪几种分类 ?什么时候适合添加索引&#x…...
Python创意作品说明怎么写,python创意编程作品集
大家好,小编来为大家解答以下问题,Python创意作品说明怎么写,python创意编程作品集,现在让我们一起来看看吧! 1、有哪些 Python 经典书籍 书名:深度学习入门 作者:[ 日] 斋藤康毅 …...
icomoon字体图标的使用
很久之前就学习过iconfont图标的使用,今天又遇到一个用icomoon字体图标写的案例,于是详细学习了一下,现整理如下。 一、下载 1.网址: https://icomoon.io/#home 2.点击IcoMoon App。 3.点击 https://icomoon.io/app 4.进入IcoM…...
Java · 常量介绍 · 变量类型转换 · 理解数值提升 · int 和 Stirng 之间的相互转换
书接上回 Java 变量介绍 我们继续学习以下内容. 四、常量字面值常量final 关键字修饰的常量五、理解类型转换int 和 long/double 相互赋值int 和 boolean 相互赋值int 字面值常量给 byte 赋值强制类型转换类型转换小结六、理解数值提升int 和 long 混合运算byte 和 byte 的运算…...
JVM从跨平台到跨专业 Ⅲ -- 类加载与字节码技术【下】
文章目录编译期处理默认构造器自动拆装箱泛型集合取值可变参数foreach 循环switch 字符串switch 枚举枚举类try-with-resources方法重写时的桥接方法匿名内部类类加载阶段加载链接初始化相关练习和应用类加载器类与类加载器启动类加载器拓展类加载器双亲委派模式自定义类加载器…...
ucore的字符输出
ucore的字符输出有cga,lpt,和串口。qemu模拟出来显示器连接到cga中。 cga cga的介绍网站:https://en.wikipedia.org/wiki/Color_Graphics_Adapter cga是显示卡,内部有个叫6845的芯片。cga卡把屏幕划分成一个一个单元格,每个单元格显示一个a…...
【ESP 保姆级教程】玩转emqx数据集成篇① ——认识数据集成
忘记过去,超越自己 ❤️ 博客主页 单片机菜鸟哥,一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-02-10 ❤️❤️ 本篇更新记录 2023-02-10 ❤️🎉 欢迎关注 🔎点赞 👍收藏 ⭐️留言📝🙏 此博客均由博主单独编写,不存在任何商业团队运营,如发现错误,请…...
PMP报考条件?
PMP已经被认为是项目管理专业身份的象征,项目经理人取得的重要资质。 PMP考试一般每年在中国大陆地区,会进行四次考试,今天就来详细说一说PMP考试的时间线。 01考试时间PMP考试在中国大陆一年开展四次,分别在每年的3月、6月、9月…...
Vite+Vue3实现版本更新检查,实现页面自动刷新
ViteVue3实现版本更新检查,实现页面自动刷新1、使用Vite插件打包自动生成版本信息2、Vite.config.ts配置3、配置环境变量4、路由配置现有一个需求就是实现管理系统的版本发版,网页实现自动刷新页面获取最新版本 搜索了一下,轮询的方案有点浪费…...
LeetCode刷题模版:292、295、297、299-301、303、304、309、310
目录 简介292. Nim 游戏295. 数据流的中位数297. 二叉树的序列化与反序列化【未理解】299. 猜数字游戏300. 最长递增子序列301. 删除无效的括号【未理解】303. 区域和检索 - 数组不可变304. 二维区域和检索 - 矩阵不可变309. 最佳买卖股票时机含冷冻期310. 最小高度树【未理解】…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
LangFlow技术架构分析
🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...
永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
【Redis】Redis 的持久化策略
目录 一、RDB 定期备份 1.2 触发方式 1.2.1 手动触发 1.2.2.1 自动触发 RDB 持久化机制的场景 1.2.2.2 检查是否触发 1.2.2.3 线上运维配置 1.3 检索工具 1.4 RDB 备份实现原理 1.5 禁用 RDB 快照 1.6 RDB 优缺点分析 二、AOF 实时备份 2.1 配置文件解析 2.2 开启…...
