警察和强盗


11

每个人都一直希望实施Conway的“人生游戏”。那很无聊!让我们去做警察和强盗吧!

您将有两支队伍:警察和强盗。每个小组有5名成员,每个成员有50个生命值。该程序将连续循环。每次迭代,都会发生以下情况:

  • 对于每个团队,打印第一个字母(C代表警察,R强盗),空格,成员HP的空格分隔列表和换行符。这是球队的状态。两者都完成后,打印另一个换行符。例如,这可能是第一轮比赛:

    C 50 50 50 50 50
    R 50 50 50 50 50
    
  • 从1到10中选择一个随机数(包括1和10)。我们打这个电话N。如果N是偶数,则强盗输掉了这一回合。如果很奇怪,警察就会输。

  • 从失败的团队中随机选择一个HP大于0的成员,并扣除NHP。成员的HP永远不会出现低于0的状态。

  • 重新启动循环。

当一个团队的所有成员失去所有HP时,游戏结束。然后,如果警察获胜,将打印以下内容:

C+
R-

如果强盗获胜:

R+
C-

这是代码高尔夫球,因此最少的字符获胜。

这是Python 2中的示例实现:

import random

cops = [50]*5
robbers = [50]*5

while any(cops) and any(robbers):
    # print the status
    print 'C', ' '.join(map(str, cops))
    print 'R', ' '.join(map(str, robbers))
    print
    # pick N
    N = random.randint(1, 10)
    # pick the losing team (robbers if N is even, else cops)
    losers = robbers if N % 2 == 0 else cops
    # pick a member whose HP is greater than 0
    losing_member = random.choice([i for i in range(len(losers)) if losers[i]])
    losers[losing_member] -= N
    # make sure the HP doesn't visibly drop below 0
    if losers[losing_member] < 0: losers[losing_member] = 0

if any(cops):
    # robbers lost
    print 'C+'
    print 'R-'
elif any(robbers):
    # cops lost
    print 'C-'
    print 'R+'

轻微讽刺:在此网站上,超过3176个问题被标记为game-of-life
Sanchises 2015年

3
@sanchises扩展讽刺意味:和14被标记cops-and-robbers
Runer112

@sanchises我通常在很大程度上是指编程(例如“帮助我!我正在尝试实现Conway的生活游戏!”)...但这仍然很具有讽刺意味。
kirbyfan64sos 2015年

我知道@ kirbyfan64sos(到那儿,做完了),但这正是人们实施GoL 之后想要更多的地方 ...无论如何,也许我会在> <> ,让我看看是否可以做到。
桑契斯2015年

我再次删除了CnR标签。在此附近,此标签具有非常特殊的含义,并描述了实际上有两个(不一定是脱节的)当事方在某些任务上互相竞争的挑战(请查看该标签的其他挑战)。
Martin Ender

Answers:


3

CJam,86个字节

我参加聚会有点晚了,但是我带了CJam的礼物!...嘿,等等,你要去哪里?

50aA*{"CR"1$+2/zSf*Nf+oNoAmr{_AmrE&+:P2$=:H!}gPH@)-Ue>t_2/z::+0#:L)!}g;'CL'+'-?N'R2$6^

在线尝试。

说明

当问题要求模仿一个简单的过程时,这是一个相对简单的答案。也许我做出的一个有趣的选择是将两支球队的健康状况保持在同一列表中。这需要3个字节来转换为两个单独的列表,这对于健康状况显示和检查团队是否丢失都需要。但是(我认为)这是由初始化中保存的2个字节和更简单的损坏处理逻辑所弥补的。

50aA*           "Initialize the health list to 10 copies of 50. Even indices
                 hold the health of cops and odd indices hold the health of
                 robbers.";
{               "Do:";
  "CR"1$+2/z      "Split the health list into the two teams for output, adding
                   the corresponding team letter to the start of each.
                       [a b c d e f g h i j]
                    -> [['C a c e g i] ['R b d f h j]]";
  Sf*Nf+          "Insert a space between each element in each team health list
                   and append a newline to the end of each team health list.";
  oNo             "Print the health status for each team and an extra newline.";
  Amr             "Generate the damage amount minus one. If the damage amount is
                   even (robbers lose), then this is odd and aligns with robbers
                   being at odd indices in the health list, and vice versa.";
  {               "Do:";
    _AmrE&+:P       "Add a random even number from [0, 10) to the damage amount
                     minus one. This value modulo the size of the health list
                     (10) selects a person on the losing team to be damaged.";
    2$=:H!
  }g              "... While the selected person's health is zero.";
  PH@)-Ue>t       "Set the damaged person's new health to the maximum of their
                   current health minus the damage amount and zero.";
  _2/z::+0#:L     "Split the health list into the two teams, sum each team's
                   health, and search for a team's health equal to zero.";
  )!
}g              "... While no team's health was found equal to zero.";
;               "Discard the health list.";
'C              "Produce a 'C'.";
L'+'-?          "Produce a '+' if team 1 (robbers) lost, or '-' otherwise.";
N               "Produce a newline.";
'R              "Produce an 'R'.";
2$6^            "Produce the opposite of the sign produced before.";
                "Implicitly print these final results.";

