두 생물 사이의 전투를 시뮬레이션


16

용감한 코드 골퍼를 환영합니다! 오늘 당신은 고블린과 엘프 사이의 큰 전투 가운데 서있을 것입니다!

    goblin attacks elf!
    elf dodges!
    elf attacks goblin!
    elf hits goblin for 13 damage!
    goblin has 37 health left.
    goblin attacks elf!
    goblin hits elf for 1 damage!
    elf has 49 health left.
    elf attacks goblin!
    elf hits goblin for 19 damage!
    goblin has 18 health left.
    goblin attacks elf!
    goblin hits elf for 26 damage!
    elf has 23 health left.
    elf attacks goblin!
    elf hits goblin for 20 damage!
    goblin has been slain!

도전

당신의 도전은 위와 같은 전투를 시뮬레이션하는 것입니다. 다음과 같은 형식으로 입력을받습니다.

creatureName health strength defense accuracy agility

예를 들어, 고블린과 엘프의 전투는 다음과 같습니다.

goblin 50 40 35 3 2 elf 50 35 30 4 5

첫 번째와 두 번째 생물은 교대로 공격합니다.

  • 'creatureName이 otherCreatureName을 공격합니다!'를 인쇄합니다.
  • 생물이 피하는 것을 확인하십시오. 생물은 (공격 시간 rand ()를 2로 나눈 값)이 (공격자의 정확도 시간 rand ())보다 클 경우 공격을 피합니다.
    • 생물이 피하다면 'creatureName 피하다!'를 인쇄하십시오.
    • 그렇지 않으면 (공격자의 강도 시간 rand ())와 (수 비자의 방어 시간 rand ()를 2로 나눈 값)을 빼서 처리 한 피해를 계산합니다. 최소 피해는 1입니다. 인쇄 'creatureName이 (x) 피해를 위해 다른 CreatureName에 충돌합니다!' 그런 다음 'creatureName의 건강 상태가 (x) 남아 있습니다.'를 인쇄하십시오. 생물의 체력이 0 이하인 경우를 제외하고는
      • 생물의 체력이 0 이하인 경우 'creatureName이 사망했습니다!'를 인쇄하십시오. 프로그램을 종료하십시오.

규칙

  • 가장 짧은 코드가 승리합니다.
  • 말 그대로 'creatureName'을 인쇄하지 말고 생물의 이름으로 바꾸십시오. '(x) 피해'또는 '(x) 건강;'을 인쇄하지 마십시오. 실제 금액으로 교체하십시오. (일부 사람들은 규칙을 구부리 는 데 매우 창의적 이기 때문에 이것을 지정해야합니다 . : P)

2
민첩성과 방어력을 절반으로 줄여 스펙을 복잡하게 만드는 이유는 무엇입니까?
피터 테일러

@Peter 그렇지 않으면 전투가 너무 오래 걸렸기 때문입니다.
손잡이

2
내 요점은 : 입력을 예를 들어 goblin 50 40 18 3 2 elf 50 35 15 4 5?
피터 테일러

@Peter Meh, 방금 너무 이상해 보였습니다. 왜 방어가 훨씬 낮을까요? 어쨌든 퍼즐입니다. P
Doorknob

'creatureName에 (x)의 건강이 남아 있는지 여부는 확실하지 않습니다.' 마지막 생물 (생물이 죽었을 때)에 인쇄되어야하며, (x)가 항상 0이어야하거나 음수 일 수 있다면 (필자가 아니라고 가정)
전염병 전문가

답변:


4

APL ( 249 (244) 242)

이번에는 절차 스타일이므로 (Dyalog에서) 편집기 창에 붙여 넣으십시오. 이름을 지정했습니다 G(첫 번째 줄은 이름입니다. 편집기 창에 표시되므로 계산해야하므로 포함 시켰습니다).

