游戏开发实战(二):Python复刻「崩坏星穹铁道」嗷呜嗷呜事务所---源码级解析该小游戏背后的算法与设计模式【纯原创】

news2025/5/25 16:50:47

文章目录

  • 奇美拉和队列
    • 奇美拉被动技能
    • 多对多观察者关系实现
      • 自定义元类
      • 奇美拉基类
    • 管理奇美拉的队列
      • 奇美拉队列类
      • 心得体会
      • 扩展
    • 规则定义
      • 工作相关
      • 奇美拉相关
    • 奇美拉属性

在本篇博文,我将介绍本项目的整体框架,以及“编码规则”,这些规则保证了本项目的结果和游戏中的实际结果的一致性。
关于游戏规则和奇美拉档案见:
游戏开发实战(一):Python复刻「崩坏星穹铁道」嗷呜嗷呜事务所—源码级解析该小游戏背后的算法与设计模式【纯原创】-CSDN博客‘
后续见:
游戏开发实战(三):Python复刻「崩坏星穹铁道」嗷呜嗷呜事务所—源码级解析该小游戏背后的算法与设计模式【纯原创】-CSDN博客
项目githu地址 https://github.com/Hanachirusat/Chimeras

奇美拉和队列

奇美拉被动技能

奇美拉的技能可以抽象为一种形式:满足条件,触发技能。因此我们可以非常自然的采用观察者模式来实现被动技能方法的自动调用。奇美拉行动后,如果某个条件得到满足,则通知该奇美拉的所有观察者。由于每个奇美拉行动后都有可能使得某个可以触发其他奇美拉被动技能的条件得到满足,因此每个奇美拉是subject,也是observer,这是一个多对多的观察关系。

通过对奇美拉的技能触发条件进行分析,我们可以把技能分成两类:自身触发和队友触发。自身触发条件中包含生命值降低这种属性(变化)触发,也包含同伴工作或追加工作这种动作触发,此外还有登场技能和回合技。队友触发条件同理。因此从代码实现层面,技能触发可以分为属性触发和动作触发。

属性触发很简单,如果奇美拉的属性发生了变化,则同时他的所有观察者,由观察者判断该属性的变化是否会触发自身的技能。而动作触发反映在代码层面可能是奇美拉执行完某个方法后,通知他所有的观察者。人都是喜欢偷懒的,那么有没有把所有触发条件统一起来的方法呢?

答案显而易见,我们可以把动作触发转变为属性触发,例如同伴工作时触发的技能,我们可以对奇美拉增加一个属性:工作次数,当奇美拉工作后,该工作次数+1。这样就可以把工作触发(动作触发)转变为属性触发。同时我们把工作逻辑剥离出来(后续将解释为什么),把每个奇美拉抽象为一个只有被动技能方法(用eval表示)的类(最终实现版本还是有其他方法的,在后面我们将一一介绍why,what以及how),并且该被动技能是自动触发的。

最后,我们继续简化,不同奇美拉的技能触发条件不同,这是不是意味着观察者模式的实现很复杂?实则不然,我们可以让奇美拉监控所有的属性,然后在eval方法中判断变化的属性是否符合奇美拉技能触发的条件。

多对多观察者关系实现

基于上一小结的介绍,在本小节,我们将详细描述如何利用元类来实现多对多的观察者关系。

自定义元类

由于我们把所有的触发条件都转换为了属性触发,那么当奇美拉的任意属性(可能触发其他奇美拉被动的属性)发生变化时,都应该通知观察该奇美拉的观察者。换句话说,我们需要控制每个属性的set过程。自然而然的方法就是property装饰器。我们在元类中遍历所有的属性,处理这些属性get和set时的逻辑。即set时将通知所有的观察者,属性发生了变化。

class ObservableMeta(type):
    """元类用于自动创建属性观察逻辑"""
    def __new__(cls, name, bases, dct):
        # 自动为可能触发其他奇美拉技能的属性创建观察逻辑
        if '__observed_attrs__' in dct:
            attrs = dct['__observed_attrs__']
            for attr in attrs:
                # 为每个被观察属性生成属性描述符
                private_attr = f"_{name}__{attr}"

                #下面的操作相当于对继承该元类的类的私有属性设置@property和@attr.setter(
                def getter(self, name=private_attr):
                    return getattr(self, name)
							
                def setter(self, value, name=private_attr, attr=attr):
                    old_value = getattr(self, name)
                    if old_value != value:
                        setattr(self, name, value)
                        #修改属性的时候,调用类的notify_observers方法
                        # 通知所有的观察者属性发生了变化
                        self.notify_observers(attr, old_value, value)
                dct[attr] = property(getter, setter)
        return super().__new__(cls, name, bases, dct)

