HarmonyOS开发实战:【亲子拼图游戏】

概述

本篇Codelab是基于TS扩展的声明式开发范式编程语言编写的一个分布式益智拼图游戏,可以两台设备同时开启一局拼图游戏,每次点击九宫格内的图片,都会同步更新两台设备的图片位置。效果图如下:

 说明:  本示例涉及使用系统接口,需要手动替换Full SDK才能编译通过。

搭建OpenHarmony环境

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以Hi3516DV300开发板为例,参照以下步骤进行:

  1. [获取OpenHarmony系统版本]):标准系统解决方案(二进制)。

    以3.0版本为例:

  2. 搭建烧录环境。

    1. [完成DevEco Device Tool的安装]
    2. [完成Hi3516开发板的烧录]
    3. 鸿蒙开发指导:qr23.cn/AKFP8k点击或复制转到。
  3. 搭建开发环境。

    1. 开始前请参考[工具准备],完成DevEco Studio的安装和开发环境配置。
    2. 开发环境配置完成后,请参考[使用工程向导]创建工程(模板选择“Empty Ability”),选择JS或者eTS语言开发。
    3. 工程创建完成后,选择使用[真机进行调测]。
      2.鸿蒙HarmonyOS与OpenHarmony文档籽料mau123789是v直接拿

搜狗高速浏览器截图20240326151450.png

分布式组网

本章节以系统自带的音乐播放器为例(具体以实际的应用为准),介绍如何完成两台设备的分布式组网。

  1. 硬件准备:准备两台烧录相同的版本系统的Hi3516DV300开发板A、B。

  2. 开发板A、B连接同一个WiFi网络。

    打开设置–>WLAN–>点击右侧WiFi开关–>点击目标WiFi并输入密码。

  3. 将设备A,B设置为互相信任的设备。

    • 找到系统应用“音乐”。

    • 设备A打开音乐,点击左下角流转按钮,弹出列表框,在列表中会展示远端设备的id。

    • 选择远端设备B的id,另一台开发板(设备B)会弹出验证的选项框。

    • 设备B点击允许,设备B将会弹出随机PIN码,将设备B的PIN码输入到设备A的PIN码填入框中。

    配网完毕。

代码结构解读

本篇Codelab只对核心代码进行讲解,首先来介绍下整个工程的代码结构:

  • MainAbility:存放应用主页面。

    • pages/index.ets:应用主页面。
  • model:存放获取组网内的设备列表相关文件。

    • RemoteDeviceModel.ets:获取组网内的设备列表。
  • ServiceAbility:存放ServiceAbility相关文件。

    • service.ts:service服务,创建一个ServiceAbility,用于跨设备连接后通讯。
  • resources :存放工程使用到的资源文件。

    • resources/rawfile:存放工程中使用的图片资源文件。
  • config.json:配置文件。

实现页面布局和样式