3

R-201

S=sum
Z=sample
C=R=rep(50,5)
while(S(R)*S(C)){cat("C",C,"\nR",R,"\n\n")
N=Z(10,1)
F=function(x,i=Z(rep(which(x>0),2),1)){x[i]=max(0,x[i]-N);x}
if(N%%2)R=F(R)else C=F(C)}
cat(c("R+\nC-\n","C+\nR-\n")[1+!S(R)])

还为什么rep(which(x>0),2)反对which(x>0)呢?
MickyT 2015年

1)我正在计算EOL字符,尽管不是最后一个。2)sum(R*C)sum(R)*sum(C)不是同一件事。例如,如果C = c(0,0,0,10,10)且R = c(10,10,10,0,0),则您不想退出。在这种情况下,我确实通过分配进行保存S=sum。3)的问题sample是,如果第一个参数是一个单一的数字,例如sample(5, 1),那么这将是一样的做sample(1:5, 1):不是总是返回5,它将从返回任意数量15。所以,sample(rep(x, 2), 1)是我老是挑中了一些技巧x时,即使在情况下length(x)1
flodel

对不起,我不好。显然咖啡不足。感谢您对rep()技巧的解释。我认为一定有一个原因,就是看不见
MickyT 2015年

2

APL(Dyalog)(101)

∇K
S←2 5⍴50
→6/⍨~∧/J←∨/S>0
⎕←3↑'CR',0⌈S
S[L;M[?⍴M←(0<S[L←1+~2⊤N;])/⍳5]]-←N←?10
→2
⎕←'CR',⍪'+-'⌽⍨J⍳0
∇

说明:

  • S←2 5⍴50:开头,将其设置S为5×2矩阵,每个值均为50。矩阵的第一行代表警察,第二行代表强盗。
  • J←∨/S>0:对于矩阵的每一行,存储J是否有任何HP大于零。
  • →6/⍨~∧/J:如果两个团队都没有在役成员,请跳至第6行。(结束)
  • ⎕←3↑'CR',0⌈S:对于矩阵中的每个值,输出其最大值和0,在第一行前添加“ C”,在第二行前添加“ R”,并添加第三行(空)。
  • N←?10:在间隔[1,10]中获取一个随机数,并将其存储在中N
  • L←1+~2⊤N:将L(失败的队伍)设置1为数字是奇数,2还是偶数。
  • M←(0<S[L... ;])/⍳5:获取该团队现有成员的索引,并将其存储在M
  • M[?⍴M... ]:从中选择一个随机值M
  • S[L;M... ]-←NN从所选团队成员的值中减去
  • →2:跳至第2行(对在职成员的测试)
  • ⎕←'CR',⍪'+-'⌽⍨J⍳0:输出最终状态,将+获胜团队-置于失败者的前面。

样品输出


1

红宝石184

c,r=[p,p].map{('50 '*5).split}
puts([?C,*c]*' ',[?R,*r]*' ')while (u,v=[r,c].map{|a|a.shuffle.find{|x|x>?0}}).all?&&[u,v][rand(1..10)%2].sub!(/.+/){eval"#$&-1"}
puts u ?'R+
C-':'C+
R-'

1

Mathematica,246 241字节

可能还会打高尔夫球...