지
⎕ML ← 3
DA ← {(⊂ ↑ ⍵), ⍎¨1 ↓ ⍵} ¨ ↓ 2 6⍴A⊂⍨ ''≠ A ← ⍞
→ 5
⎕ ← (↑ D) '닷지!'
AD ← DA
⎕ ← (↑ A) '공격', '!', ⍨ ↑ D
→ 4 / ⍨> /? A [6], D [5]
⎕ ← A [1], 'hits', D [1], 'for', 'damage!', ⍨D [2]-← 1⌈-/? A [3], ⌈D [4] ÷ 2
→ 12 / ⍨D [2] ≤0
⎕ ← D [1], 'has', D [2], '건강이 남았습니다!'
→ 5
⎕ ← D [1], '살해되었습니다!'

(편집 : 줄 레이블 대신 숫자 GOTO를 사용했습니다. 최소한 Dyalog에서 레이블을 정의하는 모든 항목 이 줄 번호로 X:설정 X되어 있으므로 숫자를 직접 사용할 수도 있습니다.)


6

펄, 254 + 1

for((@a[0..5],@b)=split;$a[1]>0;@c=@a,@a=@b,@b=@c){say"$a[0] attacks $b[0]!\n",rand$b[5]/2<rand$a[4]?do{($==rand($a[2])-rand$b[3]/2)<1and$==1;"$a[0] hits $b[0] for $= damage!\n$b[0] has ",($b[1]-=$=)>0?"$b[1] health left.":"been slain!"}:"$b[0] dodges!"}

perl -nM5.010(또는 perl -nE '<code>')로 실행하십시오 . 당 메타-n하나 개 추가 문자로 전환 계산됩니다. 이 코드에는 $=을 저장하기 위해 Damage 변수로 사용하는 것을 제외하고는 멋진 골프 트릭이 없습니다 int.

편집 : 이제 피해 계산이 정확하기를 바랍니다.


6

커피 스크립트 (454) (432)

b결과를 얻으려면 문자열을 전달하십시오. 그래픽 애니메이션 출력을 갖는 것이 더 재미있을 것이라고 생각했기 때문에 데모를 모았습니다. 입력 상자를 변경하여 통계와 이름을 변경하십시오. 비공식 Google 이미지 API 인 jpg.to 의 사진

슈퍼 액션 데모

전투 시뮬레이터

b=(s)->
 r=Math.random
 p=s.split ' '
 n=p.map Number
 l=''
 o=(x...)->l+=x.join(' ')+'!\n'
 while 1|i=!i
  c=(x)->n[i*6+x]*r()
  d=(x)->n[(i||6)+x]*r()
  t=->d(4)/2>c 5
  h=->Math.max c(2)-d(3)/2,1
  a=p[i*6]
  b=p[6+i*-6]
  o a,'attacks',b
  if c(5)/2>d 4
   e=Math.ceil h()
   q=n[(i||6)+1]-=e
   o a,'hits',b,'for',e,'damage'
   o b,'has',q,'health left'if q>0
  else
   o b,'dodges'
  if q<1
   o b,'has been slain'
   break
 l

추천 입력 (자신의 제안) :

charmander 50 40 25 3 2 bulbasaur 90 30 40 4 5
voldemort 9999 10 5 1 1 batman 20 50 10 1010 30

와 대단해! : 나는 두 가지를 받아 들일 수 있다면 DI는이 답변을 받아 들일 것입니다,하지만 난 짧은 허용 할 것이라고 규정했다, 나는 단 하나의 대답 :( +1 그래서 받아 들일 수 그리고. voldemort 9999하하 : D
손잡이

@Doorknob, 추가 보너스로, 당신은 같은 숫자를 줄 수 10e42있지만 브라우저가 멈출 수 있습니다 ...
Brigand

6

루비, 292 (264)

v=$*
def p*a;puts a*' 'end
loop{a,b=v[0],v[6]
w=v.map &:to_i
p a,:attacks,b+?!
w[11]*rand/2>w[4]*rand ? (p b,:dodges!):(h=v[7]=w[7]-=d=[rand(w[2])-rand(w[9])/2,1].max
p a,:hits,b,:for,d,:damage!
p b,:has,h<1?"been slain!":"#{h} health left."
h<1&&exit)
v.rotate!6}

내 첫 번째 코드 골프 항목; 그 메소드 정의 파싱이 저를 넘어서는 방법 :)

