鸿蒙扫雷游戏的核心架构设计

鸿蒙OS扫雷游戏采用了MVC(模型-视图-控制器)的架构思想,将游戏逻辑与UI展示分离,使得代码结构清晰且易于维护。整个游戏由以下几个核心部分构成:

数据模型设计

游戏的基础数据模型是Cell类,它代表扫雷游戏中的每个方块,包含位置信息、地雷状态、相邻地雷数量等关键属性:

@ObservedV2
class Cell {row: number;         // 行坐标column: number;      // 列坐标hasMine: boolean;    // 是否包含地雷neighborMines: number; // 相邻地雷数量@Trace isFlag: boolean; // 是否已标记@Trace value: string;   // 显示值(数字或"雷")constructor(row: number, column: number) {this.row = row;this.column = column;this.value = '';}
}

@ObservedV2装饰器使Cell类具备数据观察能力,当属性变化时能自动通知视图更新,这是鸿蒙OS声明式UI的核心特性之一。@Trace装饰器则用于追踪属性变化,帮助开发者调试数据流向。

游戏状态管理

游戏的状态管理集中在Index组件中,通过@State装饰器管理界面相关状态,确保数据变化时UI能自动刷新:

@Entry
@Component
struct Index {@State private gameBoard: Cell[][] = [];    // 游戏面板@State private mineCount: number = 10;      // 地雷数量@State private revealedCells: Set<string> = new Set(); // 已揭示方块@State private flaggedCells: Set<string> = new Set();  // 标记方块@State private cellSize: number = 60;       // 方块大小@State private isGameOver: boolean = false; // 游戏结束状态// 其他状态...
}

使用Set数据结构存储已揭示和标记的方块,利用其快速查找特性(时间复杂度O(1))提升游戏性能。字符串键"row,column"的设计巧妙地将二维坐标转换为一维键,便于状态管理。

双向绑定与视图更新

鸿蒙OS的声明式UI特性在扫雷游戏中体现为数据与视图的双向绑定,当gameBoard或状态集合发生变化时,build方法会自动重新渲染相关组件:

Text(this.isShowValue(cell)).width(`${this.cellSize}lpx`).height(`${this.cellSize}lpx`).backgroundColor(this.revealedCells.has(`${rowIndex},${colIndex}`) ?(this.isShowValue(cell) === '雷' ? Color.Red : Color.White) : Color.Gray)

上述代码中,背景颜色根据revealedCells集合中的状态动态变化,无需手动操作DOM,大大简化了开发流程。

核心算法与游戏逻辑实现

扫雷游戏的核心在于地雷放置、相邻计算和自动揭示算法,这些算法的效率直接影响游戏体验。

地雷放置与数字计算

地雷放置采用随机算法,确保在10x10的网格中均匀分布指定数量的地雷:

private placeMines() {let placed = 0;while (placed < this.mineCount) {let x = Math.floor(Math.random() * 10);let y = Math.floor(Math.random() * 10);if (!this.gameBoard[x][y].hasMine) {this.gameBoard[x][y].hasMine = true;placed++;}}
}

为避免地雷重叠,通过hasMine属性检查方块是否已放置地雷。这种实现方式简单直观,但在极端情况下(如剩余可放置位置较少时)可能出现性能问题,更优的实现可采用Fisher-Yates洗牌算法。

相邻地雷计算是扫雷游戏的核心算法之一,通过遍历当前方块周围8个方向的方块来统计地雷数量:

private countNeighborMines(row: number, col: number): number {let count = 0;for (let dx = -1; dx <= 1; dx++) {for (let dy = -1; dy <= 1; dy++) {if (dx === 0 && dy === 0) continue;let newRow = row + dx, newCol = col + dy;if (newRow >= 0 && newRow < 10 && newCol >= 0 && newCol < 10 && this.gameBoard[newRow][newCol].hasMine) {count++;}}}return count;
}

该算法的时间复杂度为O(1),因为每个方块最多检查8个相邻方块,确保了游戏的流畅运行。