在上述代码中,由于我们把奇美拉的属性定义为了私有属性,因此我们需要修改访问私有属性的形式private_attr = f"_{name}__{attr}"其中attr是私有属性,private_attr是可以直接访问私有属性的形式(注:python中没有真正意义上的私有属性,私有属性只不过实际换了个名字存储而已,有兴趣的可以详细了解下)。我们在修改属性值的时候,会记录变化的属性,旧值和新值。然后把这些值传递给观察者。

奇美拉基类

接下来我们实现所有奇美拉的基类,在该基类中我们定义了增加和移除观察者的方法,通知观察者的方法以及析构函数

class ChimerasEntity(metaclass=ObservableMeta):
    """所有可观察对象的基类"""
    __observed_attrs__ = ()  # 需要子类指定要观察的属性

    def __init__(self, name):
        self.name = name
        self._observers = weakref.WeakSet()
        self.queue = None  # 所属队列的弱引用

    def add_observer(self, observer):
        if not isinstance(observer, ChimerasEntity):
            raise TypeError("观察者必须是ObservedEntity类型")
        self._observers.add(observer)

    def remove_observer(self, observer):
        self._observers.discard(observer)


    #该方法在setter的时候被自动调用,get和set是所做的特殊操作由元类来实现
    def notify_observers(self, changed_attr, old_value, new_value):
        for observer in self._observers:
            observer.eval(self, changed_attr, old_value, new_value)

    def eval(self, changed_obj, changed_attr, old_value, new_value):
        #打印检测信息
        print(f"[类名:{self.__class__.__name__},实例名:{self.name}] 检测到变化:"
              f"【{changed_obj.__class__.__name__}{changed_obj.name} 的"
              f"{changed_attr} 属性从 {old_value} 变为 {new_value}")

    def __del__(self):
        # print(f"执行{self.__class__.__name__}的析构函数")
        queue_ = getattr(self, 'queue', None)
        if queue_ is not None:
            # print("从队列中删除")
            queue_.remove_member(self)
            self.queue=None

在上述代码中,我们保存所有观察者的弱引用,这个弱引用是一个集合的形式,无法保证顺序。这可能就是本项目为什么和实际游戏中奇美拉的行动顺序不一致的原因(注意:只是行动顺序不一致,每回合的结果是一致的!后面我们会讲为什么)。基类中的queue属性表示的是奇美拉所属的队列(队列的含义详细请参考上一篇博文:游戏开发实战(一):Python复刻「崩坏星穹铁道」嗷呜嗷呜事务所—源码级解析该小游戏背后的算法与设计模式【纯原创】-CSDN博客,队列的实现我将在后面详细介绍)

在上述代码中eval方法打印的是辅助判断的信息,实际每个奇美拉都会有自己的eval方法(继承重写该方法)。由于后面我们在奇美拉队列类(InteractionQueue)中保存的是所有奇美拉的强引用,因此该析构函数当且仅当该奇美拉已经从队列中移除后才会调用。如果奇美拉队列还保留着当前奇美拉对象的引用,直接del奇美拉对象,python解释器并不会立刻执行该奇美拉对象的析构函数之后销毁该对象。

也就是说,我们最终还是需要手动调用奇美拉队列类的方法,把当前奇美拉对象从队列中移除。我们在析构函数中所做的操作似乎是多余的!是的至少目前为止是多余的,该析构函数的执行只有当该析构函数中的操作都做了之后才会执行。为什么还要这么写?

这是因为我们后续优化的时候需要把queue中的强引用列表和奇美拉基类中的弱引用集合都变为有序弱引用。优化后析构函数中的操作相当于一层保险,如果没有主动调用奇美拉队列中的移除方法,也不会造成内存泄漏(因为奇美拉队列中是弱引用,并不会增加引用计数,del奇美拉对象的时候会正常执行奇美拉对象的析构函数从而从队列中移除该奇美拉)。同时用有序弱引用也可以调整奇美拉行动顺序从而和游戏中的顺序保持一致。

管理奇美拉的队列

奇美拉队列类

