写在前面: 给出的悬赏可能在各位眼里看起来比较可笑,但对我来说这是我两天的生活费了,网上的教程乱七八糟,目前的这个架构是在 chatGPT 设计的结构上魔改的,但出了严重的问题。如果能解决这个问题,我宁愿不吃不喝两天整 提前谢谢各位了,这项目是自己玩整的,别的都好了,就卡在一个 ast 上,虽然是自己做着玩的,但实在不想前功尽弃
这边的游戏需要设计一个可以将效果原子化和序列化的功能,由于 function 方法不可被原子化,且我这边无法使用 lua ,因此我设计了一个能输入和输出任意类型的抽象语法树,可以对其节点进行序列化和反序列化,从而使得整个树可以序列化。当前设计如下: 有一个接口(astNode),简称基类,有一个泛型 O ,有一个 operation 方法,输出类型是 O ,传参是 map<string ,object> 在基类第二层的是结构化节点:叶子节点和枝干节点,都继承自第一层。 叶子节点只存储一个值,但不能存节点,有两个泛型,一个是记录存储属性类型的,一个是记录返回类型的。叶子节点就两种,一种记录常数(constant),比如 2x+1 里的 2 和 1. 另一种记录未知数(param),就是 2x+1 里的 x ,他会读取 operation 方法传过来的 map ,从里面找到对应的对象。 枝干节点则里面可以存储叶子节点或枝干节点。 他们有三种类型,单节点型,list 型和 pair 型,单节点的,比如提取目标怪兽的血量,里面就只需要记录一个指向怪兽的叶子节点。双节点最常见,加减乘除,operation 方法就是将两个节点 operation 的值进行运算。list 节点则是类似 in ,传入一个 list ,他从里面返回一个符合需求的值。 然后第三层就是对运算目标的类型进行定义的层。比如 equals ,有针对数字的 equals ,有针对怪物实体的 equals ,等等,这一层将他们进行封装。 第四层是封装层,这层会将所有泛型全部匹配,不会出现需要在外面输入泛型的情况。 在最外侧,会有一个 tree 实体,这个实体可以访问根节点,并进行如深度搜索或者是查找节点,替换节点之类的行为。 现在的问题是: 我想要一个方式能将这个树序列化和反序列化,并通过读取用户输入将其转换为一个树。 我最开始是打算从根节点向叶子节点进行构建,但我很快发现这个方法的不可操作性:因为我的树不是完全的二叉树,有常数和未知数两种没有子节点概念的树,他们只有一个 value ,而且由于我有三种不同类型的枝干节点,我无法使用一个统一的,写在基类里的 addNode 方法在节点生成后对子节点进行操作,我必须使用 if else 才行,这违背了泛型的初衷,也十分不灵活,所以我必须从最下方的叶子节点往上方构建。 我的打算是,先筛选出所有的叶子节点,然后像搭金字塔一样,用 1 ,2 ,list 个节点将符号构建出来,然后在这个符号上再和其他符号或者节点一起搭符号,最后搭到根节点。但是这有个问题:当我在使用如 numberEqualsNode ,这种左右节点一个是 int ,另一个也是 int ,输出是 bool 的节点,我该如何判断输入的 node 的泛型是 int ?如果不判断,那么左右节点设置泛型的意义何在? 由于 java 的泛型是在运行之后会被删掉的和注释一样的用于检查编译的东西,所以我不能直接 if node is node<int>,但那样我怎么检查这个节点?
备注:无法换语言,或者使用 lua ,但可以使用 kotlin 和 scala 。可以改变一些设计,但不能把整个底层都给刨了。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.