选中计分板分数最高/低玩家

By MCSugar_cane    2018/08/07

最近群里在讨论这个问题,进而也应该有许多玩家,也应该对这个问题有所困惑,或是误解。其实也不算是误解,只能说是实际中并没按照理论上这么执行。

理论上,可以用操作符<或>来一键选择最高或最低分,也就是用一个marker储存计分板精度最高分数/最低分数同实体分数比较,如果实体分数更高/更低,则替换当前marker分数。代码如下:

    最高分数获取:
  1. /scoreboard players set marker test -2147483648
  2. /execute 所有需比较实体 ~ ~ ~ scoreboard players operation marker test > @e[c=1,r=0] test
  3. 最低分数获取:
  4. /scoreboard players set marker test 2147483648
  5. /execute 所有需比较实体 ~ ~ ~ scoreboard players operation marker test < @e[c=1,r=0] test

但是,在某些版本实际运行中,会出现问题,如图:

我的世界取最高分问题

图中使用指令如下:

  1. /kill @e[tag=!tf]
  2. /execute @e[tag=tf] ~ ~ ~ scoreboard players operation marker test > @e[c=1] test

然而,在上面GIF中,最后对比出的最高分并不是1312421,而是3。好了,你是不是以为是版本问题,但你不是一个人,之前我也是这样以为的。再测试发现你只要将上面的@e[c=1]改为@e[c=1,r=0],就可以了。因为只是@e[c=1]的话,在该情况下会导致选中多个实体而使实体无法执行operation。


切入正题,除了上面的方法,选中分数最高玩家还有二分法(减除),对比法,等也可以实现。不过由于效率都不如上面的方法则就不作介绍了,感兴趣的玩家可以自行测试。(说了这么多还是文不对题,我们是要选分数最值玩家,玩家啊!)

Emm,最高分得到后,得出是谁就很容易啦,指令如下:(marker为获取的最高分)

  1. /scoreboard players set marker test -2147483648 [脉冲]
  2. /execute @e ~ ~ ~ scoreboard players operation marker test > @e[c=1,r=0] test [连锁]
  3. /execute @e ~ ~ ~ scoreboard players operation @e[r=0,c=1] test -= marker test [连锁]
  4. /tellraw @a ["> 最高分为:",{"selector":"@e[score_test_min=0,score_test=0,tag=!filter]","color":"gold","bold":"true"}] [连锁]

不过这样还有一个不足,就是如果有test为0的玩家存在,那么除了最高分,0也会被算作是最高分。此外,还有0就是最高分的情况。为了避免失误,改进后如下:

  1. /scoreboard players set marker test -2147483648 [脉冲]
  2. /scoreboard players tag @a[score_test_min=0,score_test=0] add filter [连锁]
  3. /execute @e ~ ~ ~ scoreboard players operation marker test > @e[c=1,r=0] test [连锁]
  4. /scoreboard players test marker test 0 0 [连锁]
  5. /scoreboard players tag @a[score_test_min=0,score_test=0,tag=filter] remove filter [连锁](条件制约)
  6. /execute @e ~ ~ ~ scoreboard players operation @e[r=0,c=1] test -= marker test [连锁]
  7. /tellraw @a ["> 最高分为:",{"selector":"@e[score_test_min=0,score_test=0,tag=!filter]","color":"gold","bold":"true"}] [连锁]

如此,首先在算出最高分前,给test=0的玩家filter标签,算出的最高分若为0,则移除玩家的filter标签,最后test=0,没有filter标签的玩家就是分数最高的人。那如果说要算出排名该怎么办呢?


其实要实现这个功能也不难,在这上面拓展一下即可,如下:

初始化:

  1. /scoreboard objectives add test dummy
  2. /scoreboard objectives add queue dummy
  3. /scoreboard players add @a queue 0
  4. /summon armor_stand ~ ~ ~ {CustomName:"queueM"}

高频:

  1. /scoreboard players set marker test -2147483648
  2. /scoreboard players tag @a[score_test_min=0,score_test=0,score_queue_min=0,score_queue=0] add filter
  3. /execute @a[score_queue_min=0,score_queue=0] ~ ~ ~ scoreboard players operation marker test > @a[c=1,r=0] test
  4. /scoreboard players test marker test 0 0
  5. /scoreboard players tag @a[score_test_min=0,score_test=0,tag=filter,score_queue_min=0,score_queue=0] remove filter (条件制约)
  6. /execute @a[score_queue_min=0,score_queue=0] ~ ~ ~ scoreboard players operation @a[r=0,c=1] test -= marker test
  7. /execute @a[score_test_min=0,score_test=0,tag=!filter] ~ ~ ~ scoreboard players add @e[type=armor_stand,name=queueM] queue 1
  8. /scoreboard players operation @a[score_test_min=0,score_test=0,tag=!filter,c=1] queue = @e[type=armor_stand,name=queueM] queue

这样一来,玩家排名就是其queue分,依次输出即可,如下:

初始化:

  1. /scoreboard objectives add gRank dummy
  2. /execute @a[score_queue_min=1] ~ ~ ~ scoreboard operation @p[r=0] gRank = @p[r=0] queue

高频:

  1. /execute @a[score_gRank_min=1,score_gRank=1] ~ ~ ~ tellraw @a ["\u00a7a昵称: ",{"selector":"@p[r=0]","color":"gold","bold":"true"}," \u00a7a排名: ",{"score":{"name":"@p[r=0]","objective":"queue"},"color":"gold","bold":"false"}]
  2. /scoreboard players remove @a[score_gRank_min=1] gRank 1