我们用一个奇美拉队列来维护当前奇美拉队列,处理不同奇美拉的观察逻辑。当每一个奇美拉入队的时候,根据奇美拉技能触发类型(自身触发还是队友触发),构建这些奇美拉的观察者序列。奇美拉队列中记录了奇美拉在队伍中共的顺序,奇美拉领队和待完成的工作。

  1. 添加成员方法中将根据当前成员的观察模式(也就是技能触发的类型,观察模式为2代表观察所有包括自己,1代表进观察同伴,0代表仅观察自身),对不同的奇美拉对象添加管擦或者。注意处理完当前待添加的奇美拉对象后,还要处理已有奇美拉对象。
  2. 移除队列方法遍历当前所有奇美拉对象,并移除双向观察逻辑。
  3. 清空队列方法,调用移除队列方法清空对象。
  4. 添加和删除领队和添加和删除奇美拉对象类似。
class InteractionQueue:
    """管理相互观察的队列"""
    #1 观察所有 2
    #2 观察除了自己外的所有 1
    #3 只观察自己 0
    def __init__(self):
        self.members_list =[]
        self.leader=None
        self.work=None
        self.episode=0
    def add_member(self, member):
        if not isinstance(member, ChimerasEntity):
            raise TypeError("成员必须是ObservedEntity类型")
        # 建立新成员和已有成员的相互观察关系。
        # 判断新成员是否观察已有成员
        if member.mode>0:
            for existing_member in self.members_list:
                #观察其他所有成员,所有要把当前成员添加到其他所有成员的观察者列表中
                existing_member.add_observer(member)
        #2和0 判断新成员是否观察自身
        if member.mode%2==0:
            # 观察自己和加入队列
            member.add_observer(member)  # 观察自己
		#如果其他的成员的mode>0则表示其他成员要观察新成员,即新成员的观察者列表中要添加已有的成员
        for existing_member in self.members_list:
            if existing_member.mode > 0:
                member.add_observer(existing_member)

        self.members_list.append(member)
        #我们在每个奇美拉对象中记录所在队列的对象,方便后续的技能处理逻辑的实现。
        member.queue = self
        
    def remove_member(self, member):
        """安全移除成员并清理观察关系"""
        if member not in self.members_list:
            return

        # 清理双向观察关系,
        # current_member队列中包含所有成员,即包含member
        for existing_member in self.members_list:
            # 其他成员不再观察被移除者  
            existing_member.remove_observer(member)
            # 被移除者不再观察其他成员
            member.remove_observer(existing_member)
        member.queue = None  # 清除队列引用
        # # 移除自我观察
        # member.remove_observer(member)
        # 从队列中移除
        self.members_list.remove(member)
    def clear(self):
        """清空整个队列"""
        for member in list(self.members_list):
            self.remove_member(member)


        # # 新成员观察所有现有成员
        # for existing_member in self.members:
        #     member.add_observer(existing_member)
    def add_leader(self,leader):
        if not isinstance(leader, ChimerasEntity):
            raise TypeError("成员必须是ObservedEntity类型")

        # 建立新成员和已有成员的相互观察关系。

        # 判断新成员是否观察已有成员
        if leader.mode>0:
            for existing_member in self.members_list:
                #观察其他所有成员,所有要把当前成员添加到其他所有成员的观察者列表中
                existing_member.add_observer(leader)

        #2和0 判断新成员是否观察自身
        if leader.mode%2==0:
            # 观察自己和加入队列
            leader.add_observer(leader)  # 观察自己
        self.leader=leader
        leader.queue = self

    def remove_leader(self,leader):
        """安全移除成员并清理观察关系"""
        if self.leader!=leader:
            print("领队不在当前队列中")
            return
        for existing_member in self.members_list:
            # 删除领队的观察者身份(清空队列中其他成员的观察者弱引用)
            existing_member.remove_observer(leader)
        leader.queue = None  # 清除队列引用
        # 清空自身观察,因为自身不在member_list中
        leader.remove_observer(leader)
        # 从队列中移除
        self.leader=None

在上述奇美拉队列类中,我们把领队和工作奇美拉分开管理,方便后续奇美拉技能导致的队列变动。

心得体会

用一个类对象来管理奇美拉对象有很多好处,刚开始没考虑到的事情后面可以直接添加到奇美拉队列类中,比如抢功劳奇美拉中需要判断当前工作的进度,而在奇美拉对象中共无法直接获得工作进度。可以选择修改eval函数的接口,修改eval函数的接口就要修改基类的接口,导致需要修改其他已实现的代码。因此我最后选择直接在奇美拉队列类中新增一个属性,保存当前待完成的工作,因为每个奇美拉都保留了当前队列的引用,可以直接获得当前工作的进度。

