Cảnh sát và bọn cướp


11

Mọi người luôn muốn thực hiện Trò chơi cuộc sống của Conway. Thật là chán! Hãy làm cảnh sát và cướp thay!

Bạn sẽ có hai đội: cảnh sát và tên cướp. Mỗi đội có 5 thành viên với 50 sức khỏe mỗi người. Chương trình sẽ lặp liên tục. Mỗi lần lặp lại, những điều sau đây sẽ xảy ra:

  • Đối với mỗi đội, in chữ cái đầu tiên ( Ccho cảnh sát, Rcho bọn cướp), một khoảng trắng, danh sách được phân tách bằng dấu cách của HP của các thành viên và dòng mới. Đây là tình trạng của các đội. Sau khi cả hai được thực hiện, in một dòng mới. Ví dụ, đây là những gì nó có thể trông giống như vòng đầu tiên:

    C 50 50 50 50 50
    R 50 50 50 50 50
    
  • Chọn một số ngẫu nhiên từ 1 đến 10 (bao gồm cả 1 và 10). Chúng tôi sẽ gọi số N. Nếu Nlà chẵn, những tên cướp thua vòng này; nếu lẻ, cảnh sát mất.

  • Chọn một thành viên ngẫu nhiên trong đội thua cuộc có HP lớn hơn 0 và trừ NHP. HP của các thành viên sẽ không bao giờ xuất hiện dưới 0 trên trạng thái.

  • Khởi động lại vòng lặp.

Trò chơi kết thúc khi tất cả các thành viên của một đội mất hết HP. Sau đó, phần sau sẽ được in nếu cảnh sát thắng:

C+
R-

và nếu bọn cướp thắng:

R+
C-

Đây là mã golf, vì vậy số lượng nhân vật ngắn nhất sẽ thắng.

Đây là một triển khai mẫu trong 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+'

Trớ trêu nhỏ: trong số hơn 3176 câu hỏi trên trang web này, không quá 11 câu hỏi được gắn thẻ game-of-life.
Sanchise

3
@sanchises Trớ trêu kéo dài: và 14 được gắn thẻ cops-and-robbers!
Runer112

@sanchises Tôi chủ yếu đề cập đến lập trình nói chung (ví dụ: "Giúp tôi với! Tôi đang cố gắng thực hiện Trò chơi cuộc sống của Conway!") ... nhưng điều đó vẫn khá mỉa mai.
kirbyfan64sos

@ kirbyfan64sos Tôi biết (đã ở đó, đã làm điều đó), nhưng đây chính xác là loại trang web mà mọi người đi sau khi họ đã triển khai GoL và muốn nhiều hơn nữa ... Dù sao, có lẽ tôi sẽ đi đến đây trong> <> , hãy xem nếu tôi có thể làm điều đó.
Sanchise

Tôi đã xóa thẻ CnR một lần nữa. Xung quanh đây, thẻ này có một ý nghĩa rất cụ thể và mô tả các thách thức trong đó thực sự có hai bên (không nhất thiết phải rời rạc) cạnh tranh với nhau ở một số nhiệm vụ nhất định (hãy xem xét các thách thức khác với thẻ đó).
Martin Ender

Câu trả lời:


3

CJam, 86 byte

Tôi đến bữa tiệc muộn một chút, nhưng tôi mang món quà của CJam! ... Này, đợi đã, bạn sẽ đi đâu?

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

Hãy thử trực tuyến.

Giải trình

Khi các câu hỏi yêu cầu mô phỏng một quy trình đơn giản, đây là một câu trả lời tương đối đơn giản. Có lẽ một lựa chọn thú vị mà tôi đưa ra là giữ sức khỏe của cả hai đội xen kẽ trong cùng một danh sách. Chi phí này là 3 byte để chuyển đổi thành hai danh sách riêng biệt, cần thiết cho cả hiển thị và kiểm tra sức khỏe nếu một đội bị mất. Nhưng (tôi nghĩ) điều này được tạo ra bởi 2 byte được lưu trong quá trình khởi tạo và logic xử lý thiệt hại đơn giản hơn nhiều.

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)])

Ngoài ra tại sao rep(which(x>0),2)như trái ngược với chỉ which(x>0)?
MickyT

1) Tôi đang đếm các ký tự EOL, không phải là ký tự cuối cùng. 2) sum(R*C)sum(R)*sum(C)không giống nhau. Ví dụ: bạn sẽ không muốn thoát nếu C = c (0,0,0,10,10) và R = c (10, 10, 10, 0, 0). Trong trường hợp đó, tôi tiết kiệm bằng cách gán S=sum. 3) Vấn đề với samplelà nếu đối số đầu tiên là một số duy nhất, ví dụ sample(5, 1), thì nó sẽ giống như thực hiện sample(1:5, 1): thay vì luôn luôn trả về 5, nó sẽ trả về bất kỳ số nào từ 1đến 5. Vì vậy, sample(rep(x, 2), 1)mẹo của tôi là luôn luôn chọn một số trong số xngay cả trong trường hợp length(x)là khi 1.
flodel

Xin lỗi tôi xấu ... Rõ ràng là không đủ cà phê. Cảm ơn đã giải thích về thủ thuật rep (). Tôi nghĩ rằng phải có một lý do, chỉ không thể nhìn thấy nó
MickyT

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
∇