在本章节中,您将学会如何制作一个简单的拼图游戏。

  1. 实现主页面布局和样式。

    • 在MainAbility/pages/index.ets 主界面文件中添加入口组件PictureGame。PictureGame组件页面布局代码如下:

      // 入口组件
      @Entry
      @Component
      struct PictureGame {
        @Provide imageIndexForPosition: number[] = []
        @Provide pictureList: string[]= []
        build() {
          Column() {
            Text("益智拼图游戏").fontSize(40).margin({ top: 30, bottom: 30 })
            PictureGrid()
            Row() {
              Button("重新开始").fontSize(20).margin({ right: 10 }).onClick(() => {
                ...
              })
              Button("亲子协同").fontSize(20).margin({ left: 10 }).onClick(()=>{
                ...
              })
            }.margin(30)
            Image($rawfile('picture.jpg')).width(300).height(300)
      
          }
          .width('100%')
          .height('100%')
        }
      }
      
    • 给PictureGame组件添加九宫格拼图子组件PictureGrid。PictureGrid九宫格拼图组件主要是由[Grid组件]、[GridItem组件]和[Image组件]构成,页面布局代码如下:

      // 九宮格拼图组件
      @Component
      struct PictureGrid {
        private gridRowTemplate: string = ''
        @Consume imageIndexForPosition : number[]
        @Consume pictureList: string[]
        private heightValue: number
      
        aboutToAppear() {
          var rows = Math.round(this.pictureList.length / 3);
          this.gridRowTemplate = '1fr '.repeat(rows);
          this.heightValue = rows * 101 ;
        }
      
        build() {
          Column() {
            Grid() {
              ForEach(this.pictureList.map((item,index)=>{return {i:index,data:item};}),(item,index) => {
                GridItem() {
                  Image($rawfile(this.pictureList[item.i]))
                    .width(100)
                    .height(100)
                    .onClick(() => {
                     ...
                    })
                }
              }, (item: string) => item.toString())
            }
            .rowsTemplate(this.gridRowTemplate)
            .columnsTemplate('1fr 1fr 1fr')
            .columnsGap(1)
            .rowsGap(1)
            .height(this.heightValue)
            .width(303)
          }
        }
      }
      

      在入口组件的生命周期函数aboutToAppear()中调用onRandom()方法,初始化imageIndexForPosition数组。如果Ability是被其他设备拉起的,在aboutToAppear()中调用featureAbility.getWant(),可通过want中的参数重新初始化imageIndexForPosition数组和pictureList数组,入口组件的生命周期函数aboutToAppear()代码如下:

      async aboutToAppear() {
        let self =this;
        this.onRandom();
        // 当被拉起时,通过want传递的参数同步对端界面UI
        await featureAbility.getWant((error, want) => {
          var status = want.parameters;
          if(want.parameters.pictureList){
            self.pictureList = JSON.parse(status.pictureList)
            self.imageIndexForPosition = status.imageIndexForPosition;
            // 远端被拉起后,连接对端的service
            if(want.parameters.remoteDeviceId) {
              let remoteDeviceId = want.parameters.remoteDeviceId
              onConnectRemoteService(remoteDeviceId)
            }
          }
        });
      }
      
  2. 给"重新开始"按钮添加点击事件。

    点击"重新开始"按钮,调用onRandom()方法,打乱图片现阶段排列顺序,在onRandom()调用setupRandomPosition()方法,初始化imageIndexForPosition数组,onRandom()和setupRandomPosition()代码如下:

    onRandom() {
      this.setupRandomPosition();
      this.pictureList = []
      this.imageIndexForPosition.forEach(value => {
        if (value == 9) {
          this.pictureList.push("--")
        } else {
          this.pictureList.push(`picture_0` + value + `.png`)
        }
      });
    }
    // 初始化imageIndexForPosition数组
    setupRandomPosition() {
      let list1 = [5, 4, 3, 9, 1, 8, 6, 7, 2];
      let list2 = [3, 1, 6, 7, 9, 8, 4, 2, 5];
      let list3 = [4, 8, 3, 5, 2, 7, 9, 1, 6];
      let list4 = [4, 3, 5, 2, 8, 7, 6, 1, 9];
      let lists = [list1, list2, list3, list4];
      this.imageIndexForPosition = lists[Math.floor(Math.random() * 4)];
    }
    
  3. 给九宫格内的每张图片添加点击事件。

    点击九宫格内的图片,调用onchange()方法,每一次点击后,需要调用onFinish()方法校验当前imageIndexForPosition 中的元素是否是从小到大排列。其中onChange()和onFinish()方法代码如下

    onChange(index) {
      let self = this;
      // 相邻位置数组
      let menu = {
        "1": [2, 4],
        "2": [1, 3, 5],
        "3": [2, 6],
        "4": [1, 5, 7],
        "5": [2, 4, 6, 8],
        "6": [3, 5, 9],
        "7": [4, 8],
        "8": [5, 7, 9],
        "9": [6, 8]
      }
      // 被点击的图片位置
      let click_num = index + 1;
      // 空白图片位置
      let no_see_num = self.imageIndexForPosition.indexOf(9) + 1;
      // 获取点击后能够移动的图片位置
      let arr = menu[no_see_num];
      // 判断arr是否包含点击的图片
      if(arr.length==2){
        if (!(arr[0]==click_num||arr[1]==click_num)) {
    
        } else {
          let temp = self.imageIndexForPosition[no_see_num - 1];
          self.imageIndexForPosition[no_see_num - 1] = self.imageIndexForPosition[click_num - 1];
          self.imageIndexForPosition[click_num - 1] = temp;
    
          self.pictureList = [];
          self.imageIndexForPosition.forEach(value => {
            if (value == 9) {
              self.pictureList.push("--")
            } else {
              self.pictureList.push(`picture_0` + value + `.png`)
            }
          });
        }
      }else if(arr.length==3){
        if (!(arr[0]==click_num||arr[1]==click_num||arr[2]==click_num)) {
          
        } else {
          let temp = self.imageIndexForPosition[no_see_num - 1];
          self.imageIndexForPosition[no_see_num - 1] = self.imageIndexForPosition[click_num - 1];
          self.imageIndexForPosition[click_num - 1] = temp;
    
          self.pictureList = [];
          self.imageIndexForPosition.forEach(value => {
            if (value == 9) {
              self.pictureList.push("--")
            } else {
              self.pictureList.push(`picture_0` + value + `.png`)
            }
          });
        }
      }else if(arr.length==4){
        if (!(arr[0]==click_num||arr[1]==click_num||arr[2]==click_num||arr[3]==click_num)) {
          
        } else {
          let temp = self.imageIndexForPosition[no_see_num - 1];
          self.imageIndexForPosition[no_see_num - 1] = self.imageIndexForPosition[click_num - 1];
          self.imageIndexForPosition[click_num - 1] = temp;
    
          self.pictureList = [];
          self.imageIndexForPosition.forEach(value => {
            if (value == 9) {
              self.pictureList.push("--")
            } else {
              self.pictureList.push(`picture_0` + value + `.png`)
            }
          });
        }
      }
      // 发送消息到远端Service服务
      sendMessageToRemoteService(JSON.stringify(self.imageIndexForPosition));
      // 判断是否完成拼接
      self.onFinish();
    }
    
    onFinish() {
      let finalList = [1, 2, 3, 4, 5, 6, 7, 8, 9];
      if (this.equarList(this.imageIndexForPosition, finalList)) {
        this.pictureList = [];
        this.imageIndexForPosition.forEach(value => {
          this.pictureList.push("picture_0" + value + ".png")
        });
        prompt.showToast({
          message: "success"
        });
        // 完成拼接后断开Service连接
        onDisconnectService();
      }
    }
    