扩展

用奇美拉队列类来管理奇美拉队列,开始时我们创建奇美拉对象然后添加到奇美拉队列对象中,注意添加顺序,最左面的奇美拉应该先添加。最后当任务完成后,我们需要调用奇美拉队列对象的移除方法移除所有的奇美拉对象,然后del所有的奇美拉对象。对象删除之类的操作在实际生产环境中是非常重要的。而在本项目中,所有奇美拉对象在主程序执行完毕后销毁。

规则定义

这里的很多规则是在实现过程中不断完善的,有了方便读者阅读和理解,在此我先给出所有的规则,之后再给出所有奇美拉类的具体实现。

工作相关

  • 采用回合制,第一回合开始的时候统一设置奇美拉登场相关的属性从而触发奇美拉登场技能。后续的每回合都做如下操作:

    1. 每回合开始时回合数加1,以便触发奇美拉每回合的技能。
    2. 固定奇美拉攻击力,这点非常重要!!这保证了本项目的结果和游戏结果一致!!因为在实际游戏中,对于攻击力的buff最后才会执行,因此我们固定攻击力快照后,即使增加攻击力的buff提前执行,也并不影响实际的结果!!!
    3. 第一个奇美拉工作。工作逻辑为先处理工作对象的hp,再处理当前对象的hp,判断当前工作是否已经被完成,工作数量+1。先判断工作是否被完成,再工作数+1是正确绑定工作完成关系的关键。因为当前奇美拉已经完成工作,并且先工作+1,那可能会触发其他奇美拉的追加攻击,导致程序判定触发被动的奇美拉完成工作。(这涉及到后面的规则,为了和游戏结果保持一致,工作已经被完成也会继续追加攻击以便继续加buff)。
    4. 判断奇美拉hp是否小于1,如果小于1则离场。如果奇美拉的hp小于1并且代表登场的属性为False,则奇美拉也离场(其他奇美拉的技能可能会导致奇美拉hp>0但是直接离场)