a=ConstantArray[50,{2,5}];b=Or@@(#<1&)/@#&;c=Print;d=StringJoin@Riffle[IntegerString/@#," "]&;e=RandomInteger;Label@f;Which[b@a[[1]],c@"R+\nC-",b@a[[2]],c@"C+\nR-",True,c["C "<>d@a[[1]]<>"\nR "<>d@a[[2]]];a[[Mod[g=e@9+1,2]+1,e@4+1]]-=g;Goto@f]

1

PHP-416字节

我是打高尔夫球的新手,尽管尝试这项挑战很容易。这就是我的想法。

<?$c=[50,50,50,50,50];$r=[50,50,50,50,50];while((array_sum($c)!=0)&&(array_sum($r)!=0)){$a="C ".join(" ",$c)."\n";$b="R ".join(" ",$r)."\n";echo$a,$b;$n=rand(1,10);$m=rand(0,4);if($n %2==0){while($r[$m]==0){$m=rand(0,4);}$r[$m]=$r[$m]-$n;if($r[$m]<0){$r[$m]=0;}}else{while($c[$m]==0){$m=rand(0,4);}$c[$m]=$c[$m]-$n;if($c[$m]<0){$c[$m]=0;}}if(array_sum($r)==0){echo"C+\nR-\n";}if(array_sum($c)==0){echo"R+\nC-\n";}}?>

附带说明:

<? 
$c=[50,50,50,50,50];$r=[50,50,50,50,50];                       populate Arrays
while((array_sum($c) != 0) && (array_sum($r) != 0)){           loop until on array sums up to 0
    $a="C ".join(" ",$c)."\n";                                 set cops health to a
    $b="R ".join(" ",$r)."\n";                                 set robbers health to b
    echo$a,$b;                                                 print cop and robber health
    $n=rand(1,10);                                             chose random n
    $m=rand(0,4);                                              chose random member
    if($n % 2 == 0){                                           check if n is even
        while($r[$m] == 0){ $m=rand(0,4); }                    loop until value m of array r is not 0
        $r[$m]=$r[$m]-$n;                                      lower health of member m
        if($r[$m] < 0){ $r[$m]=0; }                            if health goes below 0 set it to 0
    }else{
        while($c[$m] == 0){ $m=rand(0,4); }                    same as above
        $c[$m]=$c[$m] - $n;
        if($c[$m] < 0){$c[$m]=0;}
    }
    if(array_sum($r) == 0){ echo"C+\nR-\n"; }                  check if r array sums up to 0 and print that cops won
    if(array_sum($c) == 0){ echo"R+\nC-\n"; }                  check if c array sums up to 0 and print that robbers won
}
?>

我不是PHP用户,但我想也许您可以通过!= 0用not运算符(!array_sum($r))删除并替换为零的校验来减少一些字符。
kirbyfan64sos 2015年

@ kirbyfan64sos不起作用
Timo

哦。在大多数语言中,它会。
kirbyfan64sos 2015年

1

C,390个 384 371字节

我的第一个高尔夫,如果有任何可能的改善,请告诉我:)

高尔夫球版:

#include <time.h>
#include <stdio.h>
int p[10],j,r,c,w,N,x;int s(){r=c=0;for(j=5;j--;){c+=p[5+j];r+=p[j];}return !!r-!!c;}void t(){for(j=10;j--;)printf("%s %d",j-4?j-9?"":"\n\nC":"\nR",p[j]*=p[j]>0);}main(){srand(time(0));for(j=10;j--;)p[j]=50;t();while(!(w=s())){N=rand()%10+1;while(!p[x=N%2*5+rand()%5]);p[x]-=N;t();}N=(x=w<1?'C':'R')-w*15;printf("\n\n%c+\n%c-",x,N);}

有点松散的版本:

#include <time.h>
#include <stdio.h>
int p[10],j,r,c,w,N,x;

int s(){
    r=c=0;
    for(j=5;j--;){
        c+=p[5+j];
        r+=p[j];
    }
    return !!r-!!c;
}

void t(){
    for(j=10;j--;)printf("%s %d",j-4?j-9?"":"\n\nC":"\nR",p[j]*=p[j]>0);
}

main(){
    srand(time(0));
    for(j=10;j--;)p[j]=50;
    t();
    while(!(w=s())){
        N=rand()%10+1;
        while(!p[x=N%2*5+rand()%5]);
        p[x]-=N;
        t();
    }
    //w=-1 if cops won, w=1 if robbers won
    N=(x=w<1?'C':'R')-w*15;
    printf("\n\n%c+\n%c-",x,N);
}

编辑:我找到了一种方法来缩短它并修复了一个小错误


小改进:您可以将循环(例如for(j=0;j<10;j++))替换为较短的版本(for(j=10;--j;))。
kirbyfan64sos 2015年