自动揭示与胜利判定

自动揭示算法是扫雷游戏的灵魂,当玩家点击一个周围没有地雷的方块时,需要递归揭示其周围所有安全方块:

private revealCell(row: number, col: number) {if (this.isGameOver || this.revealedCells.has(`${row},${col}`)) return;const key = `${row},${col}`;this.revealedCells.add(key);if (this.gameBoard[row][col].hasMine) {this.showGameOverDialog();} else {if (this.gameBoard[row][col].neighborMines === 0) {for (let dx = -1; dx <= 1; dx++) {for (let dy = -1; dy <= 1; dy++) {if (dx === 0 && dy === 0) continue;let newRow = row + dx, newCol = col + dy;if (newRow >= 0 && newRow < 10 && newCol >= 0 && newCol < 10) {this.revealCell(newRow, newCol);}}}}}if (this.isVictory()) {this.showVictoryDialog();}
}

递归实现的自动揭示算法简洁明了,但在极端情况下(如点击一个大面积的空白区域)可能导致栈溢出。鸿蒙OS的JavaScript引擎支持尾递归优化,但更安全的实现可采用迭代方式(如BFS或DFS)。

胜利判定算法通过统计已揭示的非地雷方块数量来判断游戏是否胜利:

private isVictory() {let revealedNonMineCount = 0;const totalNonMineCells = 10 * 10 - this.mineCount;for (let i = 0; i < 10; i++) {for (let j = 0; j < 10; j++) {if (this.revealedCells.has(`${i},${j}`)) {revealedNonMineCount++;}}}return revealedNonMineCount === totalNonMineCells;
}

性能优化策略

扫雷游戏在鸿蒙OS上的性能优化主要体现在以下几个方面:

  1. 数据结构优化:使用Set存储已揭示和标记的方块,确保查找操作的高效性
  2. 避免重复计算:地雷相邻数量在初始化时计算完成,游戏过程中无需重复计算
  3. 事件节流:虽然代码中未显式实现,但鸿蒙OS的手势处理底层已做优化,避免高频点击导致的性能问题
  4. 组件复用:通过ForEach循环动态生成方块组件,避免静态创建100个组件的性能开销

交互设计与用户体验优化

鸿蒙扫雷游戏在交互设计上充分考虑了移动端的操作特点,通过手势识别和视觉反馈提升用户体验。

手势交互实现

游戏支持两种核心手势:单击揭示方块和长按标记地雷,通过parallelGesture实现手势组合:

.parallelGesture(GestureGroup(GestureMode.Exclusive,TapGesture({ count: 1, fingers: 1 }).onAction(() => this.revealCell(rowIndex, colIndex)),LongPressGesture({ repeat: true }).onAction(() => cell.isFlag = true)
));

GestureMode.Exclusive确保两种手势不会冲突,长按操作会优先于单击操作。repeat: true参数允许长按持续触发标记状态,提升操作流畅度。

视觉反馈设计

视觉反馈是扫雷游戏体验的重要组成部分,鸿蒙游戏通过以下方式提供清晰的反馈:

  1. 颜色变化:已揭示的方块背景色变为白色,地雷方块显示为红色
  2. 数字标识:显示相邻地雷数量,数字颜色根据数量不同(如1为蓝色,2为绿色)
  3. 标记旗帜:长按标记的方块显示"旗"字,帮助用户记录可疑地雷位置
  4. 游戏状态提示:通过对话框提示游戏结束或胜利,并显示用时
Text(this.isShowValue(cell)).backgroundColor(this.revealedCells.has(`${rowIndex},${colIndex}`) ?(this.isShowValue(cell) === '雷' ? Color.Red : Color.White) : Color.Gray).fontColor(!this.revealedCells.has(`${rowIndex},${colIndex}`) || this.isShowValue(cell) === '雷' ?Color.White : Color.Black)

响应式布局设计