奇美拉相关

  1. 工作已经被完成也会继续追加攻击以便继续加buff

  2. 奇美拉如果导致其他奇美拉直接离场,并不会修改离场奇美拉的hp,也不会从队列中移除该奇美拉,而是修改该奇美拉对象中表示登场的属性为False

    这么做可能会出现一个问题,那就是游戏中奇美拉离场的动作优先级很高,而在本项目实现中,奇美拉离场逻辑在每回合最后才处理。这可能导致奇美拉离场和交换位置相关技能之间的联动和游戏中的结果不一致。因此在本项目中,我们做出一致性规定:奇美拉一定在本回合工作结束,所有技能都触发后才离场。交换位置的技能发动后,奇美拉可以和将要离场但是还未离场的奇美拉交换位置。

    做出如上规定后,与交换位置相关的技能的代码逻辑就变得简单多了,我们只需要考虑当前位置即可,不需要考虑当前位置前后的奇美拉是否已经离场。

  3. 奇美拉技能发动的大前提一定是奇美拉在场!!这点和上面的2有联动。

  4. 工作已经被完成后,奇美拉会继续追加攻击当前被完成的工作,以便吃到buff加成。

  5. 奇美拉技能执行期间,如果可能触发其他技能,那应该保证当前需要处理的逻辑处理完成后再修改可能触发技能的属性。由于这种情况很少,因此我用这种简单的方法保证”原子性“(这么说并不准确!!只是方便理解把)。比如如果奇美拉追加攻击后,应该先判断工作是否被完成再增加奇美拉追加工作的次数。因为增加追加工作次数可能触发其他奇美拉的被动(同伴工作或者追加工作触发的被动)

  6. 奇美拉体力降低到0时不会立刻退场,等到回合结束后统一离场=其他奇美拉技能可以增加hp)。同伴累到的判断条件为奇美拉的hp小于0。因此可能会出现这么一种情况,同伴累到时的触发的被动可能会被同一个奇美拉触发多次,这点是否在游戏中也是如此本人并没有验证,在此指出

  7. 在eval中,如果我们操作可能被监控的属性,应该用非下划线的形式,否则不会被监控到。在本项目中,只要属性变化一定会调用观察者的eval,因此我们需要准确处理eval中的逻辑,如果不满足条件应该提前推出eval函数。(在最后的优化讨论中,我将给出优化方向,奇美拉仅监控其他奇美拉会触发技能的属性,而不是监控所有属性

  8. 技能对同伴的操作一律不包含自身,例如使得同伴体力全部+8,不包括自身。我并没有验证游戏结果,而是仅从字面意思判断,同伴肯定指的是自己之外的奇美拉。我自己是这么理解的,如果游戏中同伴也包括自身,则对应修改即可,本项目则坚持同伴指的是自己之外的奇美拉。

奇美拉属性

self.name=name  #奇美拉名字
self.__atk=1  
self.__hp=1
self.__episode=0  #回合数,用于触发回合技
self.__on=False  #是否在场,True为登场,刚开始的时候为False
self.__work_num=0  #工作次数,用于触发 【同伴工作后】的技能
self.__append_work_num=0  #追加攻击次数,用于触发 【同伴追加工作后】的技能
self.__mode=0  #监控规则,详情见正文描述
self.__skill=True  #奇美拉是否有技能
self.__complete_work_num = 0  #奇美拉完成工作次数,用于触发【同伴完成工作】的技能
self.__fixed_atk=0  #每回合开始奇美拉的攻击快照。保证了本项目结果和游戏结果的一致性。

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

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

相关文章

一周学会Pandas2 Python数据处理与分析-Pandas2数据合并与对比-pd.concat():轴向拼接

锋哥原创的Pandas2 Python数据处理与分析 视频教程: 2025版 Pandas2 Python数据处理与分析 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 在数据分析中,数据往往分散在多个来源(如不同文件、数据库表或API),需…

安卓原生兼容服务器

安卓原生兼容服务器的定义 安卓原生兼容服务器‌指基于Android系统内核和服务框架构建的服务器环境,能够在不依赖第三方适配层的情况下,直接运行符合Android API规范的服务程序,并满足与其他软硬件组件的协同工作需求。其核心特征体现在以下…

优化用户体验:拦截浏览器前进后退、刷新、关闭、路由跳转等用户行为并弹窗提示

🧑‍💻 写在开头 点赞 收藏 学会🤣🤣🤣 需求 首先列举一下需要拦截的行为,接下来我们逐个实现。 浏览器前进后退标签页刷新和关闭路由跳转 1、拦截浏览器前进后退 这里的实现是核心,涉及到大…

大学生创新创业项目管理系统设计——数据库实验九

本实验为自己设计完成,我当年数据库实验得了94分 目录 1.实验目的 2.实验内容和要求 3.实验步骤 4.实验心得 实验九 数据库设计 1.实验目的 掌握数据库设计的过程和方法。 2.实验内容和要求 (35)大学生创新创业项目管理系统设计 一…

电磁场与电场、磁场的关系

电磁场与电场、磁场之间存在着深刻的内在联系和统一性关系。这三者共同构成了电磁相互作用的基本框架,是理解电磁现象的关键所在。 电场和磁场实际上是电磁场的两个不同表现形式,它们既相互区别又密切联系。电场主要由静止电荷产生,表现为对…

Python爬虫实战:研究Newspaper框架相关技术

1. 引言 1.1 研究背景与意义 互联网的快速发展使得新闻信息呈现爆炸式增长,如何高效地获取和分析这些新闻数据成为研究热点。新闻爬虫作为一种自动获取网页内容的技术工具,能够帮助用户从海量的互联网信息中提取有价值的新闻内容。本文基于 Python 的 …

Kotlin MultiPlatform 跨平台版本的记账 App

前言 一刻记账 KMP (Kotlin MultiPlatform) 跨平台版本今天终于把 Android 和 iOS 进度拉齐了. 之前只有纯 Android 的版本. 最近大半年有空就在迁移代码到 KMP 上 中间学了 iOS 基础知识. xcode 的使用. 跨平台的架构的搭建… 感觉经历了很多很多. 一把辛酸泪 迁移的心路历…

PIO 中的赋值魔术,MOV 指令

前言 在普通编程语言中,mov 可以理解为“赋值指令”,将一个值从一个地方拷贝到另一个地方。在 RP2040 的 PIO 汇编语言中,mov 同样是数据传递的关键指令,但它操作的是 PIO 独有的几个寄存器。 在 PIO 中,你可以用 mov …

第十七次CCF-CSP算法(含C++源码)

第十七次CCF-CSP认证 小明种苹果AC代码 小明种苹果&#xff08;续&#xff09;AC代码 后面好难哈哈 小手冰凉 小明种苹果 输入输出&#xff1a; 题目链接 AC代码 #include<iostream> using namespace std; int n,m; int res,res3; int sum; int res21; int main(){cin …

打造一个支持MySQL查询的MCP同步插件:Java实现

打造一个支持MySQL查询的MCP同步插件&#xff1a;Java实现 用Java实现一个MCP本地插件&#xff0c;直接通过JDBC操作本地MySQL&#xff0c;并通过STDIO与上层MCP客户端&#xff08;例如Cursor&#xff09;通信。插件注册一个名为mysql 的同步工具&#xff0c;接收连接参数及SQL…

黑马k8s(十五)

1.Ingress介绍 2.Ingress使用 环境准备 Http代理 Https代理

解决 cursor 中不能进入 conda 虚拟环境

【问题】 遇到一个小问题&#xff0c;我创建的conda 环境在 cmd、powershell中都可以激活&#xff0c;但在pycharm、cursor中却不能激活&#xff1f; 看图 cmd中正常&#xff1a; cursor中不正常&#xff1a; 【解决方法】 cursor 中&#xff0c;打开终端&#xff0c;输入&a…

C++ 实现二叉树的后序遍历与中序遍历构建及层次遍历输出

C 实现二叉树的后序遍历与中序遍历构建及层次遍历输出 目录 C 实现二叉树的后序遍历与中序遍历构建及层次遍历输出一、实验背景与目标二、实验环境三、实验内容四、数据结构与算法数据结构算法描述1. **构建二叉树函数 buildTree**2. **层次遍历函数 LevelOrder** 关键代码与解…

虚拟环境中的PyQt5 Pycharm设置参考

假如虚拟环境名是p3939 里面安装了pyqt5相关的库 1.QtDesigner Qt Designer 是通过拖拽的方式放置控件&#xff0c;并实时查看控件效果进行快速UI设计 位置 内容 name 可以随便命名&#xff0c;只要便于记忆就可以&#xff0c;本次采取通用…

AUTOSAR图解==>AUTOSAR_SRS_LIN

AUTOSAR LIN模块分析 目录 LIN模块概述LIN模块架构LIN通信状态流程LIN通信序列LIN配置结构总结1. LIN模块概述 本文档基于AUTOSAR规范SRS_LIN文档,对LIN(Local Interconnect Network)相关模块进行详细分析。主要包括以下几个模块: LIN接口 (LinIf)LIN驱动 (Lin)LIN传输层…

华为昇腾使用ollama本地部署DeepSeek大模型

文章目录 前言一、本次使用的硬件资源二、Ollama介绍三、Ollama在arm64位的芯片的安装及使用方法总结 前言 本次打算在华为昇腾上面使用ollama进行部署DeepSeek大模型。 一、本次使用的硬件资源 存储资源 内存资源 cpu资源 二、Ollama介绍 Ollama 是一个开源的大型语言…

多态的总结

什么是多态&#xff1f; 答&#xff1a;多态是多种形态&#xff0c;是为了完成某种行为时&#xff0c;不同对象会产生不同的形态&#xff08;结合车票例子解释&#xff09; 2. 什么是重载、重写(覆盖)、重定义(隐藏)&#xff1f; 答&#xff1a;重载的条件是&#xff1a;在同一…

Windows 高分辨率屏幕适配指南:解决界面过小、模糊错位问题

&#x1f5a5;️ Windows 高分辨率屏幕适配指南&#xff1a;解决界面过小、模糊错位问题 摘要&#xff1a; 在使用高分辨率屏幕时&#xff0c;许多老旧的桌面软件会出现界面显示异常的问题&#xff0c;例如窗口过小、控件错位、文字模糊等。本文提供一套通用解决方案&#xff0…

K8S-statefulset-mysql-ha

需求 实现一个HA mysql&#xff0c;包括1个master&#xff0c;2个slave。在K8S上已statefulset部署。 mysql HA原理 略 K8S环境需要解决的问题 1、由于使用同一个statefulset配置&#xff0c;因此需要考虑master和slave使用不同的cnf文件。 2、不同pod之间文件的传输 3、…

【方案分享】展厅智能讲解:基于BLE蓝牙Beacon的自动讲解触发技术实现

【方案分享】展厅智能讲解&#xff1a;基于BLE蓝牙Beacon的自动讲解触发技术实现 让观众靠近展品即可自动弹出讲解页面&#xff0c;是智能展厅的核心功能之一。本文将从软硬件技术、BLE Beacon原理、微信小程序实现、优劣对比与拓展方案五个维度&#xff0c;系统讲解“靠近展台…