拉起远端FA,并连接远端Service服务

在本章节中,您将学会如何拉起在同一组网内的设备上的FA,创建并连接远端Service服务。

  1. 调用featureAbility.startAbility()方法,拉起远端FA,并同步界面UI。

    点击"亲子协同"按钮,调用RegisterDeviceListCallback()发现设备列表,并弹出设备列表选择框CustomDialogExample,选择设备后拉起远端FA。CustomDialogExample()代码如下:

    // 设备列表弹出框
    @CustomDialog
    struct CustomDialogExample {
      @State editFlag: boolean = false
      @Consume imageIndexForPosition : number[]
      @Consume pictureList: string[]
      controller: CustomDialogController
      cancel: () => void
      confirm: () => void
      build() {
        Column() {
          List({ space: 10, initialIndex: 0 }) {
            ForEach(DeviceIdList, (item) => {
              ListItem() {
                Row() {
                  Text(item)
                    .width('87%').height(50).fontSize(10)
                    .textAlign(TextAlign.Center).borderRadius(10).backgroundColor(0xFFFFFF)
                    .onClick(() => {
                      onStartRemoteAbility(item,this.imageIndexForPosition,this.pictureList);
                      this.controller.close();
                    })
                  Radio({value:item})
                    .onChange((isChecked) => {
                      onStartRemoteAbility(item,this.imageIndexForPosition,this.pictureList);
                      this.controller.close();
                    }).checked(false)
                }
              }.editable(this.editFlag)
            }, item => item)
          }
        }.width('100%').height(200).backgroundColor(0xDCDCDC).padding({ top: 5 })
      }
    }
    

    点击Text组件或者Radio组件都会调用onStartRemoteAbility()方法拉起远端FA,onStartRemoteAbility()代码如下:

    function onStartRemoteAbility(deviceId,imageIndexForPosition,pictureList: string[]) {
      AuthDevice(deviceId);
      let numDevices = remoteDeviceModel.deviceList.length;
      if (numDevices === 0) {
        prompt.showToast({
          message: "onStartRemoteAbility no device found"
        });
        return;
      }
    
      var params = {
        imageIndexForPosition: JSON.stringify(imageIndexForPosition),
        pictureList : JSON.stringify(pictureList),
        remoteDeviceId : localDeviceId
      }
      var wantValue = {
        bundleName: 'com.huawei.cookbook',
        abilityName: 'com.example.openharmonypicturegame.MainAbility',
        deviceId: deviceId,
        parameters: params
      };
      featureAbility.startAbility({
        want: wantValue
      }).then((data) => {
        // 拉起远端后,连接远端service
        onConnectRemoteService(deviceId)
      });
    }
    

    创建ServiceAbility,步骤如下图所示:

  2. 调用featureAbility.connectAbility方法,连接远端Service服务,连接成功后返会remote对象。

    在featureAbility.startAbility()成功的回调中调用onConnectRemoteService()方法,onConnectRemoteService()方法代码如下:

    // 连接远端Service
    async function onConnectRemoteService(deviceId) {
      // 连接成功的回调
      async function onConnectCallback(element, remote) {
         mRemote = remote;
      }
      // Service异常死亡的回调
      function onDisconnectCallback(element) {
      }
      // 连接失败的回调
      function onFailedCallback(code) {
        prompt.showToast({
          message: "onConnectRemoteService onFailed: " + code
        });
      }
      let numDevices = remoteDeviceModel.deviceList.length;
      if (numDevices === 0) {
        prompt.showToast({
          message: "onConnectRemoteService no device found"
        });
        return;
      }
      connectedAbility = await featureAbility.connectAbility(
        {
          deviceId: deviceId,
          bundleName: "com.huawei.cookbook",
          abilityName: "com.example.openharmonypicturegame.ServiceAbility",
        },
        {
          onConnect: onConnectCallback,
          onDisconnect: onDisconnectCallback,
          onFailed: onFailedCallback,
        },
      );
    }
    

    在配置文件config.json需要设置ServiceAbility的属性visible为true,代码如下:

    "abilities": [
          ...
          {
            "visible": true,
            "srcPath": "ServiceAbility",
            "name": ".ServiceAbility",
            "icon": "$media:icon",
            "srcLanguage": "ets",
            "description": "$string:description_serviceability",
            "type": "service"
          }
    ],
    

    同时,Service侧也需要在onConnect()时返回IRemoteObject,从而定义与Service进行通信的接口。onConnect()需要返回一个IRemoteObject对象,OpenHarmony提供了IRemoteObject的默认实现,通过继承rpc.RemoteObject来创建自定义的实现类。Service侧把自身的实例返回给调用侧的代码如下:

    import rpc from "@ohos.rpc";
    import commonEvent from '@ohos.commonEvent';
    class FirstServiceAbilityStub extends rpc.RemoteObject{
        constructor(des) {
            if (typeof des === 'string') {
                super(des);
            } else {
                return null;
            }
        }
        onRemoteRequest(code, data, reply, option) {
            if (code === 1) {
                let arr = data.readIntArray();
                reply.writeInt(100);
                // 发布公共事件相关流程
    	    ...
    
    
            } else {
            }
            return true;
        }
    }
    
    export default {
        // 创建Service的时候调用,用于Service的初始化
        onStart() {
        },
        // 在Service销毁时调用。Service应通过实现此方法来清理任何资源,如关闭线程、注册的侦听器等。
        onStop() {
        },
        // 在Ability和Service连接时调用,该方法返回IRemoteObject对象,开发者可以在该回调函数中生成对应Service的IPC通信通道
        onConnect(want) {
            try {
                let value = JSON.stringify(want);
            } catch(error) {
            }
            return new FirstServiceAbilityStub("[pictureGame] first ts service stub");
        },
        // 在Ability与绑定的Service断开连接时调用
        onDisconnect(want) {
            let value = JSON.stringify(want);
        },
        // 在Service创建完成之后调用,该方法在客户端每次启动该Service时都会调用
        onCommand(want, startId) {
            let value = JSON.stringify(want);
        }
    };
    