명령 행 매개 변수 (예 :)에서 입력을 읽는 것이 괜찮 ruby battle.rb goblin 50 40 35 3 2 elf 50 35 30 4 5습니까?

이데 오네


예, 괜찮습니다.
Doorknob

5

자바 스크립트; 347 341 333

항상 그렇듯이, 나는 내 자신의 해결책으로 시작할 것입니다.

for(m=prompt().split(' '),r=Math.random,a=console.log,c=0,d=6;;){if(a(m[c]+' attacks '+m[d]+'!'),r()*m[c+4]>r()*m[d+5]/2){if(a(m[c]+' hits '+m[d]+' for '+(h=Math.max(~~(r()*m[c+2]-r()*m[d+3]/2),1))+' damage!'),(m[d+1]-=h)<1){a(m[d]+' has been slain!');break}a(m[d]+' has '+m[d+1]+' health left.')}else a(m[d]+' dodges!');t=c;c=d;d=t}

편집 : 분명히 console.log일부 브라우저에서 변수 나누기에 할당 하면 함수 선언이있는 동일한 코드가 대신 있습니다.

for(m=prompt().split(' '),r=Math.random,a=function(x){console.log(x)},c=0,d=6;;){if(a(m[c]+' attacks '+m[d]+'!'),r()*m[c+4]>r()*m[d+5]/2){if(a(m[c]+' hits '+m[d]+' for '+(h=Math.max(~~(r()*m[c+2]-r()*m[d+3]/2),1))+' damage!'),(m[d+1]-=h)<1){a(m[d]+' has been slain!');break}a(m[d]+' has '+m[d+1]+' health left.')}else a(m[d]+' dodges!');t=c;c=d;d=t}

나는 그것을로 변경하려고 생각 alert했지만 그것은 악할 것입니다 : P


나는를 얻을 수 Uncaught TypeError: Illegal invocation의 때문에 a=console.log. console예를 들어 객체를 컨텍스트 로 바인딩하지 않아도 a=console.log.bind(console)됩니까?
C5H8NNaO4

@ C5H 흠, 이상하다. 그것은 나를 위해 작동합니다.
Doorknob

방금 Firefox, Safari, Chrome에서 확인했습니다. Firefox에서 작동합니다. =) Chrome에서 위를
알려주고

@ C5H :( 어쩌면 내가 그것을 대체 할 수 alert는 있지만 매우 성 가실 것입니다 : P
Doorknob

: P 예는 참으로 성가신 것,하지만 적어도 그것은 "6"문자를 저장하고 피할 것 형식 오류 =)하지만 난 그 확인은, 적어도이 =) 파이어 폭스에서 실행되는 것 같아요
C5H8NNaO4

4

파이썬 : 393

나는 3을 가졌다면 조금 더 세게 눌렀을 것입니다 print = p.

393 :

from random import randrange as r
x = input().split()
t=range
a,b=6,0
for i in t(1,6)+t(7,12):x[i]=int(x[i])
while x[b+1] > 0:
 a,b=b,a;print x[a]+" attacks "+x[b]
 if r(x[a+5]/2)>r(x[b+5]):print x[a]+' dodges!';continue
 d=max(r(x[a+2])-r(x[b+3]/2),1);print x[a]," hits ",x[b]," for ",d," damage!";x[b+1]-=d
 if x[b+1]>0:print x[b]," has ",x[b+1]," health left."
print x[b]," has been slain"

399 :