游戏界面采用响应式设计,通过cellSize状态动态调整方块大小,确保在不同尺寸的设备上都有良好的显示效果:

// 游戏面板容器
Flex({ wrap: FlexWrap.Wrap }) {// 方块生成逻辑...
}
.width(`${(this.cellSize + this.cellMargin * 2) * 10}lpx`);

这种设计使得游戏能够自适应手机、平板等不同设备的屏幕尺寸,无需为每种设备单独开发界面。

鸿蒙特性在游戏开发中的应用

扫雷游戏的鸿蒙实现充分利用了平台的特有能力,展现了鸿蒙OS在应用开发中的优势。

声明式UI与状态管理

鸿蒙OS的声明式UI模型使得游戏界面与数据状态紧密绑定,当gameBoard或状态集合变化时,UI会自动更新,大大简化了开发流程:

// 状态变化自动触发UI更新
this.revealedCells.add(`${row},${col}`);// 视图根据状态动态渲染
Text(this.isShowValue(cell)).visibility(cell.isFlag && !this.isGameOver ? Visibility.Visible : Visibility.None)

这种数据驱动视图的模式避免了传统命令式UI中繁琐的DOM操作,提高了代码的可维护性。

组件化与复用

游戏中的每个方块都是一个可复用的组件单元,通过ForEach循环动态生成,这种组件化思想是鸿蒙应用开发的核心:

