当前位置: 首页 > news >正文

Unity 一个比较适合学习的FSM状态机(汉化和功能简述)

        该轮子由网络资源而来,遵从作者开源意愿,仅作免费学习和分享,不作任何商业行为 ,本文不支持任何交易行为,侵权删!!!

        至于我为什么不将此文章设置为转载,是因为该代码所在的网站早在2020年前就已经关闭了,也就是该资源是祖传的,很有意思吧

 1.总览

请无视枚举中多出来的内容

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/**
基于 Eric Dybsand 在《Game Programming Gems 1》第3.1章中的有限状态机系统作者:Roberto Cezar Bianchini,2010年7月使用方法:1. 在相应的枚举中放置有限状态系统的转换和状态标签。2. 编写继承自 FSMState 的新类,并在每个类中填充(转换-状态)对。这些对表示当 FSMSystem 处于状态 S1 时,如果触发了转换 T,且状态 S1 有从 T 到 S2 的转换,FSMSystem 应该处于状态 S2。请记住,这是一个确定性 FSM。一个转换不能导致两个不同的状态。方法 Reason 用于确定应该触发哪个转换。你可以在其他地方编写触发转换的代码,并将此方法留空,如果你觉得这更适合你的项目。方法 Act 包含 NPC 在此状态下应该执行的动作代码。你可以在其他地方编写动作代码,并将此方法留空,如果你觉得这更适合你的项目。3. 创建 FSMSystem 类的实例,并添加状态。4. 从你的 Update 或 FixedUpdate 方法中调用 Reason 和 Act(或你用于触发转换和使 NPC 在游戏中表现的任何方法)。Unity 引擎的异步转换,如 OnTriggerEnter、SendMessage,也可以使用,只需在事件发生时从你的 FSMSystem 实例中调用 PerformTransition 方法,并传入正确的转换。软件按“原样”提供,不提供任何形式的明示或暗示担保,
包括但不限于适销性、特定用途适用性和非侵权的担保。
在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,
无论是在合同诉讼、侵权行为或其他情况下,
由软件或软件使用或其他交易引起或与之相关。
*//// <summary>
/// 在这个枚举中放置转换的标签。
/// 不要更改第一个标签 NullTransition,因为 FSMSystem 类使用它。
/// </summary>
public enum Transition {NullTransition = 0, // 使用这个转换来表示系统中不存在的转换StartButtonClick,PauseButtonClick
}/// <summary>
/// 在这个枚举中放置状态的标签。
/// 不要更改第一个标签 NullStateID,因为 FSMSystem 类使用它。
/// </summary>
public enum StateID {NullStateID = 0, // 使用这个 ID 来表示系统中不存在的状态Menu,Play,Pause,GameOver
}/// <summary>
/// 这个类代表有限状态系统中的状态。
/// 每个状态都有一个包含(转换-状态)对的字典,
/// 显示当这个状态是当前状态时,如果触发了转换,
/// FSM 应该处于哪个状态。
/// 方法 Reason 用于确定应该触发哪个转换。
/// 方法 Act 包含 NPC 在这个状态下应该执行的动作代码。
/// </summary>
public abstract class FSMState : MonoBehaviour {protected Ctrl ctrl;public Ctrl CTRL {set {ctrl = value;}}protected FSMSystem fsm;public FSMSystem FSM {set {fsm = value;}}protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();protected StateID stateID;public StateID ID {get {return stateID;}}public void AddTransition(Transition trans, StateID id) {// 检查参数是否无效if (trans == Transition.NullTransition) {Debug.LogError("FSMState 错误:NullTransition 不允许作为真实的转换");return;}if (id == StateID.NullStateID) {Debug.LogError("FSMState 错误:NullStateID 不允许作为真实的 ID");return;}// 由于这是一个确定性 FSM,// 检查当前转换是否已经在字典中if (map.ContainsKey(trans)) {Debug.LogError("FSMState 错误:状态 " + stateID.ToString() + " 已经有转换 " + trans.ToString() +"无法分配给另一个状态");return;}map.Add(trans, id);}/// <summary>/// 这个方法从该状态的映射中删除一个转换-状态对。/// 如果转换不在该状态的映射中,将打印错误信息。/// </summary>public void DeleteTransition(Transition trans) {// 检查 NullTransitionif (trans == Transition.NullTransition) {Debug.LogError("FSMState 错误:不允许使用 NullTransition");return;}// 在删除之前检查该对是否在映射中if (map.ContainsKey(trans)) {map.Remove(trans);return;}Debug.LogError("FSMState 错误:传递给 " + stateID.ToString() + " 的转换 " + trans.ToString() +" 不在该状态的转换列表中");}/// <summary>/// 如果这个状态接收到一个转换,这个方法返回 FSM 应该处于的新状态/// </summary>public StateID GetOutputState(Transition trans) {// 检查映射中是否有这个转换if (map.ContainsKey(trans)) {return map[trans];}return StateID.NullStateID;}/// <summary>/// 这个方法用于在进入状态之前设置状态条件。/// 它在 FSMSystem 类将其分配为当前状态之前自动调用。/// </summary>public virtual void DoBeforeEntering() {}/// <summary>/// 这个方法用于在 FSMSystem 切换到另一个状态之前,/// 执行任何必要的操作,如重置变量。/// 它在 FSMSystem 切换到新状态之前自动调用。/// </summary>public virtual void DoBeforeLeaving() {}/// <summary>/// 这个方法决定状态是否应该转换到其列表中的另一个状态。/// NPC 是一个引用,指向由这个类控制的对象。/// </summary>public virtual void Reason() {}/// <summary>/// 这个方法控制 NPC 在游戏世界中的行为。/// NPC 执行的每个动作、移动或交流都应该放在这里。/// NPC 是一个引用,指向由这个类控制的对象。/// </summary>public virtual void Act() {}} // class FSMState/// <summary>
/// FSMSystem 类代表有限状态机类。
/// 它有一个包含 NPC 状态的列表和添加、删除状态以及更改当前状态的方法。
/// </summary>
public class FSMSystem {private List<FSMState> states;// 改变 FSM 状态的唯一方法是执行转换// 不要直接更改 CurrentStateprivate StateID currentStateID;public StateID CurrentStateID {get {return currentStateID;}}private FSMState currentState;public FSMState CurrentState {get {return currentState;}}public FSMSystem() {states = new List<FSMState>();}public void SetCurrentState(FSMState s) {currentState = s;currentStateID = s.ID;s.DoBeforeEntering();}/// <summary>/// 这个方法将新状态放入 FSM 中,/// 如果状态已经在列表中,则打印错误信息。/// 添加的第一个状态也是初始状态。/// </summary>public void AddState(FSMState s, Ctrl ctrl) {// 在删除之前检查空引用if (s == null) {Debug.LogError("FSM 错误:不允许空引用");}s.FSM = this;s.CTRL = ctrl;// 插入的第一个状态也是初始状态,// 模拟开始时机器所处的状态if (states.Count == 0) {states.Add(s);return;}// 如果状态不在列表中,则将其添加到列表中foreach (FSMState state in states) {if (state.ID == s.ID) {Debug.LogError("FSM 错误:无法添加状态 " + s.ID.ToString() +" 因为状态已经被添加");return;}}states.Add(s);}/// <summary>/// 如果状态存在,这个方法从 FSM 列表中删除一个状态,/// 如果状态不在列表中,则打印错误信息。/// </summary>public void DeleteState(StateID id) {// 在删除之前检查 NullStateif (id == StateID.NullStateID) {Debug.LogError("FSM 错误:不允许使用 NullStateID 作为真实状态");return;}// 搜索列表并删除其中的状态foreach (FSMState state in states) {if (state.ID == id) {states.Remove(state);return;}}Debug.LogError("FSM 错误:无法删除状态 " + id.ToString() +"。它不在状态列表中");}/// <summary>/// 这个方法尝试根据当前状态和传递的转换来改变 FSM 所处的状态。/// 如果当前状态没有传递的转换的目标状态,则打印错误信息。/// </summary>public void PerformTransition(Transition trans) {// 在更改当前状态之前检查 NullTransitionif (trans == Transition.NullTransition) {Debug.LogError("FSM 错误:不允许使用 NullTransition 作为真实转换");return;}// 检查当前状态是否有传递的转换StateID id = currentState.GetOutputState(trans);if (id == StateID.NullStateID) {Debug.LogError("FSM 错误:状态 " + currentStateID.ToString() + " 没有目标状态 " +" 对于转换 " + trans.ToString());return;}// 更新 currentStateID 和 currentStatecurrentStateID = id;foreach (FSMState state in states) {if (state.ID == currentStateID) {// 在设置新状态之前进行状态的后处理currentState.DoBeforeLeaving();currentState = state;// 在状态可以推理或行动之前重置其到所需条件currentState.DoBeforeEntering();break;}}} // PerformTransition()} //class FSMSystem

2.功能分述 