from random import randrange as r
x = raw_input().split()
t=range
a,b=6,0
for i in t(1,6)+t(7,12):x[i]=int(x[i])
while x[b+1] > 0:
 a,b=b,a;print x[a]+" attacks "+x[b]
 if r(x[a+5]/2) > r(x[b+5]):print x[a]+' dodges!';continue
 d=max(r(x[a+2])-r(x[b+3]/2),1);print x[a]," hits ",x[b]," for ",d," damage!";x[b+1]-=d                        if x[b+1]>0:print x[b]," has ",x[b+1]," health left."
print x[b]," has been slain"

사람들이 루프 상태가 양호하면 대상이 건강 상태보다 낮은 지 확인할 필요가 없다고 생각합니다.


이중 상태 점검이 추가 콘솔보다 짧기 때문에 상태를 두 번 확인하고 루프 헤더에서 전투를 끝내고 루프에서 "지운 상태"또는 "적중 ..."을 인쇄합니다
.log

4

자바 스크립트 : 340 306

339 :

for(m=Math.random,a=prompt().split(" "),c=[a,a.splice(6)],e;0<+c[0][1]&&0<+c[1][1];)c.reverse(),console.log(c[0][0]+" attacks "+c[1][0]+"!\n"+(c[0][4]*m()<c[1][5]*m()/2?c[1][0]+" dodges!":c[0][0]+" hits "+c[1][0]+" for "+(e=1+(c[0][2]*m()-c[1][3]*m()/2|0))+" damage!\n"+c[1][0]+" has "+(0>(c[1][1]-=e)?"been slain!":c[1][1]+" health left.")))

306 :

for(var m=Math.random,a=prompt().split(" "),b=a.splice(6),d,e;0<+a[1]&&0<+b[1];d=a,a=b,b=d)console.log(a[0]+" attacks "+b[0]+"!\n"+(a[4]*m()<b[5]*m()/2?b[0]+" dodges!":a[0]+" hits "+b[0]+" for "+(e=a[2]*m()-b[3]*m()/2|0,e<=0?e=1:e)+" damage!\n"+b[0]+" has "+(0>(b[1]-=e)?"been slain!":b[1]+" health left.")))

샘플 출력 :

goblin attacks elf!
elf dodges!
elf attacks goblin!
elf hits goblin for 21 damage!
goblin has 29 health left.
goblin attacks elf!
elf dodges!
elf attacks goblin!
elf hits goblin for 15 damage!
goblin has 14 health left.
goblin attacks elf!
goblin hits elf for 1 damage!
elf has 49 health left.
elf attacks goblin!
elf hits goblin for 16 damage!
goblin has been slain!   

메모 수정 : +1 문자, "!" "dodges"이후
Oh와 나는 "Sample output"뒤에 실제로 출력하는 것을 잊었다.
@tbodt가 제안한 것처럼 헤더를 JavaScript로 변경했다.


사람들을 혼란스럽게하지 않기 위해 JavaScript라고 부르지 않겠습니까?
tbodt

@tbodt 내가 대신 자바 스크립트로 변경) = 사람들을 혼란 것이라고 생각하지 않았다
C5H8NNaO4

3

R : 387 자

a=scan(,"");i=as.integer;r=runif;C=cat;X=data.frame(i(a[2:6]),i(a[8:12]));z=1;Y=c(a[1],a[7]);repeat{p=1+z%%2;n=X[,p];m=X[,-p];N=Y[p];M=Y[-p];C(N,"attacks",M,"\n");if(r(1)*n[5]<r(1)*m[5]/2){C(M,"dodges!\n")}else{C(N,"hits",M,"for",d<-max(round(n[2]*r(1)-m[3]*r(1)/2),1),"damages!\n");h=max(m[1]-d,0);if(h){C(M,"has",X[1,-p]<-h,"health left\n")}else{C(M,"has been slained!");break}};z=z+1}

또는 들여 쓰기 및 주석으로 완전히 개발하여 다음과 같은 사항을 명확하게합니다.

