加权轮次

作者:Eric Hodges

规范

来自 http://www.perlmonks.org/?node_id=731443

这是一个策略游戏的一部分。战斗中有多艘船只,您必须确定它们采取行动的顺序。

  • 每艘船都有一个主动性值。

  • 在回合开始时,每艘船都会获得与其主动性值相等的票数。选票是随机抽取的。当一艘船的选票第一次被抽中时,它就会轮到它行动。它剩下的选票就作废了。

工作示例

  • 3 艘船 <A B C>,主动性值为 (1,2,4)。

  • 我们将选票放入一个数组中:<A B B C C C C>

  • 我们随机抽取一张选票:C。轮到 C 行动了。

  • 我们再抽一张选票:C。什么也不做。

  • 我们再抽一张选票:C。什么也不做。

  • 我们再抽一张选票:B。轮到 B 行动了。

  • 我们再抽一张选票:B。什么也不做。

  • 我们再抽一张选票:A。轮到 A 行动了。

  • 我们抽取最后一张选票:C。什么也不做。

  • 所以最终的顺序是:<C B A>

这不一定是执行该算法的最有效方式。

需要注意的有用事项

  • 要生成一个从 1 到 N 的随机数,请使用 (1..N).pick

  • 要生成一个从 0 到 N-1 的随机数,请使用 (0..^N).pick

源代码:weighted-roll-731696.pl

use v6;

our $SHIPS = 4;
our $REPS  = 30;

my @weights = (1..16).pick($SHIPS, :replace);
for @weights.kv -> $k, $v { say "$k: $v" }

my $total = [+] @weights;
say "Total Weights $total";

sub pick(@weights, $total) {
   my $rand = (0..^$total).pick;
   for @weights.kv -> $i, $w {
       $rand -= $w;
       return $i if $rand < 0;
   }
}

sub pickAll(@weights is copy, $total is copy) {
   my @order;
   for @weights {
        my $pick = pick(@weights, $total);
        @order.push($pick);
        $total -= @weights[$pick];
        @weights[$pick] = 0;
   }
   return @order;
 }

say ~pickAll(@weights,$total) for 1 .. $REPS;