ForEach(this.gameBoard, (row: Cell[], rowIndex: number) => {ForEach(row, (cell: Cell, colIndex: number) => {Stack() {// 方块UI组件...}});
});

组件化设计使得游戏界面结构清晰,同时便于后续扩展,如添加不同难度级别或主题皮肤。

系统能力集成

游戏集成了鸿蒙OS的系统能力,如对话框提示功能:

promptAction.showDialog({title: '游戏结束: 游戏失败!',buttons: [{ text: '重新开始', color: '#ffa500' }]
}).then(() => {this.initializeGame();
});

promptAction是鸿蒙OS提供的系统对话框API,支持自定义标题、消息和按钮,使得游戏能够无缝融入系统交互体系。

游戏扩展与进阶优化

基于当前的扫雷游戏实现,还可以从以下几个方面进行扩展和优化:

难度级别扩展

添加不同难度级别是扫雷游戏的常见需求,可通过修改网格大小和地雷数量实现:

// 简单模式:8x8网格,10个地雷
private initEasyMode() {this.mineCount = 10;this.generateBoard(8, 8);
}// 中级模式:16x16网格,40个地雷
private initMediumMode() {this.mineCount = 40;this.generateBoard(16, 16);
}// 高级模式:30x16网格,99个地雷
private initHardMode() {this.mineCount = 99;this.generateBoard(30, 16);
}

同时需要调整cellSize以适应不同网格大小,确保界面在各种难度下都能良好显示。

主题与视觉优化

添加主题切换功能可以提升游戏体验,可通过定义不同的颜色方案实现:

// 主题接口
interface Theme {cellColor: ResourceColor;revealedColor: ResourceColor;mineColor: ResourceColor;numberColors: ResourceColor[];
}// 亮色主题
const lightTheme: Theme = {cellColor: Color.Gray,revealedColor: Color.White,mineColor: Color.Red,numberColors: [Color.Blue, Color.Green, Color.Orange, Color.Red, Color.Purple, Color.Teal, Color.Brown, Color.Black]
};// 暗色主题
const darkTheme: Theme = {cellColor: Color.DarkGray,revealedColor: Color.DimGray,mineColor: Color.Red,numberColors: [Color.SkyBlue, Color.Lime, Color.Orange, Color.Red, Color.Plum, Color.Aqua, Color.Chocolate, Color.White]
};

性能与体验优化

针对大规模网格(如高级模式30x16),可实现以下优化:

  1. 虚拟滚动:只渲染可见区域的方块,而非全部方块
  2. 异步初始化:使用setTimeout分批次初始化地雷和计算数字,避免UI卡顿
  3. 手势优化:添加双击快捷揭示功能(点击数字方块时揭示周围未标记方块)
  4. 动画效果:为方块揭示添加淡入动画,提升视觉体验
// 双击快捷揭示
doubleTapGesture().onAction(() => {if (this.gameBoard[row][col].neighborMines > 0) {this.revealSurroundingCells(row, col);}})

附:代码

import { promptAction } from '@kit.ArkUI';@Entry
@Component
struct Index {// 游戏面板数据@State private gameBoard: Cell[][] = [];// 地雷总数@State private mineCount: number = 10;// 已经揭示的方块集合@State private revealedCells: Set<string> = new Set();// 标记为地雷的方块集合@State private flaggedCells: Set<string> = new Set();// 方块大小@State private cellSize: number = 60;// 方块之间的边距@State private cellMargin: number = 2;// 游戏开始时间private startTime: number = Date.now();// 游戏结束标志@State private isGameOver: boolean = false;// 在组件即将显示时初始化游戏aboutToAppear(): void {this.initializeGame();}// 初始化游戏private initializeGame() {this.isGameOver = false;this.startTime = Date.now();this.revealedCells.clear();this.flaggedCells.clear();this.generateBoard();}// 生成游戏面板private generateBoard() {this.gameBoard = [];for (let i = 0; i < 10; i++) {this.gameBoard.push([]);for (let j = 0; j < 10; j++) {this.gameBoard[i].push(new Cell(i, j));}}this.placeMines();this.calculateNumbers();}// 随机放置地雷private placeMines() {let placed = 0;while (placed < this.mineCount) {let x = Math.floor(Math.random() * 10);let y = Math.floor(Math.random() * 10);if (!this.gameBoard[x][y].hasMine) {this.gameBoard[x][y].hasMine = true;placed++;}}}// 计算每个方块周围的地雷数量private calculateNumbers() {for (let i = 0; i < 10; i++) {for (let j = 0; j < 10; j++) {if (!this.gameBoard[i][j].hasMine) {this.gameBoard[i][j].neighborMines = this.countNeighborMines(i, j);this.gameBoard[i][j].value = this.gameBoard[i][j].neighborMines.toString();} else {this.gameBoard[i][j].value = '雷';}}}}// 计算给定坐标周围地雷的数量private countNeighborMines(row: number, col: number): number {let count = 0;for (let dx = -1; dx <= 1; dx++) {for (let dy = -1; dy <= 1; dy++) {if (dx === 0 && dy === 0) {continue;}let newRow = row + dx, newCol = col + dy;if (newRow >= 0 && newRow < 10 && newCol >= 0 && newCol < 10 && this.gameBoard[newRow][newCol].hasMine) {count++;}}}return count;}// 揭示方块private revealCell(row: number, col: number) {if (this.isGameOver || this.revealedCells.has(`${row},${col}`)) {return;}const key = `${row},${col}`;this.revealedCells.add(key);if (this.gameBoard[row][col].hasMine) {this.showGameOverDialog();} else {if (this.gameBoard[row][col].neighborMines === 0) {for (let dx = -1; dx <= 1; dx++) {for (let dy = -1; dy <= 1; dy++) {if (dx === 0 && dy === 0) {continue;}let newRow = row + dx, newCol = col + dy;if (newRow >= 0 && newRow < 10 && newCol >= 0 && newCol < 10) {this.revealCell(newRow, newCol);}}}}}if (this.isVictory()) {this.showVictoryDialog();}}// 显示游戏结束对话框private showGameOverDialog() {this.isGameOver = true;promptAction.showDialog({title: '游戏结束: 游戏失败!',buttons: [{ text: '重新开始', color: '#ffa500' }]}).then(() => {this.initializeGame();});}// 显示胜利对话框private showVictoryDialog() {this.isGameOver = true;promptAction.showDialog({title: '恭喜你,游戏胜利!',message: `用时:${((Date.now() - this.startTime) / 1000).toFixed(3)}秒`,buttons: [{ text: '重新开始', color: '#ffa500' }]}).then(() => {this.initializeGame();});}// 判断游戏是否胜利private isVictory() {let revealedNonMineCount = 0;for (let i = 0; i < this.gameBoard.length; i++) {for (let j = 0; j < this.gameBoard[i].length; j++) {if (this.revealedCells.has(`${i},${j}`)) {revealedNonMineCount++;}}}return revealedNonMineCount == 90;}// 决定是否显示方块值private isShowValue(cell: Cell): string {if (this.isGameOver) {return cell.value === '0' ? '' : cell.value;} else {if (this.revealedCells.has(`${cell.row},${cell.column}`)) {return cell.value === '0' ? '' : cell.value;} else {return '';}}}build() {Column({ space: 10 }) {// 重置游戏按钮Button('重新开始').onClick(() => {this.initializeGame()});// 创建游戏面板容器Flex({ wrap: FlexWrap.Wrap }) {// 遍历每一行ForEach(this.gameBoard, (row: Cell[], rowIndex: number) => {// 遍历每一列ForEach(row, (cell: Cell, colIndex: number) => {Stack() {// 显示方块上的数字或雷Text(this.isShowValue(cell)).width(`${this.cellSize}lpx`).height(`${this.cellSize}lpx`).margin(`${this.cellMargin}lpx`).fontSize(`${this.cellSize / 2}lpx`).textAlign(TextAlign.Center).backgroundColor(this.revealedCells.has(`${rowIndex},${colIndex}`) ?(this.isShowValue(cell) === '雷' ? Color.Red : Color.White) : Color.Gray).fontColor(!this.revealedCells.has(`${rowIndex},${colIndex}`) || this.isShowValue(cell) === '雷' ?Color.White : Color.Black).borderRadius(5).parallelGesture(GestureGroup(GestureMode.Exclusive,TapGesture({ count: 1, fingers: 1 }).onAction(() => this.revealCell(rowIndex, colIndex)),LongPressGesture({ repeat: true }).onAction(() => cell.isFlag = true)));// 显示标记旗帜Text(`${!this.revealedCells.has(`${rowIndex},${colIndex}`) ? '旗' : ''}`).width(`${this.cellSize}lpx`).height(`${this.cellSize}lpx`).margin(`${this.cellMargin}lpx`).fontSize(`${this.cellSize / 2}lpx`).textAlign(TextAlign.Center).fontColor(Color.White).visibility(cell.isFlag && !this.isGameOver ? Visibility.Visible : Visibility.None).onClick(() => {cell.isFlag = false;})}});});}.width(`${(this.cellSize + this.cellMargin * 2) * 10}lpx`);}.padding(20).backgroundColor('#ffffff').width('100%').height('100%');}
}// 方块类
@ObservedV2
class Cell {// 方块所在的行row: number;// 方块所在的列column: number;// 是否有地雷hasMine: boolean = false;// 周围地雷数量neighborMines: number = 0;// 是否被标记为地雷@Trace isFlag: boolean = false;// 方块值@Trace value: string;// 构造函数constructor(row: number, column: number) {this.row = row;this.column = column;this.value = '';}
}

鸿蒙OS扫雷游戏的开发实践展示了平台在游戏应用开发中的强大能力,从声明式UI的高效开发到系统能力的深度集成,再到性能优化和交互设计,鸿蒙OS为开发者提供了完整的解决方案。扫雷游戏作为经典的算法与交互结合的案例,其实现过程涵盖了数据结构、算法设计、用户体验等多个维度,对于理解移动应用开发具有重要参考价值。

随着鸿蒙OS生态的不断发展,游戏开发者可以进一步利用ArkTS语言的特性和平台的底层能力,开发出更复杂、更具沉浸感的游戏应用。从扫雷这样的轻量级游戏到更大型的3D游戏,鸿蒙OS都提供了从开发到部署的全流程支持,为开发者和用户带来全新的体验。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux C语言的opendir如何获取目录下的隐藏文件

在 Linux 文件系统中&#xff0c;所谓隐藏文件是文件名以 . 开头的文件&#xff08;例如 .bashrc、.git、.config 等&#xff09;。 在编程层面&#xff0c;opendir readdir 并不会自动排除隐藏文件。 只要你不在代码中手动过滤&#xff0c;readdir 会把目录下所有文件&#…

母线槽接头过热隐患难防?在线测温方案实时守护电力安全

近年来&#xff0c;由于各种设备对电力的大力需求&#xff0c;并有逐年增加的趋势&#xff0c;传统电路接线方式在施工时越来越力不从心。系统一旦定型&#xff0c;后续想要简化变更更是难上加难。母线槽方案因此兴起&#xff0c;凭借多点连接&#xff08;接头、插接头、插接箱…

Windows本地部署wordpress

一、下载wordpress 地址&#xff1a;Download – WordPress.org 下载后解压出来 二、下载小皮面板 地址&#xff1a;Windows版phpstudy下载 - 小皮面板(phpstudy) 下载后安装 三、打开小皮面板&#xff0c;安装对应内置应用 1、MySQL8&#xff08;注意要是8版本,卸载其他版本…

Android 性能优化

一、Android中检测性能工具 Profiler —— 使用Profiler的CPU分析功能。 Method Tracing ———— 通过该方法,我们可以记录应用运行过程中的方法调用情况,包括每个方法的执行时间、调用次数等。 Systrace 是Android平台提供的一款工具,用于记录短期内的设备活动。 Systra…

图片压缩工具 | Electron应用配合 commander 提供命令行调用功能

OPEN-IMAGE-TINY&#xff0c;一个基于 Electron VUE3 的图片压缩工具&#xff0c;项目开源地址&#xff1a;https://github.com/0604hx/open-image-tiny 功能描述 应用程序的命令行调用功能允许用户通过终端&#xff08;如Windows的CMD/PowerShell或Linux/macOS的Terminal&am…

Linux》》Shell脚本 基本语法

执行脚本的三种方式 查找变量的过程 变量引用的顺序》》先从当前进程查询变量&#xff0c;如果当前进程没有此变量&#xff0c;默认去父进程查找这个变量。如果查找到则返回&#xff0c;否则一直查找到 祖宗&#xff08;PID为1&#xff09;&#xff0c;还没有&#xff0c;则就…

C#.VB.NET多线程,多用户下独立锁和全局锁的区别

以下代码,每个客户端都分配了一个锁吗? 用户WebSocket信息类Public Class UserWebSocketInfoPublic Property SessionID As StringPublic Property WebSocket As WebSocketPublic Property LastResponseTime As DateTimePublic Property PendingHeartbeatCount As IntegerPubl…

无人机加速器模块技术解析

一、加速器模块的运行方式 1. 传感器数据采集与融合 加速度计核心作用&#xff1a;测量三维线性加速度&#xff08;X/Y/Z轴&#xff09;&#xff0c;结合陀螺仪&#xff08;角速度&#xff09;和磁力计&#xff08;方向&#xff09;构成九轴姿态传感器&#xff0c;实时输出…

用html实现数字生命

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>数学粒子动画</title><style>body {mar…

SQLite3 在嵌入式系统中的应用指南

SQLite3 在嵌入式系统中的应用指南 一、嵌入式系统中 SQLite3 的优势 SQLite3 是嵌入式系统的理想数据库解决方案&#xff0c;具有以下核心优势&#xff1a; 特性嵌入式系统价值典型指标轻量级适合资源受限环境库大小&#xff1a;500-700KB零配置无需数据库管理员开箱即用无…

通义大模型与现有企业系统集成实战《CRM案例分析与安全最佳实践》

1. 集成架构设计 &#xff08;1&#xff09;混合部署架构演进 #mermaid-svg-eW4YPoU2fdbnT4xp {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-eW4YPoU2fdbnT4xp .error-icon{fill:#552222;}#mermaid-svg-eW4YPoU2f…

leetcode:746. 使用最小花费爬楼梯

学习要点 动态规划正着推动态规划倒着推理解递归在动态规划与纯递归的类比分析中体会两者各自的特点 题目链接 746. 使用最小花费爬楼梯 - 力扣&#xff08;LeetCode&#xff09; 题目描述 解法1&#xff1a;动态规划倒着推 // dp[i]--->从第i阶楼梯到达楼顶最小花费int…

汽车毫米波雷达增强感知:基于相干扩展和高级 IAA 的超分辨率距离和角度估计.

重庆西南大学毫米波雷达团队在IEEE Transactions on Consumer Electronics 上发表的一篇论文&#xff1a;《基于相干扩展和高级 IAA 的超分辨率距离和角度估计》。 本文深入研究了毫米波&#xff08;mmWave&#xff09;调频连续波雷达距离和角度的超分辨问题。首先&#xff0c;…

软件更新 | 从数据到模型,全面升级!TSMaster新版助力汽车研发新突破

为满足汽车电子开发领域日益增长的测试与仿真需求&#xff0c;TSMaster最新版本聚焦实车数据采集、MBD智能建模与新API扩展三大核心功能。无论您是进行车载网络测试、ECU开发还是自动化验证&#xff0c;新版本都能为您提供更高效、更可靠的解决方案&#xff01; TSMaster 2025.…

PDF-XSS

前言&#xff1a; PDF文件是一种复杂的文档格式&#xff0c;由一系列对象组成&#xff0c;包括字体、图像、页面内容等。PDF文件支持嵌入JavaScript代码&#xff0c;这使得PDF文件不仅可以显示静态内容&#xff0c;还可以执行动态操作。这种特性被攻击者利用来嵌入恶意脚本代码…

MySQL 表关联关系详解

MySQL 表关联关系详解 本文档详细列举了MySQL中常见的表关联关系场景以及对应的SQL语句示例。 1. 一对一关系 (One-to-One) 场景&#xff1a;用户表和用户详情表 一个用户对应一个用户详情通常用于将大表拆分&#xff0c;提高查询性能 -- 创建用户表 CREATE TABLE users (…

kubernetes(k8s)集群部署(超详细)

k8s部署 kubernetes集群图例kubernetes 安装仓库初始化1、创建云主机2、初始化私有仓库kube-master安装1、防火墙相关配置2、配置yum仓库(跳板机)3、安装软件包(master)4、镜像导入私有仓库5、Tab键设置6、安装代理软件包7、配置内核参数8、使用kubeadm部署9、验证安装结果计算…

「Flink」算子主要方法介绍

背景&#xff1a; 上期文章主要讲了Flink项目搭建的一些方法&#xff0c;其中对于数据流的处理很大一部分是通过算子来进行计算和处理的&#xff0c;算子也是Flink中功能非常庞大&#xff0c;且很重要的一部分。 算子介绍&#xff1a; 算子在Flink的开发者文档中是这样介绍的…

3405. 统计恰好有 K 个相等相邻元素的数组数目

3405. 统计恰好有 K 个相等相邻元素的数组数目 给你三个整数 n &#xff0c;m &#xff0c;k 。长度为 n 的 好数组 arr 定义如下&#xff1a; arr 中每个元素都在 闭 区间 [1, m] 中。恰好 有 k 个下标 i &#xff08;其中 1 < i < n&#xff09;满足 arr[i - 1] arr…

Spring AI 项目实战(十):Spring Boot + AI + DeepSeek 构建智能合同分析技术实践(附完整源码)

系列文章 序号文章名称1Spring AI 项目实战(一):Spring AI 核心模块入门2Spring AI 项目实战(二):Spring Boot + AI + DeepSeek 深度实战(附完整源码)3Spring AI 项目实战(三):Spring Boot + AI + DeepSeek 打造智能客服系统(附完整源码)4