a=scan(,"")                        # Read stdin as character vector
i=as.integer
r=runif
C=cat
X=data.frame(i(a[2:6]),i(a[8:12])) # Data frame with opponents stats
z=1                                # Turn counter 
Y=c(a[1],a[7])                     # Vector of opponents name
repeat{                            # shorter than while(T)
    p=1+z%%2                       # R indexing starts with 1 not 0
    n=X[,p]                        # Attacking opponent stats
    m=X[,-p]                       # Defending opponent stats
    N=Y[p]                         # Attacking opponent name
    M=Y[-p]                        # Defending opponent name
    C(N,"attacks",M,"\n")          # By default, cat separates elements with a space
    if(r(1)*n[4]<r(1)*m[5]/2){
        C(M,"dodges!\n")
    }else{
        C(N,"hits",M,"for",d<-max(round(n[2]*r(1)-m[3]*r(1)/2),1),"damages!\n")
        h=max(m[1]-d,0)            # Health after the strike
        if(h){                     # If health is not 0
            C(M,"has",X[1,-p]<-h,"health left\n")
        }else{                     # If it is
            C(M,"has been slained!")
            break
            }
    }
    z=z+1
}

2

C # -464 453 자

이틀 밤이 지나면 다른 항목에 가까워 질 수 없습니다 (C #에는 놀라운 일이 아닙니다). 아직도 개선의 여지가 있다고 생각합니다. 특히 영리한 트릭은 없습니다.

using System;using System.Linq;class P{static void Main(string[]a){int D,h=1,z=6;
var n=a.Select(x=>int.TryParse(x,out D)?D:0).ToList();var r=new Random();Func<int>
R=()=>r.Next(101);for(;h>0;z=z>0?0:6){D=(n[8-z]*R()-n[3+z]*R()/2)/100;var d=n[5+z]
*R()/2>n[10-z]*R();h=d?h:n[1+z]-=D=D<1?1:D;Console.Write("{0} attacks {1}!\n"+(d?
"{1} dodges!\n":"{0} hits {1} for {2} damage!\n")+(d?"":"{1} has {3}\n"),a[6-z],a
[z],D,h>0?h+" health left.":"been slain!");}}}

댓글 :

using System;
using System.Linq;
class P
{
    static void Main(string[] a)
    {
        int D, // string to int parsing and attack damage 
            h = 1, // health 
            z = 6; // index

        // painful requirement to convert the input strings to integers
        var n = a.Select(x => int.TryParse(x, out D) ? D : 0).ToList();

        // set up a function to return a new random number
        var r = new Random();
        Func<int> R = () => r.Next(101);

        // we'll exit the loop when the defender's health (h) is <= 0.
        // z is used as an index offset to get values out of the list, it flips between 0 an 6 each round
        for (; h > 0; z = z > 0 ? 0 : 6)
        {
            // calculate damage
            D = (n[8 - z] * R() - n[3 + z] * R() / 2) / 100;

            // see if defender dodges
            var d = n[5 + z] * R() / 2 > n[10 - z] * R();

            // subtract health from defender if necessary. store health of defender in h
            h = d ? h : n[1 + z] -= D = D < 1 ? 1 : D;

            // print the round
            Console.Write(
                "{0} attacks {1}!\n" + (d ? "{1} dodges!\n" : "{0} hits {1} for {2} damage!\n") + 
                (d ? "" : "{1} has {3}\n"), a[6 - z], a[z], D, h > 0 ? h + " health left." : "been slain!");
        }
    }
}

1

파이썬 3, 314

from random import*
r=random
p=print
I=input().split()
H=1
while H>0:s,a,H,D,G=map(int,I[2:5:2]+I[7::2]);N=I[6];p(I[0],"attacks",N+"!");I=I[6:]+I[:6];X=max(int(s*r()-D*r()/2),1)*(G*r()/2<a*r());I[1]=H=H-X;X<1and p(N,"dodges!")or p(I[6],"hits",N,"for",X,"damage!\n"+N,"has",["been slain!","%s health left."%H][H>0])
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.