Java手写简单Merkle树

news2025/2/1 15:33:51

 Java手写Merkle树代码

package com.blockchain.qgy.component;

import com.blockchain.qgy.model.MerkleTreeNode;
import com.blockchain.qgy.util.SHAUtil;

import java.util.*;

public class MerkleTree<T> {
    //merkle树
    private List<MerkleTreeNode<T>> list;
    //根节点
    private MerkleTreeNode<T> root;

    public MerkleTree(List<T> nodes){
        createMerkleTree(nodes);
    }

    /**
     * function 初始化merkle树
     * @param nodes: 数据集合
     */
    private void createMerkleTree(List<T> nodes) {
        //判断入参
        if (Objects.isNull(nodes) || nodes.size() == 0) return;

        list = new ArrayList<>();

        //创建叶子节点
        List<MerkleTreeNode<T>> leafList = createLeafList(nodes);
        list.addAll(leafList);

        //创建父级节点
        List<MerkleTreeNode<T>> parents = new ArrayList<>(leafList);
        //循环创建直到找到根节点
        do {
            List<MerkleTreeNode<T>> temp = new ArrayList<>(parents);
            temp = createParentList(temp);
            parents = temp;
            list.addAll(parents);
        }while (parents.size() > 1);

        root = parents.get(0);
    }

    /**
     * function 初始化父亲节点
     * @param leafList:叶子节点
     * @return 父节点
     */
    private List<MerkleTreeNode<T>> createParentList(List<MerkleTreeNode<T>> leafList) {
        //判断入参
        if (Objects.isNull(leafList) || leafList.size() == 0) return new ArrayList<>();

        List<MerkleTreeNode<T>> parents = new ArrayList<>();

        int length = leafList.size();
        for(int i = 0;i < length - 1; i += 2){
            MerkleTreeNode<T> parent = createParentNode(leafList.get(i),leafList.get(i+1));
            parents.add(parent);
        }

        //当节点数为奇数时,单独进行处理
        if ((length & 1) == 1) {
            MerkleTreeNode<T> parent = createParentNode(leafList.get(length - 1),null);
            parents.add(parent);
        }

        return parents;
    }

    /**
     * function 生成一个父节点
     * @param left:左节点
     * @param right:右节点
     * @return 父节点
     */
    private MerkleTreeNode<T> createParentNode(MerkleTreeNode<T> left, MerkleTreeNode<T> right) {
        MerkleTreeNode<T> parent = new MerkleTreeNode<>();

        parent.setLeft(left);
        parent.setRight(right);

        String hash = left.getHash();
        if(!Objects.isNull(parent.getRight())) {
            hash = SHAUtil.sha256BasedHutool(hash.concat(parent.getRight().getHash()));
        }
        parent.setHash(hash);
        parent.setName("无人签名");
        parent.setData((T) new Object());
        return parent;
    }

    /**
     * function 初始化叶子节点
     * @param nodes:数据集合
     * @return merkle的叶子节点
     */
    private List<MerkleTreeNode<T>> createLeafList(List<T> nodes) {
        //判断入参
        if (Objects.isNull(nodes) || nodes.size() == 0) return new ArrayList<>();

        List<MerkleTreeNode<T>> leafList = new ArrayList<>();

        for(T curr : nodes) {
            MerkleTreeNode<T> node = new MerkleTreeNode<>(curr);
            leafList.add(node);
        }

        return leafList;
    }

    public void printfTree() {
        Collections.reverse(list);
        MerkleTreeNode<T> root = list.get(0);
        Queue<MerkleTreeNode<T>> queue = new LinkedList<MerkleTreeNode<T>>(){
  
  {
            offer(root);
        }};
        printfTree(queue,1);
    }

    public void printfTree(Queue<MerkleTreeNode<T>> queue,Integer floor) {
        Queue<MerkleTreeNode<T>> currQueue = new LinkedList<>();
        System.out.println("第"+floor+"层--------------------------------------------------------------------------------------------------------------------------");
        while (!queue.isEmpty()) {
            MerkleTreeNode<T> poll = queue.poll();
            System.out.println(poll.toString());
            if(!Objects.isNull(poll.getLeft())) currQueue.offer(poll.getLeft());
            if(!Objects.isNull(poll.getRight())) currQueue.offer(poll.getRight());
        }
        if (!currQueue.isEmpty()) printfTree(currQueue,floor+1);
    }

    public List<MerkleTreeNode<T>> getList() {
        return list;
    }

    public MerkleTreeNode<T> getRoot() {
        return root;
    }