RPC跨设备通讯

在本章节中,您将学会在成功连接远端Service服务的前提下,如何利用RPC进行跨设备通讯。

  1. 成功连接远端Service服务的前提下,点击"重新开始"按钮或者九宫格内的图片,都会完成一次跨设备通讯,假如在设备A端点击"重新开始"按钮,消息的传递是由设备A端的FA传递到设备B的Service服务,发送消息的方法sendMessageToRemoteService()代码如下:

    // 连接成功后发送消息
    async function sendMessageToRemoteService(imageIndexForPosition) {
      if (mRemote == null) {
        prompt.showToast({
          message: "mRemote is null"
        });
        return;
      }
      let option = new rpc.MessageOption();
      let data = new rpc.MessageParcel();
      let reply = new rpc.MessageParcel();
      data.writeIntArray(JSON.parse(imageIndexForPosition));
      await mRemote.sendRequest(1, data, reply, option);
      let msg = reply.readInt();
    }
    
  2. 在B端的Service接收消息,当A端成功连接B端Service服务后,在A端会返回一个remote对象,当A端remote对象调用sendRequest()方法后,在B端的Service中的onRemoteRequest()方法中会接收到发送的消息,其中继承rpc.RemoteObject的类和onRemoteRequest()方法代码如下:

    class FirstServiceAbilityStub extends rpc.RemoteObject{
        constructor(des) {
            if (typeof des === 'string') {
                super(des);
            } else {
                return null;
            }
        }
    
        onRemoteRequest(code, data, reply, option) {
            if (code === 1) {
                // 从data中接收数据
                let arr = data.readIntArray();
                // 回复接收成功标识
                reply.writeInt(100);
                // 发布公共事件相关流程
               ...
    
            } else {
            }
            return true;
        }
    }
    