Giải trình:

  • S←2 5⍴50: ở đầu, được đặt thành Sma trận 5 nhân 2 trong đó mỗi giá trị là 50. Hàng trên cùng của ma trận đại diện cho cảnh sát, hàng thứ hai đại diện cho kẻ cướp.
  • J←∨/S>0: cho mỗi hàng của ma trận, lưu trữ Jxem có bất kỳ HP nào lớn hơn không.
  • →6/⍨~∧/J: nếu không phải cả hai đội đều có thành viên sống, hãy nhảy đến dòng 6. (kết thúc)
  • ⎕←3↑'CR',0⌈S: đối với mỗi giá trị trong ma trận, xuất tối đa của nó và 0, thêm 'C' vào hàng đầu tiên và 'R' cho hàng thứ hai và thêm dòng thứ ba (trống).
  • N←?10: lấy một số ngẫu nhiên trong khoảng [1,10] và lưu nó vào N.
  • L←1+~2⊤N: đặt L(đội thua cuộc) thành 1nếu số đó là số lẻ và 2nếu là số chẵn.
  • M←(0<S[L... ;])/⍳5: lấy chỉ số của các thành viên còn sống trong đội đó và lưu trữ chúng trongM
  • M[?⍴M... ]: chọn một giá trị ngẫu nhiên từM
  • S[L;M... ]-←N: trừ đi Ngiá trị của thành viên nhóm đã chọn
  • →2: nhảy đến dòng 2 (bài kiểm tra cho các thành viên còn sống)
  • ⎕←'CR',⍪'+-'⌽⍨J⍳0: xuất trạng thái cuối cùng, đặt +phía trước đội chiến thắng và -phía trước đội thua cuộc.

Sản lượng mẫu


1

Ruby, 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

Toán học, 246 241 byte

Có lẽ có thể được đánh gôn hơn nữa ...

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 byte

Tôi mới chơi golf và mặc dù thử thách này sẽ đủ dễ để thử. Vì vậy, đây là những gì tôi đã đưa ra.

<?$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";}}?>

Với lời giải thích:

<? 
$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
}
?>

Tôi không phải là người dùng PHP, nhưng tôi đoán rằng có thể bạn sẽ cắt giảm một vài ký tự bằng cách xóa != 0và thay thế kiểm tra bằng 0 bằng toán tử không ( !array_sum($r)).
kirbyfan64sos

@ kirbyfan64sos không hoạt động
Timo

Oh. Trong hầu hết các ngôn ngữ, nó sẽ.
kirbyfan64sos

1

C, 390 384 371 byte

Golf đầu tiên của tôi, nếu có bất kỳ cải tiến có thể, chỉ cần cho tôi biết :)

phiên bản đánh gô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();}N=(x=w<1?'C':'R')-w*15;printf("\n\n%c+\n%c-",x,N);}

phiên bản hơi vô căn cứ:

#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);
}

chỉnh sửa: Tôi tìm thấy một cách để rút ngắn nó một chút và sửa một lỗi nhỏ


Một cải tiến nhỏ: bạn có thể thay thế các vòng lặp (ví dụ for(j=0;j<10;j++)) bằng một phiên bản ngắn hơn ( for(j=10;--j;)).
kirbyfan64sos

Bạn hoàn toàn đúng, "sửa" cái này và một vài thứ khác, cảm ơn.
Metaforce

0

Mẻ - 396 byte

Tôi không biết nếu điều này về mặt kỹ thuật - vì thực tế nó không chọn một thành viên ngẫu nhiên trong đội có sức khỏe lớn hơn 0 . Nó chỉ chọn một thành viên ngẫu nhiên và nếu phép trừ sức khỏe tạo ra một số nhỏ hơn 0, thì số đó trở thành 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!-

Yêu cầu là giá trị không bao giờ hiển thị dưới 0 trên trạng thái in. Tôi đã làm điều tương tự trong ví dụ tôi đã chỉ ra.
kirbyfan64sos

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

Octave, 182 177 158 145 byte

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,:)

Tôi đã từ bỏ việc kiểm tra xem liệu nhân vật có cao hơn không - điều này chỉ có ý nghĩa nếu chúng tôi buộc phải hiển thị trạng thái trong mỗi lượt - ở đây chúng tôi chỉ bỏ qua một số ngẫu nhiên từ RNG, làm cho nó trở nên ngẫu nhiên hơn.

Ngoài ra, thay thế

t=max(0,t)

với ngắn hơn

t.*=t>0


[lưu ý - đó là in 'C + R-' mà không có dòng mới - nó được sửa ở phiên bản 145 byte]

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))

Bị thoái hóa:

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))

Tôi đã thay đổi repmat(50,5,2)thành repmat(5)- vì vậy chúng tôi có ma trận 5x5 thay vì 5x2 bây giờ (3 cột bổ sung không ảnh hưởng đến thuật toán). Tôi cũng tìm thấy một cách để nén đầu ra.

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

Bị thoái hóa:

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

Về cơ bản, chúng tôi tạo ra ma trận 5x2, trong đó cột đầu tiên là cảnh sát và cột thứ hai là kẻ cướp:

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

Các sumchức năng khi một đối số áp dụng làm cho một số tiền bằng cột, do đó, nó ban đầu:

250    250

Khi một trong số chúng đạt đến 0, ước tính prod(sum(t))bằng 0 sẽ phá vỡ vòng lặp. Sau đó, chúng ta có thể kiểm tra xem ai thắng kiểm tra xem tổng của cột bằng không.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.