        功能:定义了状态转换的标签。NullTransition 用于表示不存在的转换。

public enum Transition
{NullTransition = 0, // 使用这个转换来表示系统中不存在的转换StartButtonClick,PauseButtonClick
}

        功能:定义了状态的标签。NullStateID 用于表示不存在的状态。

public enum StateID
{NullStateID = 0, // 使用这个 ID 来表示系统中不存在的状态Menu,Play,Pause,GameOver
}

        功能

  • AddTransition:添加状态转换。
  • DeleteTransition:删除状态转换。
  • GetOutputState:获取转换后的状态。
  • DoBeforeEntering:进入状态前的设置。
  • DoBeforeLeaving:离开状态前的设置。
  • Reason:决定是否进行状态转换。
  • Act:控制 NPC 在当前状态下的行为。
  • public abstract class FSMState : MonoBehaviour
    {protected Ctrl ctrl;public Ctrl CTRL { set { ctrl = value; } }protected FSMSystem fsm;public FSMSystem FSM { set { fsm = value; } }protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();protected StateID stateID;public StateID ID { get { return stateID; } }public void AddTransition(Transition trans, StateID id){// 检查参数是否无效if (trans == Transition.NullTransition){Debug.LogError("FSMState 错误:NullTransition 不允许作为真实的转换");return;}if (id == StateID.NullStateID){Debug.LogError("FSMState 错误:NullStateID 不允许作为真实的 ID");return;}// 检查当前转换是否已经在字典中if (map.ContainsKey(trans)){Debug.LogError("FSMState 错误:状态 " + stateID.ToString() + " 已经有转换 " + trans.ToString() +"无法分配给另一个状态");return;}map.Add(trans, id);}public void DeleteTransition(Transition trans){// 检查 NullTransitionif (trans == Transition.NullTransition){Debug.LogError("FSMState 错误:不允许使用 NullTransition");return;}// 在删除之前检查该对是否在映射中if (map.ContainsKey(trans)){map.Remove(trans);return;}Debug.LogError("FSMState 错误:传递给 " + stateID.ToString() + " 的转换 " + trans.ToString() +" 不在该状态的转换列表中");}public StateID GetOutputState(Transition trans){// 检查映射中是否有这个转换if (map.ContainsKey(trans)){return map[trans];}return StateID.NullStateID;}public virtual void DoBeforeEntering() { }public virtual void DoBeforeLeaving() { }public virtual void Reason() { }public virtual void Act() { }
    }
    

        功能

  • AddState:添加新状态到 FSM。
  • DeleteState:从 FSM 中删除状态。
  • SetCurrentState:设置当前状态。
  • PerformTransition:执行状态转换。
  • public class FSMSystem
    {private List<FSMState> states;// 改变 FSM 状态的唯一方法是执行转换// 不要直接更改 CurrentStateprivate StateID currentStateID;public StateID CurrentStateID { get { return currentStateID; } }private FSMState currentState;public FSMState CurrentState { get { return currentState; } }public FSMSystem(){states = new List<FSMState>();}public void SetCurrentState(FSMState s){currentState = s;currentStateID = s.ID;s.DoBeforeEntering();}public void AddState(FSMState s, Ctrl ctrl){// 在删除之前检查空引用if (s == null){Debug.LogError("FSM 错误:不允许空引用");}s.FSM = this;s.CTRL = ctrl;// 插入的第一个状态也是初始状态,// 模拟开始时机器所处的状态if (states.Count == 0){states.Add(s);return;}// 如果状态不在列表中,则将其添加到列表中foreach (FSMState state in states){if (state.ID == s.ID){Debug.LogError("FSM 错误:无法添加状态 " + s.ID.ToString() +" 因为状态已经被添加");return;}}states.Add(s);}public void DeleteState(StateID id){// 在删除之前检查 NullStateif (id == StateID.NullStateID){Debug.LogError("FSM 错误:不允许使用 NullStateID 作为真实状态");return;}// 搜索列表并删除其中的状态foreach (FSMState state in states){if (state.ID == id){states.Remove(state);return;}}Debug.LogError("FSM 错误:无法删除状态 " + id.ToString() +"。它不在状态列表中");}public void PerformTransition(Transition trans){// 在更改当前状态之前检查 NullTransitionif (trans == Transition.NullTransition){Debug.LogError("FSM 错误:不允许使用 NullTransition 作为真实转换");return;}// 检查当前状态是否有传递的转换StateID id = currentState.GetOutputState(trans);if (id == StateID.NullStateID){Debug.LogError("FSM 错误:状态 " + currentStateID.ToString() + " 没有目标状态 " +" 对于转换 " + trans.ToString());return;}// 更新 currentStateID 和 currentStatecurrentStateID = id;foreach (FSMState state in states){if (state.ID == currentStateID){// 在设置新状态之前进行状态的后处理currentState.DoBeforeLeaving();currentState = state;// 在状态可以推理或行动之前重置其到所需条件currentState.DoBeforeEntering();break;}}} // PerformTransition()} //class FSMSystem
    

 

 

 

相关文章:

Unity 一个比较适合学习的FSM状态机(汉化和功能简述)

该轮子由网络资源而来&#xff0c;遵从作者开源意愿&#xff0c;仅作免费学习和分享&#xff0c;不作任何商业行为 &#xff0c;本文不支持任何交易行为&#xff0c;侵权删&#xff01;&#xff01;&#xff01; 至于我为什么不将此文章设置为转载&#xff0c;是因为该代码所在…...

25、Wpf之App资源应用

开发平台&#xff1a;Win10 64位 开发环境&#xff1a;VS2022(64位) Preview .NET Framework&#xff1a;.NET 6 文章目录 一 Resources1.1 Application中定义资源1.2 样式&#xff08;Styles&#xff09;1.3 模板&#xff08;Templates&#xff09;1.4 数据转换器&#xff08;…...

【深度好文】反模式:10种滥用设计模式案例分析

Hello&#xff0c;大家好&#xff0c;我是V哥。很多文章都在介绍设计模式怎么用&#xff0c;讲解设计模式的原理等等&#xff0c;设计模式的思想是编程中的精髓&#xff0c;用好了可以让代码结构利于维护和扩展&#xff0c;同时代码风格也更加优雅&#xff0c;V 哥也写过这样一…...

OkHttp Interceptor日志上报

最近为了做一些网络上的优化&#xff0c;所以就得提前埋点&#xff0c;为后续网络优化提供数据支持。 主要是对发起请求埋点&#xff0c;请求错误埋点&#xff0c;客户端请求耗时埋点。 事件上报到阿里云&#xff0c;接入的是阿里的应用实时监控服务。 网络请求使用的是OhHttp…...

高性能反向代理--HAProxy

文章目录 Web架构负载均衡介绍为什么使用负载均衡负载均衡类型 HAProxy简介应用场景HAProxy是什么HAProxy功能 脚本安装HAProxy基础配置global多进程和线程HAProxy日志配置项 Proxies配置-listen-frontend-backendserver配置 frontendbackend配置实例子配置文件 HAProxy调度算法…...

数据结构应用实例(四)——最小生成树

Content&#xff1a; 一、问题描述二、算法思想三、代码实现四、两种算法的比较五、小结 一、问题描述 利用 prim 算法和 kruskal 算法实现最小生成树问题&#xff1b; 二、算法思想 首先判断图是否连通&#xff0c;只有在连通的情况下才进行最小树的生成&#xff1b; 三、代…...

为OneAPI配置MySQL数据库及设置开机启动

OneAPI启动时&#xff0c;如果发现没有数据库他会在项目根目录自动创建SqlLit&#xff0c;为提高OneAPI的性能及管理&#xff0c;这里给出一个使用MySQL数据库的案例&#xff0c;同时本文介绍如何在源码部署的情况下&#xff0c;设置OneAPI的开机自动启动。 OneAPI的源代码安装…...

完整的k8s搭建服务器流程

一、准备 1、禁用selinux #临时禁用 setenforce 0 #永久禁用 sed -i s/enforcing/disabled/ /etc/selinux/config #检查selinux是否已禁用 sestatus 2、禁用交换分区 #命令行临时禁用 swapoff -a #永久禁用 vim /etc/fstab 注释掉有swap字样的那行&#xff0c;重启 3、允许…...

【Petri网导论学习笔记】Petri网导论入门学习(一)

Petri 网导论 如需学习转载请注明原作者并附本帖链接&#xff01;&#xff01;&#xff01; 如需学习转载请注明原作者并附本帖链接&#xff01;&#xff01;&#xff01; 如需学习转载请注明原作者并附本帖链接&#xff01;&#xff01;&#xff01; 发现网上关于Petri网的学习…...

Zabbix监控自动化

监控在运维工作中所占的比例为 30%左右&#xff0c;监控做得好&#xff0c;会省很多事&#xff0c;让工作能有序地进行。理想的监控应该是自动化的&#xff0c;只需要配置规则&#xff0c;即可自动完成所有的事情&#xff0c;比如主机的自动添加和注册、模板的自动添加、分组的…...

pytorch pyro 贝叶斯神经网络 bnn beyesean neure network svi ​定制SVI目标和培训循环,变更推理

定制SVI目标和培训循环 Pyro支持各种基于优化的贝叶斯推理方法&#xff0c;包括Trace_ELBO作为SVI(随机变分推理)的基本实现。参见文件&#xff08;documents的简写&#xff09;有关各种SVI实现和SVI教程的更多信息I, 二&#xff0c;以及罗马数字3了解SVI的背景。 在本教程中…...

Openeuler22 部署 RackTables0.22.0

目录 0、前言 一、部署lamp环境&#xff0c;lamp环境测试 1、部署Apache&#xff0c;apache环境测试 2、部署php、mysql&#xff0c;php环境测试 二、放文件 三、配置mysql 四、安装racktables 第一步、点击proceed继续 第二步、点击proceed 第三步、根据提示进行操作…...

从传统到智能:高标准农田灌区信息化助力农业现代化

从传统农业的粗放式管理&#xff0c;到如今智能化、精准化的现代农业转型&#xff0c;高标准农田灌区信息化建设无疑是推动这一历史进程的关键力量。它不仅标志着农业生产方式的根本性变革&#xff0c;还深刻影响着农业资源的高效利用与可持续发展策略&#xff0c;为实现农业现…...

堆排序-建堆,增删替换

我们 之前写过根据 堆排序的优先级队列&#xff0c;但是如果我们想要建立一个堆怎么办呢&#xff1f; 如何实现上浮 下潜 具体看这篇文章 堆排序-优先级队列-CSDN博客 建堆 我们有两种方法建立一个堆 1.我们基于add方法建立一个堆&#xff0c;一次次的add&#xff0c;然后对…...

使用AI写WebSocket知识是一种怎么样的体验?

一、WebSocket基础知识 1. WebSocket概念 1.1 为什么会出现WebSocket 一般的Http请求我们只有主动去请求接口&#xff0c;才能获取到服务器的数据。例如前后端分离的开发场景&#xff0c;自嘲为切图仔的前端大佬找你要一个配置信息的接口&#xff0c;我们后端开发三下两下开…...

若依系统(Security)增加微信小程序登录(自定义登录)

若依系统(分离版后端)自带的账号验证是基于 UsernamePasswordAuthenticationToken authenticationToken new UsernamePasswordAuthenticationToken(username, password); 验证&#xff0c;然后在系统中controller或service类中 SecurityUtils 工具类中直接可获取用户或用户…...

道可云人工智能元宇宙每日资讯|2024互联网岳麓峰会在长沙召开

道可云元宇宙每日简报&#xff08;2024年9月10日&#xff09;讯&#xff0c;今日元宇宙新鲜事有&#xff1a; 2024互联网岳麓峰会在长沙召开 9月9日&#xff0c;2024互联网岳麓峰会在长沙召开&#xff0c;湖南省副省长曹志强在峰会表示&#xff0c;今年上半年湖南省人工智能产…...

MySQL JDBC URL各参数详解

jdbc:mysql://localhost:3306/test?userroot&password123456&useUnicodetrue&characterEncodinggbk &autoReconnecttrue&failOverReadOnlyfalse&serverTimezoneUTC&drivercom.mysql.cj.jdbc.Driver 参数名称参数说明缺省值user指定用于连接数据库…...

celery control.shutdown

Celery 提供了 control 模块&#xff0c;允许你发送控制命令给正在运行的 worker。其中 shutdown 命令可以用来关闭一个或多个 worker。下面是如何使用 control.shutdown 来关闭 worker 的详细说明。 使用 control.shutdown 1. 导入必要的模块 首先&#xff0c;你需要导入 C…...

数据库设计与软件工程阶段的对应关系

数据库设计的很多阶段确实可以与软件工程的各阶段对应起来&#xff0c;这体现了数据库设计作为软件工程中一个核心组成部分的紧密关联性。 1. 需求分析阶段 数据库设计&#xff1a;需求分析是数据库设计的初始阶段&#xff0c;主要任务是收集和分析用户的需求&#xff0c;包括…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...

C#学习第29天:表达式树(Expression Trees)

目录 什么是表达式树&#xff1f; 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持&#xff1a; 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...