Service服务发布公共事件

当Service服务接收到消息后,在onRemoteRequest()发布公共事件,代码如下:

onRemoteRequest(code, data, reply, option) {
    if (code === 1) {
	// 从data中接收数据
	let arr = data.readIntArray();
	// 回复接收成功标识
	reply.writeInt(100);
	// 公共事件相关信息
	var params ={
	    imageIndexForPosition: arr
	}
	var options = {
            // 公共事件的初始代码
	    code: 1,
            // 公共事件的初始数据			
	    data: 'init data',、
            // 有序公共事件 	        
	    isOrdered: true, 	
	    bundleName: 'com.huawei.cookbook',
	    parameters: params

        }
	// 发布公共事件回调
	function PublishCallBack() {
	}
	// 发布公共事件
	commonEvent.publish("publish_moveImage", options, PublishCallBack);

	} else {
	}
	return true;
 }

在接收到消息后,把接收到的图片位置数组放入params中,然后发布名称为"publish_moveImage"的有序公共事件。

FA订阅公共事件

在本章节中,您将学会如何通过CommonEvent订阅公共事件。在九宫格组件PictureGrid的生命周期函数aboutToAppear()中,调用订阅公共事件方法subscribeEvent(),用来订阅"publish_moveImage"公共事件,subscribeEvent()代码如下:

 subscribeEvent(){
    let self = this;
    // 用于保存创建成功的订阅者对象,后续使用其完成订阅及退订的动作
    var subscriber; 
    // 订阅者信息
    var subscribeInfo = {
      events: ["publish_moveImage"],
      priority: 100

    };

    // 设置有序公共事件的结果代码回调
    function SetCodeCallBack(err) {
    }
    // 设置有序公共事件的结果数据回调
    function SetDataCallBack(err) {
    }
    // 完成本次有序公共事件处理回调
    function FinishCommonEventCallBack(err) {
    }
    // 订阅公共事件回调
    function SubscribeCallBack(err, data) {
      let msgData = data.data;
      let code = data.code;
      // 设置有序公共事件的结果代码
      subscriber.setCode(code, SetCodeCallBack);
      // 设置有序公共事件的结果数据
      subscriber.setData(msgData, SetDataCallBack);
      // 完成本次有序公共事件处理
      subscriber.finishCommonEvent(FinishCommonEventCallBack)
      // 处理接收到的数据data
      self.imageIndexForPosition = data.parameters.imageIndexForPosition;
      self.pictureList = [];
      self.imageIndexForPosition.forEach(value => {
        if (value == 9) {
          self.pictureList.push("--")
        } else {
          self.pictureList.push(`picture_0` + value + `.png`)
        }
      });

      self.onFinish();
    }

    // 创建订阅者回调
    function CreateSubscriberCallBack(err, data) {
      subscriber = data;
      // 订阅公共事件
      commonEvent.subscribe(subscriber, SubscribeCallBack);
    }

    // 创建订阅者
    commonEvent.createSubscriber(subscribeInfo, CreateSubscriberCallBack);
 }