    public void setList(List<MerkleTreeNode<T>> list) {
        this.list = list;
    }

    public void setRoot(MerkleTreeNode<T> root) {
        this.root = root;
    }


}

package com.blockchain.qgy.model;

import com.blockchain.qgy.util.SHAUtil;

public class MerkleTreeNode<T> {
    //左节点
    private MerkleTreeNode<T> left;
    //右节点
    private MerkleTreeNode<T> right;
    //区块数据
    private T data;
    //节点hash值
    private String hash;
    //数字签名
    private String name;

    public MerkleTreeNode() {

    }

    public MerkleTreeNode(T data) {
        this.data = data;
        this.hash = SHAUtil.sha256BasedHutool(data.toString());
        this.name = "无人签名";
    }

    public MerkleTreeNode(T data, String name){
        this.data = data;
        this.hash = SHAUtil.sha256BasedHutool(data.toString());
        this.name = name;
    }

    public MerkleTreeNode<T> getLeft() {
        return left;
    }

    public void setLeft(MerkleTreeNode<T> left) {
        this.left = left;
    }

    public MerkleTreeNode<T> getRight() {
        return right;
    }

    public void setRight(MerkleTreeNode<T> right) {
        this.right = right;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public String getHash() {
        return hash;
    }

    public void setHash(String hash) {
        this.hash = hash;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return  "MerkleTreeNode:\n" +
                "name:" + name + ";\n" +
                "data:" + data + ";\n" +
                "------------\n";
    }
}

 

注意:这里用了SHAUtil工具类,该部分代码链接如下:

SHAUtil代码

测试代码

package com.blockchain.qgy.test;

import com.blockchain.qgy.component.MerkleTree;
import com.blockchain.qgy.model.MerkleTreeNode;
import org.testng.annotations.Test;

import java.util.Arrays;
import java.util.List;

public class MerkleTreeTest {

