猫史档案馆


【box3教程】并查集实现玩家联盟系统!1

用户:yee089yee089查看:17 回复:9 评论:17 创建时间:2022-05-09T10:13:31


声明:

1、本教程和编创协的算法部没有半毛钱关系。

2、如果有bug,各位大佬在评论区使劲喷,我只是一个萌新

3、这段代码是第一版,所以更像‘面向过程’编程。后面我会封装的。

4、父节点是非常正常的术语,你

————————————————————————————————————————————————(分鸽线)

玩家的联盟实际上就是一个非常容易想到,非常‘裸’(也就是模板题)的并查集,

并查集,这个名字非常高级()()但是其实基础版的非常好实现。我们来模拟亿下:

首先有n个人:a_1,a_2,a_3,a_4,a_5,a_6,……,a_n.

我们要实现两个功能:合并a_i和a_j(merge),

                             检查a_i和a_j是否在同一组织里(check)

首先我们建立一个父节点的数组f,初始化为:对于任意0~n间的i,a_i=i(好像这么说(?))

合并a,b,我们先找到a的祖先c,b的祖先d,让d指向c。怎么找到祖先呢?我们看这个初始化,根节点的父节点指向自己,那么我们可以这么写find:

 
function find(z){
	let x = z;
	while(x != a[x]){
		a[x] = a[a[x]];//经典的路径压缩优化,非常棒
		x = a[x];
	}
	return x;
}

(a就是f,不想改了)

检查a,b是否在同一集合呢?只需要检查a的祖先和b的祖先是不是一个人就可以了。上代码:

function check(az,b){
    let ax = find(az),
        bx = find(b);
    return ax == bx;
}

好的,现在你应该会写并查集了吧emotion_doge()()

————————————————————————————————————————————————(分鸽线)

接下来我们要做一个玩家进入后的联盟(左键攻击,右键询问是否联盟,联盟后不能互相攻击)。

这一段有手就行emotion_doge,我们直接上代码:

let player_list = new Map();//映射表方便。
let num_to_pla = [];
player_list.clear();
let a = [0];
world.onPlayerJoin(async({entity})=>{
    entity.enableDamage = true
    if(player_list.get(entity.player.name) == undefined){
        player_list.set(entity.player.name,num_to_pla.length);
        num_to_pla.push(entity.player.name)
        a.push(a.length);//之所以这么写,主要是为了节省内存,还省的再打初始化)
    }
    entity.onClick(async({clicker,button})=>{
        if(button == Box3ButtonType.ACTION1 && !check(entity.player,clicker.player)){//虽然名义上是一个O(n)的check,但是经过足够多的路径压缩后整课树会成为‘菊花树’(只有两层的树),所以其实基本是O(1)check
            const ans = await entity.player.dialog({
                type:Box3DialogType.SELECT,
                title:clicker.player.name + '对你发送了联盟请求',
                options:['同意','不同意']
            })
            if(!ans ||ans == null)return;
            if(ans.index == 0){
                console.log(clicker.player.name+' 与 '+entity.player.name+'联合')
                //merge
                let xf = find(player_list.get(entity.player.name)),
                    yf = find(player_list.get(clicker.player.name));
                a[yf] = a[xf];
            }
        }
        if(button == Box3ButtonType.ACTION0 && !check(entity.player,clicker.player)){
            entity.hurt(1)
        }
    })
}) 

评论区发全部代码~。

你学废了吗?


回复

上一页1 页 / 共 1下一页
yee089yee089

let player_list = new Map();
let num_to_pla = [];
player_list.clear();
let a = [0];
c喵ole.clear()
c喵ole.clear()
 
function find(z){
	let x = z;
	while(x != a[x]){
		a[x] = a[a[x]];
		x = a[x];
	}
	return x;
}
function check(az,b){
    let ax = find(player_list.get(az.name)),
        bx = find(player_list.get(b.name));
    return ax == bx;
}
world.onPlayerJoin(async({entity})=>{
    entity.enableDamage = true
    if(player_list.get(entity.player.name) == undefined){
        player_list.set(entity.player.name,num_to_pla.length);
        num_to_pla.push(entity.player.name)
        a.push(a.length);
    }
    entity.onClick(async({clicker,button})=>{
        if(button == Box3ButtonType.ACTION1 && !check(entity.player,clicker.player)){
            c喵t ans = await entity.player.dialog({
                type:Box3DialogType.SELECT,
                title:clicker.player.name + '对你发送了联盟请求',
                opti喵:['同意','不同意']
            })
            if(!ans ||ans == null)return;
            if(ans.index == 0){
                c喵ole.log(clicker.player.name+' 与 '+entity.player.name+'联合')
                //merge
                let xf = find(player_list.get(entity.player.name)),
                    yf = find(player_list.get(clicker.player.name));
                a[yf] = a[xf];
            }
        }
        if(button == Box3ButtonType.ACTION0 && !check(entity.player,clicker.player)){
            entity.hurt(1)
        }
    })
})

点赞0


评论


yee089yee089

自古沙发归楼主()

点赞0


评论


治愈绾兮治愈绾兮

az,太复杂了()

点赞0


评论


全能代码师全能代码师

还行,我之前写过sql的,还有管理联盟的成员,联盟首领什么的

点赞0


评论


全能代码师全能代码师

但是还是有点bug,很久以前写的了

 

点赞0


评论


灵清帝王吃爆一切厕所灵清帝王吃爆一切厕所

《简单》《萌新》

点赞0


评论


yee089yee089

ddd

点赞0


评论


ZNS_哪吒ZNS_哪吒

ddd

点赞0


评论


不知道该叫啥的一只萌新不知道该叫啥的一只萌新

如果不会并查集的可以给每个人分配一个id然后二分查找

点赞0


评论