在FA中订阅到Service服务发布的"publish_moveImage"事件后,在SubscribeCallBack()回调中重新赋值imageIndexForPosition数组与pictureList数组,从而同步更新界面UI。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2016NOIP普及组真题 1. 金币

线上OJ&#xff1a; 一本通&#xff1a;http://ybt.ssoier.cn:8088/problem_show.php?pid1969 核心思想&#xff1a; 解法1、由于数据量只有 10000 天&#xff0c;估可以采用 模拟每一天 的方式。 #include <bits/stdc.h> using namespace std;int k 0;int main() {i…

SpringBoot项目基于java的教学辅助平台

采用技术 SpringBoot项目基于java的教学辅助平台的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 学生信息管理 教师信息管理 课程信息管理 科目分类管…

【面试经典 150 | 链表】K 个一组翻转链表

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;迭代 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容进行回顾…

xxl-job使用自动注册节点,ip不对,如何解决????

很明显这时我们本机的ip和我们xxl-job自动注册的ip是不一致的&#xff0c;此时该如何处理呢&#xff1f;&#xff1f;&#xff1f;&#xff1f; 方法一&#xff1a;在配置文件中&#xff0c;将我们的ip固定写好。 ### xxl-job executor server-info xxl.job.executor.ip写你的…

pandas基本用法

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas的数据结构1、一维数组pd.Series1.1 pd.Series&#xff08;data,index,dtype&#xff09;示例1&#xff1a;不定义index示例2&#xff1a;自定义inde…

基于HMM隐马尔可夫模型的金融数据预测算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于HMM隐马尔可夫模型的金融数据预测算法.程序实现HMM模型的训练&#xff0c;使用训练后的模型进行预测。 2.测试软件版本以及运行结果展示 MATLAB2022A版本运…

excel 无法正确处理 1900-03-01 前的日期

问题由来&#xff1a;excel 用公式 TEXT(A1,"yyyy-mm-dd") 转日期时&#xff0c;当A1 的值等于59 的时候&#xff0c;返回值是1900-02-28&#xff1b;当A1 的值等于61 的时候&#xff0c;返回值是1900-03-01&#xff1b;那么当 A1的值为 60 的时候&#xff0c;返回值…

数图智慧零售解决方案,赋能零售行业空间资源价值最大化

数图智慧零售解决方案 赋能零售行业空间资源价值最大 在激烈的市场竞争中&#xff0c;如何更好地提升空间资源价值&#xff0c;提高销售额&#xff0c;成为行业关注的焦点。近日&#xff0c;NIQ发布的《2024年中国饮料行业趋势与展望》称&#xff0c;“在传统零售业态店内&…

第十一章数据仓库和商务智能10分

【数据仓库-后端&#xff0c;商务智能-前端】 基本算法&#xff1a;关联关系&#xff08;牵手-谈恋爱&#xff09;&#xff0c;集群关系&#xff08;杭州人爱吃酸甜口&#xff09;&#xff0c;决策树&#xff0c;线性回归&#xff0c;贝叶斯&#xff0c;神经网络&#xff0c;时…

Adobe AE(After Effects)2015下载地址及安装教程

Adobe After Effects是一款专业级别的视觉效果和动态图形处理软件&#xff0c;由Adobe Systems开发。它被广泛用于电影、电视节目、广告和其他多媒体项目的制作。 After Effects提供了强大的合成和特效功能&#xff0c;可以让用户创建出令人惊艳的动态图形和视觉效果。用户可以…

使用大模型来实现医疗领域的隐私信息保护

