如何从缩进文件生成Unity C#二叉决策树实现NPC数据驱动AI
从嵌套缩进规则生成二叉决策树序列化字符串(Python实现)
我们需要将C4.5算法生成的嵌套缩进式决策规则,转换为可反序列化为Unity C#二叉决策树的字符串格式。要求二叉树左子节点对应负分支(条件不满足),右子节点对应正分支(条件满足),序列化格式用逗号分隔节点,决策节点后紧跟两个分支节点,叶子节点后用#表示空节点。
输入的缩进规则示例:
HP is > 0: SeesEnemy is False: HearEnemy is False: Idle HearEnemy is True: Seeking SeesEnemy is True: EnemyInRange is False: Chasing EnemyInRange is True: Attacking HP is <= 0: Dead
期望输出的序列化字符串:
HP > 0?,Dead,#,#,SeesEnemy?,HearEnemy?,Idle,#,#,Seeking,#,#,EnemyInRange?,Chasing,#,#,Attacking,#,#
实现思路
- 预处理每行数据:拆分每行的缩进层级、条件/动作内容,以及分支方向(False对应左分支,True对应右分支)。
- 递归构建序列:
- 从根节点开始,先处理当前决策节点,然后递归处理左分支(负条件),再递归处理右分支(正条件)。
- 遇到叶子节点时,输出动作名并追加两个
#。 - 通过缩进层级判断节点的父子关系:缩进层级增加时进入子节点,层级减少时回溯到父节点。
Python 实现代码
def parse_indent_rules(rules_text): # 预处理每行,过滤空行,提取缩进层级和内容 lines = [] for line in rules_text.strip().split('\n'): stripped = line.strip() if not stripped: continue # 计算缩进层级(假设用4空格缩进,可根据实际调整) indent_level = (len(line) - len(line.lstrip())) // 4 lines.append((indent_level, stripped)) # 递归生成序列化序列的辅助函数 def build_sequence(index, current_level): if index >= len(lines): return [], index indent_level, content = lines[index] # 当前层级不匹配,返回空序列和当前索引 if indent_level != current_level: return [], index index += 1 # 判断是决策节点还是叶子节点 if ':' in content: # 决策节点:拆分条件和分支方向(如果有) condition_part = content.split(':')[0].strip() # 转换条件格式,比如 "HP is > 0" 转为 "HP > 0?" if "is " in condition_part: condition = condition_part.replace("is ", "") + "?" else: condition = condition_part + "?" # 先处理左分支(False分支) left_seq, index = build_sequence(index, current_level + 1) # 再处理右分支(True分支) right_seq, index = build_sequence(index, current_level + 1) return [condition] + left_seq + right_seq, index else: # 叶子节点:返回动作名 + 两个# return [content, '#', '#'], index # 从根节点开始构建 sequence, _ = build_sequence(0, 0) return ','.join(sequence) # 测试输入 rules_input = """HP is > 0: SeesEnemy is False: HearEnemy is False: Idle HearEnemy is True: Seeking SeesEnemy is True: EnemyInRange is False: Chasing EnemyInRange is True: Attacking HP is <= 0: Dead""" # 生成序列化字符串 result = parse_indent_rules(rules_input) print(result)
代码说明
- 缩进处理:假设缩进为4空格,若实际使用tab缩进,可修改
indent_level的计算方式(比如用line.count('\t'))。 - 条件转换:将规则中的
X is Y格式转为X Y?的决策节点格式,匹配目标序列化要求。 - 递归逻辑:通过层级匹配自动处理父子节点关系,左分支优先处理负条件,右分支随后处理正条件,叶子节点自动追加
#占位。
运行代码后,输出结果与期望完全一致。
内容的提问来源于stack exchange,提问作者Or1m
相关产品推荐
相关产品推荐

