13454awdafasd
如题,我想知道诸如工业之类的MOD的电线是如何判断的?

比如:
1. 如何判断电线是连接起来的
2. 如何判断电线的电量传输和消耗等等

并且我是在用插件开发,类似于Slimefun但又不同(版本: 1.12.2 其他版本兼容无所谓)

洞穴夜莺
本帖最后由 洞穴夜莺 于 2020-9-5 18:00 编辑

这里应该要用到图论
涉及最短路算法
具体就不说了,繁琐得很,不是一天两天能说明白的

roj234
给个思路:
pending = Set.add(起始位置)
pending2 = new Set;
all = new Set;
while(!pending.isEmpty()) {
    for(BlockPos pos : pending) {
        检测电线周边有没有不在all中的电线,有的话加入pending2
    }
    all.addAll(pending);

    tmp = pending;
    pending = pending2;
    pending2 = tmp;
    pending2.clear();
}

电线不能太长什么的自己处理, 此外效率估计不会太高最后返回all,代表所有符合条件的方块

名为123的貘
希腊奶
但是我自己写的话,如果像是凛冰超导之类的玩意,可能会考虑并查集之类的……那样一次更新导线时间复杂度就是O(n=直接连接的导线数)
最短路不难吧……而且这里长度都是1,直接广搜即可。

洞穴夜莺
名为123的貘 发表于 2020-9-5 21:24
希腊奶
但是我自己写的话,如果像是凛冰超导之类的玩意,可能会考虑并查集之类的……那样一次更新导线时间 ...

确实是连通性不难
但是求最短路的时间复杂度高

名为123的貘
洞穴夜莺 发表于 2020-9-5 21:26
确实是连通性不难
但是求最短路的时间复杂度高

可以优化算法使用的次数。
当发生更新的时候,接入机器则所有机器都算一遍路线,导线更改则更新一遍并查集,如果分裂则重新算一遍所有机器的路线。这样也就卡一下下而已。

13454awdafasd
roj234 发表于 2020-9-5 21:14
给个思路:
pending = Set.add(起始位置)
pending2 = new Set;

所以每放一个方块就加入到一个Set里 拆一个方块移除

然后每个方块六个面不断地去遍历去一个一个找最短线路吗?
另外我也在考虑一个导线开一个线程 不过这样消耗似乎非常大
[或者说可以区块? 如果每次放都去遍历的话 多了会很卡吧 还有导线回路会不会导致死循环啥的]

(你说的我实在是没懂..)


13454awdafasd
名为123的貘 发表于 2020-9-5 21:24
希腊奶
但是我自己写的话,如果像是凛冰超导之类的玩意,可能会考虑并查集之类的……那样一次更新导线时间 ...

广搜指一个一个方块去遍历六个面吗 有的话就继续这个操作直到尽头 那怎么判断上面的机器呢

或者有没有办法给一个block加类似于nbt的东西 如果不行的话我就要考虑map了 但是由于我的不同机器是存在不同map里的(早知道用一个map了) 如果用一个map很难区分类型 难道全都继承一个然后最终判断的时候一个一个instanceof吗 会不会过于麻烦

另外一个map中仅仅使用一个location作为key(狭义上的location 仅仅存储了xyzWorld) 会不会有不方便的地方[发现写这些东西考虑的点多又杂]

飞翔之歌
本帖最后由 飞翔之歌 于 2020-9-6 10:16 编辑
13454aw**sd 发表于 2020-9-6 10:10
广搜指一个一个方块去遍历六个面吗 有的话就继续这个操作直到尽头 那怎么判断上面的机器呢

或者有没有办 ...

并查集了解一下,每个导线分属不同的并查集,只需遍历一个方块的六个面并合并即可。

飞翔之歌
本帖最后由 飞翔之歌 于 2020-9-6 10:18 编辑

类似于: 机器-导线 导线-机器导线跟导线分开的,有两个并查集
当导线变成 机器-导线-导线-机器
导线连接,两个并查集合并

13454awdafasd
飞翔之歌 发表于 2020-9-6 10:15
并查集了解一下,每个导线分属不同的并查集,只需遍历一个方块的六个面并合并即可。 ...

本来有点思路了 这么一说又没了 啊这

飞翔之歌
onBlockPlaced() {
  遍历六个面对应的方块
        如果是导线\机器
              获得并查集,将自己合并进去
}

第一页 上一页 下一页 最后一页