大模型隐私主要分为训练阶段、推理阶段以及用户与大模型交互过程中的隐私泄露&#xff0c;目前的研究重点在大模型训练阶段。传统隐私保护技术主要包括联邦学习、差分隐私、同态加密等&#xff0c;这些技术在大模型背景下的应用挑战不断加剧&#xff1a;(1)联邦学习应用于大模型…

ArkTs

一、概述 ArkTs是由TypeScript扩展而来&#xff0c;在继承TypeScript语法的基础上进行了一系列优化&#xff0c;使开发者能够以更简洁、更自然的方式开发应用。 TypeScript语法: 线上网站:https://www.typescriptlang.org/zh/play 二、TS变量 变量声明: 常量声明: const b…

【高端电流检测IC储能产品应用方案】耐压45V侧轨的电流检测芯片FP137 应用于电脑电源,开关电源以及多口快充充电器,户外移动电源,适配器,电池充电器等

近年来&#xff0c;随着电子产品的飞速发展&#xff0c;对电流检测精度和可靠性的要求也越来越高。特别是在电脑电源、开关电源以及多口快充充电器、户外移动电源、适配器、电池充电器等领域&#xff0c;对电流检测技术的需求更是日益增长。 电流检测芯片是一种关键的电子元器…

强化学习(三)基于动态规划 Dynamic Programming 的求解方法

文章目录 1. 动态规划与强化学习的联系2. 利用动态规划求解最优价值函数2.1 案例背景2.2 策略评估&#xff08;预测&#xff09;2.3 策略迭代&#xff08;控制&#xff09; 在前文《强化学习的数学框架&#xff1a;马尔科夫决策过程 MDP》中&#xff0c;我们用马尔可夫过程抽象…

STM32 软件I2C方式读取MT6701磁编码器获取角度例程

STM32 软件I2C方式读取MT6701磁编码器获取角度例程 &#x1f4cd;相关篇《STM32 软件I2C方式读取AS5600磁编码器获取角度例程》&#x1f33f;《Arduino通过I2C驱动MT6701磁编码器并读取角度数据》&#x1f530;MT6701芯片和AS5600从软件读取对比&#xff0c;只是读取的寄存器和…

Adobe AE(After Effects)2024下载地址及安装教程

Adobe After Effects是一款专业级别的视觉效果和动态图形处理软件&#xff0c;由Adobe Systems开发。它被广泛用于电影、电视节目、广告和其他多媒体项目的制作。 After Effects提供了强大的合成和特效功能&#xff0c;可以让用户创建出令人惊艳的动态图形和视觉效果。用户可以…

【OpenGL实验】在python、Qt5、pyOpenGL程序的若干要点

实验效果图&#xff1a; 代码 目录 一、说明二、关于QGLWidget2.1 三个方便的虚函数2.2 析构函数2.3 QGLWidget析构函数 三、关于QGLWidget的三个虚函数分工3.1 initializeGL&#xff1a;数据准备、数据绑定分离3.2 resizeGL&#xff1a;视角改变函数3.3 paintGL&#xff1a;…

苍穹外卖分类管理

分析 需求分析 SQL的写法 1 在mapper中写 2 在xml中写 Mapper public interface CategoryMapper {/*** 插入数据* param category*/AutoFill(OperationType.INSERT)Insert("insert into category(type, name, sort, status, create_time, update_time, create_user, upd…

docker安装并跑通QQ机器人实践(2)-签名服务器bs-qsign搭建

在前文中&#xff0c;我们详尽阐述了QQ机器人的搭建过程及其最终实现的各项功能展示。接下来&#xff0c;我们将转向探讨该项目基于Docker构建服务的具体实践。本篇将以QQ机器人签名服务——qsign为起点&#xff0c;逐步展开论述。 1 获取和运行 xzhouqd/qsign:8.9.63 镜像 1.…

【K8s】:在 Kubernetes 集群中部署 MySQL8.0 高可用集群(1主2从)

【K8s】&#xff1a;在 Kubernetes 集群中部署 MySQL8.0 高可用集群&#xff08;1主2从&#xff09; 一、准备工作二、搭建nfs服务器2.1 安装 NFS 服务器软件包&#xff08;所有节点执行&#xff09;2.2 设置共享目录2.3 启动 NFS 服务器2.4 设置防火墙规则&#xff08;可选&am…