您完全正确,“解决”了此问题以及其他一些小问题,谢谢。
Metaforce 2015年

0

批次-396字节

我不知道这在技术上是否有意义-因为它实际上没有选择健康状况大于0的团队成员。它只是选择一个随机成员,并且如果健康减法生成的数字小于0,则该数字变为0。

@echo off&setLocal enableDelayedExpansion&for %%a in (C R)do for %%b in (1 2 3 4 5)do set %%a%%b=50
:a
set/aN=%RANDOM%*10/32768+1
set/ac=%N%/2*2
if %c%==%N% (set T=C&set L=R)else set T=R&set L=C
set/aG=%RANDOM%*5/32768+1
set/a%T%%G%-=%N%
for %%a in (C R)do set %%a=0&for %%b in (1 2 3 4 5)do (if !%%a%%b! LEQ 0 set %%a%%b=0
set/a%%a+=!%%a%%b!)
if %C% NEQ 0 if %R% NEQ 0 goto :a
echo !T!+&echo !L!-

要求是在打印状态下该值绝不能显示低于0的值。在显示的示例中,我做了同样的事情。
kirbyfan64sos 2015年

0

Javascript:410

function x(l){var t=this,o=t.p={n:l||"C",h:[50,50,50,50,50],s:function(){return o.h.reduce(function(a,b){return a+b})},r:function(){console.log(o.n+' '+o.h.join(' '))},d:function(m){while(o.h[z=~~(Math.random()*5)]<1){}o.h[z]=m>o.h[z]?0:o.h[z]-m}};o.r()}q=[new x(),new x('R')];while((c=q[0].p.s()>0)&&q[1].p.s()>0){q[(z=~~(Math.random()*10))%2].p.d(z);q[0].p.r();q[1].p.r()}console.log(c?'C+\r\nR-':'R+\n\rC-')

0

八度,182177158字节

145:

t=repmat(50,5);while prod(any(t))d=ceil(rand*10);c=2-mod(d,2);r=ceil(rand*5);t(r,c)-=d;t.*=t>0;end;p=2*any(t,1);['C-';'R+';'C+';'R-'](1+p:2+p,:)

我放弃检查角色射击是否大于零-这仅在我们被迫每转一次显示状态时才有意义-在这里,我们只是从RNG中随机跳过一个随机数,使其更加随机。

此外,已取代

t=max(0,t)

较短

t.*=t>0


[注意-它正在打印'C + R-'而没有换行符-它已固定在145字节版本中]

158:

t=repmat(50,5);while prod(any(t))d=ceil(rand*10);c=2-mod(d,2);do r=ceil(rand*5);until t(r,c);t(r,c)-=d;t=max(0,t);end;p=4*any(t,1);disp('C-R+C+R-'(1+p:4+p))

已脱胶:

t=repmat(50,5);               #only first two columns (cops, robbers) relevant
while prod(any(t))
    d=ceil(rand*10);
    c=2-mod(d,2);
    do r=ceil(rand*5);until t(r,c);
    t(r,c)-=d;
    t=max(0,t);
end;
p=4*any(t,1);
disp('C-R+C+R-'(1+p:4+p))

我改repmat(50,5,2)repmat(5)-所以我们有5x5矩阵,而不是现在的5x2(另外3列不影响算法)。我还找到了一种压缩输出的方法。

177:

t=repmat(50,5,2);while prod(sum(t))d=ceil(rand*10);c=2-mod(d,2);do r=ceil(rand*5);until t(r,c);t(r,c)-=d;t=max(0,t);end;if sum(t)(1)printf "C+\nR-\n";else printf "C-\nR+\n";end

已脱胶:

t=repmat(50,5,2);
while prod(sum(t))
    d=ceil(rand*10);
    c=2-mod(d,2);                  #cops or robbers affected?
    do r=ceil(rand*5);until t(r,c);
    t(r,c)-=d;
    t=max(0,t);
end
if sum(t)(1)
    printf "C+\nR-\n"
else
    printf "C-\nR+\n"
end

基本上,我们创建一个5x2矩阵,其中第一列是警察,第二列是强盗:

t =
50     50
50     50
50     50
50     50
50     50
[cops] [robbers]

sum当应用一个参数时,该函数按列求和,因此最初是:

250    250

当其中之一达到零时,prod(sum(t))评估结果为零,从而打破了循环。然后,我们可以检查谁赢得了检查,其列的总和为零。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.