    @Test
    public void Test(){
        List<String> contents = Arrays.asList("星","极","天","下","第","一");
        MerkleTree<String> stringMerkleTree = new MerkleTree<>(contents);
        stringMerkleTree.printfTree();
        MerkleTreeNode<String> root = stringMerkleTree.getRoot();
        System.out.println("root:"+root);
        System.out.println("hash:"+root.getHash());
    }
}

结果:

"C:\Program Files\Java\jdk1.8.0_261\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:D:\idea\IntelliJ IDEA 2020.2.1\lib\idea_rt.jar=55223:D:\idea\IntelliJ IDEA 2020.2.1\bin" -Dfile.encoding=UTF-8 -classpath "D:\idea\IntelliJ IDEA 2020.2.1\lib\idea_rt.jar;D:\idea\IntelliJ IDEA 2020.2.1\plugins\testng\lib\testng-rt.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\rt.jar;D:\项目\区块链\target\classes;C:\Users\86153\Desktop\java架包\org\testng\testng\6.8.7\testng-6.8.7.jar;C:\Users\86153\Desktop\java架包\junit\junit\4.10\junit-4.10.jar;C:\Users\86153\Desktop\java架包\org\hamcrest\hamcrest-core\1.1\hamcrest-core-1.1.jar;C:\Users\86153\Desktop\java架包\org\beanshell\bsh\2.0b4\bsh-2.0b4.jar;C:\Users\86153\Desktop\java架包\com\beust\jcommander\1.27\jcommander-1.27.jar;C:\Users\86153\Desktop\java架包\org\yaml\snakeyaml\1.12\snakeyaml-1.12.jar;C:\Users\86153\Desktop\java架包\org\mockito\mockito-all\1.9.5\mockito-all-1.9.5.jar;C:\Users\86153\Desktop\java架包\com\xiaoleilu\hutool-all\3.0.9\hutool-all-3.0.9.jar;C:\Users\86153\Desktop\java架包\com\google\crypto\tink\tink\1.2.0\tink-1.2.0.jar;C:\Users\86153\Desktop\java架包\com\amazonaws\aws-java-sdk-core\1.11.166\aws-java-sdk-core-1.11.166.jar;C:\Users\86153\Desktop\java架包\software\amazon\ion\ion-java\1.0.2\ion-java-1.0.2.jar;C:\Users\86153\Desktop\java架包\com\fasterxml\jackson\dataformat\jackson-dataformat-cbor\2.6.7\jackson-dataformat-cbor-2.6.7.jar;C:\Users\86153\Desktop\java架包\joda-time\joda-time\2.8.1\joda-time-2.8.1.jar;C:\Users\86153\Desktop\java架包\com\amazonaws\aws-java-sdk-kms\1.11.166\aws-java-sdk-kms-1.11.166.jar;C:\Users\86153\Desktop\java架包\com\amazonaws\jmespath-java\1.11.166\jmespath-java-1.11.166.jar;C:\Users\86153\Desktop\java架包\com\fasterxml\jackson\core\jackson-databind\2.6.7.1\jackson-databind-2.6.7.1.jar;C:\Users\86153\Desktop\java架包\com\fasterxml\jackson\core\jackson-annotations\2.6.0\jackson-annotations-2.6.0.jar;C:\Users\86153\Desktop\java架包\com\google\api-client\google-api-client\1.22.0\google-api-client-1.22.0.jar;C:\Users\86153\Desktop\java架包\com\google\oauth-client\google-oauth-client\1.22.0\google-oauth-client-1.22.0.jar;C:\Users\86153\Desktop\java架包\com\google\http-client\google-http-client\1.22.0\google-http-client-1.22.0.jar;C:\Users\86153\Desktop\java架包\org\apache\httpcomponents\httpclient\4.0.1\httpclient-4.0.1.jar;C:\Users\86153\Desktop\java架包\org\apache\httpcomponents\httpcore\4.0.1\httpcore-4.0.1.jar;C:\Users\86153\Desktop\java架包\commons-logging\commons-logging\1.1.1\commons-logging-1.1.1.jar;C:\Users\86153\Desktop\java架包\commons-codec\commons-codec\1.3\commons-codec-1.3.jar;C:\Users\86153\Desktop\java架包\com\google\http-client\google-http-client-jackson2\1.22.0\google-http-client-jackson2-1.22.0.jar;C:\Users\86153\Desktop\java架包\com\fasterxml\jackson\core\jackson-core\2.1.3\jackson-core-2.1.3.jar;C:\Users\86153\Desktop\java架包\com\google\apis\google-api-services-cloudkms\v1-rev9-1.22.0\google-api-services-cloudkms-v1-rev9-1.22.0.jar;C:\Users\86153\Desktop\java架包\com\google\guava\guava\25.0-jre\guava-25.0-jre.jar;C:\Users\86153\Desktop\java架包\com\google\code\findbugs\jsr305\1.3.9\jsr305-1.3.9.jar;C:\Users\86153\Desktop\java架包\org\checkerframework\checker-compat-qual\2.0.0\checker-compat-qual-2.0.0.jar;C:\Users\86153\Desktop\java架包\com\google\errorprone\error_prone_annotations\2.1.3\error_prone_annotations-2.1.3.jar;C:\Users\86153\Desktop\java架包\com\google\j2objc\j2objc-annotations\1.1\j2objc-annotations-1.1.jar;C:\Users\86153\Desktop\java架包\org\codehaus\mojo\animal-sniffer-annotations\1.14\animal-sniffer-annotations-1.14.jar;C:\Users\86153\Desktop\java架包\com\google\auto\service\auto-service\1.0-rc4\auto-service-1.0-rc4.jar;C:\Users\86153\Desktop\java架包\com\google\auto\auto-common\0.8\auto-common-0.8.jar;C:\Users\86153\Desktop\java架包\com\google\protobuf\protobuf-java\3.3.0\protobuf-java-3.3.0.jar;C:\Users\86153\Desktop\java架包\org\json\json\20170516\json-20170516.jar;D:\idea\IntelliJ IDEA 2020.2.1\plugins\testng\lib\jcommander-1.27.jar" com.intellij.rt.testng.RemoteTestNGStarter -usedefaultlisteners false -socket55222 @w@C:\Users\86153\AppData\Local\Temp\idea_working_dirs_testng.tmp -temp C:\Users\86153\AppData\Local\Temp\idea_testng.tmp
[TestNG] Running:
  C:\Users\86153\AppData\Local\JetBrains\IntelliJIdea2020.2\temp-testng-customsuite.xml


第1层------------------------------------------------------------------------------------------------------------------
MerkleTreeNode:
name:无人签名;
data:java.lang.Object@b684286;
------------

第2层------------------------------------------------------------------------------------------------------------------
MerkleTreeNode:
name:无人签名;
data:java.lang.Object@880ec60;
------------

MerkleTreeNode:
name:无人签名;
data:java.lang.Object@3f3afe78;
------------

第3层------------------------------------------------------------------------------------------------------------------
MerkleTreeNode:
name:无人签名;
data:java.lang.Object@7f63425a;
------------

MerkleTreeNode:
name:无人签名;
data:java.lang.Object@36d64342;
------------

MerkleTreeNode:
name:无人签名;
data:java.lang.Object@39ba5a14;
------------

第4层------------------------------------------------------------------------------------------------------------------
MerkleTreeNode:
name:无人签名;
data:星;
------------

MerkleTreeNode:
name:无人签名;
data:极;
------------

MerkleTreeNode:
name:无人签名;
data:天;
------------

MerkleTreeNode:
name:无人签名;
data:下;
------------

MerkleTreeNode:
name:无人签名;
data:第;
------------

MerkleTreeNode:
name:无人签名;
data:一;
------------

root:MerkleTreeNode:
name:无人签名;
data:java.lang.Object@b684286;
------------

hash:4e8da83f3ee3cb2ddb2d5dec5724a0c01bb4f6f48d2f7c3dd46f51158b26b5f4


===============================================
Default Suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================


Process finished with exit code 0
 

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

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

相关文章

DDD - 微服务架构模型_领域驱动设计(DDD)分层架构 vs 整洁架构(洋葱架构) vs 六边形架构(端口-适配器架构)

文章目录 引言1. 概述2. 领域驱动设计&#xff08;DDD&#xff09;分层架构模型2.1 DDD的核心概念2.2 DDD架构分层解析 3. 整洁架构&#xff1a;洋葱架构与依赖倒置3.1 整洁架构的核心思想3.2 整洁架构的层次结构 4. 六边形架构&#xff1a;解耦核心业务与外部系统4.1 六边形架…

数据结构与算法之二叉树: LeetCode LCP 10. 二叉树任务调度 (Ts版)

二叉树任务调度 https://leetcode.cn/problems/er-cha-shu-ren-wu-diao-du/description/ 描述 任务调度优化是计算机性能优化的关键任务之一。在任务众多时&#xff0c;不同的调度策略可能会得到不同的总体执行时间&#xff0c;因此寻求一个最优的调度方案是非常有必要的 通…

玩转大语言模型——配置图数据库Neo4j(含apoc插件)并导入GraphRAG生成的知识图谱

系列文章目录 玩转大语言模型——使用langchain和Ollama本地部署大语言模型 玩转大语言模型——ollama导入huggingface下载的模型 玩转大语言模型——langchain调用ollama视觉多模态语言模型 玩转大语言模型——使用GraphRAGOllama构建知识图谱 玩转大语言模型——完美解决Gra…

计算机毕业设计Python+CNN卷积神经网络考研院校推荐系统 考研分数线预测 考研推荐系统 考研爬虫 考研大数据 Hadoop 大数据毕设 机器学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

OpenCV:闭运算

目录 1. 简述 2. 用膨胀和腐蚀实现闭运算 2.1 代码示例 2.2 运行结果 3. 闭运算接口 3.1 参数详解 3.2 代码示例 3.3 运行结果 4. 闭运算的应用场景 5. 注意事项 相关阅读 OpenCV&#xff1a;图像的腐蚀与膨胀-CSDN博客 OpenCV&#xff1a;开运算-CSDN博客 1. 简述…

智云-一个抓取web流量的轻量级蜜罐-k8s快速搭建教程

智云-一个抓取web流量的轻量级蜜罐-k8s快速搭建教程 github地址 https://github.com/xiaoxiaoranxxx/POT-ZHIYUN k8s搭建教程 首先下载代码文件 git clone https://github.com/xiaoxiaoranxxx/POT-ZHIYUN.git cd POT-ZHIYUN编译镜像 代码相关文件在github https://github.com/x…

万物皆有联系:驼鸟和布什

布什&#xff1f;一块布十块钱吗&#xff1f;不是&#xff0c;大家都知道&#xff0c;美国有两个总统&#xff0c;叫老布什和小布什&#xff0c;因为两个布什总统&#xff08;父子俩&#xff09;&#xff0c;大家就这么叫来着&#xff0c;目的是为了好区分。 布什总统的布什&a…

< OS 有关 > 阿里云:轻量应用服务器 的使用 :轻量化 阿里云 vpm 主机

原因&#xff1a; &#xff1c; OS 有关 &#xff1e; 阿里云&#xff1a;轻量应用服务器 的使用 &#xff1a;从新开始 配置 SSH 主机名 DNS Tailscale 更新OS安装包 最主要是 清除阿里云客户端这个性能杀手-CSDN博客 防止 I/O 祸害系统 操作&#xff1a; 查看进程&#x…

SOME/IP--协议英文原文讲解3

前言 SOME/IP协议越来越多的用于汽车电子行业中&#xff0c;关于协议详细完全的中文资料却没有&#xff0c;所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块&#xff1a; 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 Note: Thi…

unity学习24:场景scene相关生成,加载,卸载,加载进度,异步加载场景等

目录 1 场景数量 SceneManager.sceneCount 2 直接代码生成新场景 SceneManager.CreateScene 3 场景的加载 3.1 用代码加载场景&#xff0c;仍然build setting里先加入配置 3.2 卸载场景 SceneManager.UnloadSceneAsync(); 3.3 同步加载场景 SceneManager.LoadScene 3.3.…

四.4 Redis 五大数据类型/结构的详细说明/详细使用( zset 有序集合数据类型详解和使用)

四.4 Redis 五大数据类型/结构的详细说明/详细使用&#xff08; zset 有序集合数据类型详解和使用&#xff09; 文章目录 四.4 Redis 五大数据类型/结构的详细说明/详细使用&#xff08; zset 有序集合数据类型详解和使用&#xff09;1. 有序集合 Zset(sorted set)2. zset 有序…

S4 HANA税码科目确定(OB40)

本文主要介绍在S4 HANA OP中税码科目确定(OB40)相关设置。具体请参照如下内容&#xff1a; 税码科目确定(OB40) 在以上界面维护“Transaction Key”的记账码。 在以上界面进一步维护“Transaction Key”确定科目的规则。 Chart of Account:用于明确该规则适用于什么科目表。 …

vim的特殊模式-可视化模式

可视化模式&#xff1a;按 v进入可视化模式 选中 y复制 d剪切/删除 可视化块模式: ctrlv 选中 y复制 d剪切/删除 示例&#xff1a; &#xff08;vim可视化模式的进阶使用&#xff1a;vim可视化模式的进阶操作-CSDN博客&#xff09;

UE5制作视差图

双目深度估计开源数据集很多都是用UE制作的&#xff0c;那么我们自己能否通过UE制作自己想要的场景的数据集呢。最近花了点时间研究了一下&#xff0c;分享给需要的小伙伴。 主要使用的是UnrealCV插件&#xff0c;UnrealCV是一个开源项目&#xff0c;旨在帮助计算机视觉研究人…

记忆化搜索(5题)

是什么&#xff1f; 是一个带备忘录的递归 如何实现记忆化搜索 1.添加一个备忘录&#xff08;建立一个可变参数和返回值的映射关系&#xff09; 2.递归每次返回的时候把结果放到备忘录里 3.在每次进入递归的时候往备忘录里面看看。 目录 1.斐波那契数列 2.不同路径 3.最…

【游戏设计原理】96 - 成就感

成就感是玩家体验的核心&#xff0c;它来自完成一件让自己满意的任务&#xff0c;而这种任务通常需要一定的努力和挑战。游戏设计师的目标是通过合理设计任务&#xff0c;不断为玩家提供成就感&#xff0c;保持他们的参与热情。 ARCS行为模式&#xff08;注意力、关联性、自信…

【设计测试用例自动化测试性能测试 实战篇】

&#x1f308;个人主页&#xff1a;努力学编程’ ⛅个人推荐&#xff1a; c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构&#xff0c;刷题刻不容缓&#xff1a;点击一起刷题 &#x1f319;心灵鸡汤&#xff1a;总有人要赢&#xff0c;为什么不能是我呢 设计测试用例…

20-30 五子棋游戏

20-分析五子棋的实现思路_哔哩哔哩_bilibili20-分析五子棋的实现思路是一次性学会 Canvas 动画绘图&#xff08;核心精讲50个案例&#xff09;2023最新教程的第21集视频&#xff0c;该合集共计53集&#xff0c;视频收藏或关注UP主&#xff0c;及时了解更多相关视频内容。https:…

受击反馈HitReact、死亡效果Death Dissolve、Floating伤害值Text(末尾附 客户端RPC )

受击反馈HitReact 设置角色受击标签 (GameplayTag基本了解待补充) 角色监听标签并设置移动速度 创建一个受击技能&#xff0c;并应用GE 实现设置角色的受击蒙太奇动画 实现角色受击时播放蒙太奇动画&#xff0c;为了保证通用性&#xff0c;将其设置为一个函数&#xff0c;并…

STM32 LED呼吸灯

接线图&#xff1a; 这里将正极接到PA0引脚上&#xff0c;负极接到GND&#xff0c;这样就高电平点亮LED&#xff0c;低电平熄灭。 占空比越大&#xff0c;LED越亮&#xff0c;占空比越小&#xff0c;LED越暗 PWM初始化配置 输出比较函数介绍&#xff1a; 用这四个函数配置输…