アリスとボブは戦います


24
  • アリス(A)とボブ(B)は戦いをすることにしました。
  • 各戦闘員の体力は10です。
  • 彼らは、ダメージのために6面のサイコロを振って交代します。
  • そのダメージは相手のヘルスから取り除かれます。
  • 最終的に、アリスまたはボブのいずれかが敵を打ち負かします。

戦いの様子を見せてください。実行されたアクションのこれらのコードを出力します。

攻撃

B a A    
^ Combatant
  ^ Action (attack)
    ^ Target

ロール

B r 4
^ Combatant
  ^ Action (roll)
    ^ Value

健康の変化

A h 6
^ Combatant
  ^ Attribute (health)
    ^ Value   

勝つ

A w 
^ Combatant
  ^ Action (win)

出力例:

A a B
A r 4
B h 6
B a A
B r 6
A h 4
A a B
A r 6
B h 0        
A w

ルールは次のとおりです。

  • 任意の言語で書きます。
  • サイコロを1回振ると、数字1、2、3、4、5、または6のいずれかになる確率が等しくなります。
  • アリスは常に始まります(ボブは昔ながらの方法で、騎士道的です)。
  • 各ターンのアクションを出力します。
  • 攻撃、ロール、ダメージ、および勝利のアクションを報告する必要があります。
  • 戦闘員は大文字、アクションは小文字です。
  • 一貫して同じ結果を生成してはなりません。
  • 出力戦闘員、アクション、および値の間に少なくとも1つの空白文字が必要です。
  • 勝利アクションは、対戦相手の体力が0以下の場合に発生します。
  • アクションのすべての部分は同じ行になければなりません。
  • 行ごとに1つのアクションが必要です。
  • 少ないバイトが勝ちます。

どうぞ!


9
アリス(A)とボブ(B)という名前は、ネットワークセキュリティクラスへのフラッシュバックを与えてくれます。俳優アリス(A)は、...等...キーとボブ(B)にパケットを送信します
マジックタコ壺

21
@MagicOctopusUrnそれが彼らです。彼らは通常、通信しようとしています。悲しいことに、コミュニケーションが崩壊すると、しばしば対立が起こります。
AJFaraday

7
私は...これらは単純回だった...私たちはマロリーから私たちの秘密を非表示にする方法を把握しようとしていた日を欠場
ボブ・

4
@Bob Malloryは本当に気が散るものです。気をつけなければならないイブです。
AJFaraday

3
@ msh210よく、コードゴルフの重要な詳細は誰もが同じ挑戦をすることです、しかし、ここに論理があります:-ダンジョンとドラゴンをプレイしているなら、あなたは「私はゴブリンを蹴るつもりです」と言うでしょう、そしてあなたはdロールを有効にして、ロールの結果を実装します。ロールの目的が誰にもわからない場合、ロールは意味がありません。
AJFaraday

回答:


5

05AB1E、49バイト

"BaABr0Aha"S3ô»D„AB‡[6LΩ©Tǝ¤H®-©16ǝ=®0‹#s]н…ÿ w?

オンラインでお試しください!

説明

"BaABr0Aha"                                        # push the initial state of B
           S                                       # split to list of characters
            3ô                                     # divide into 3 parts
              »                                    # join each part on space and all on nl
               D„AB‡                              # make a copy with A and B inverted
                     [                             # start a loop
                      6LΩ©                         # pick a random number in [1 ... 6]
                          Tǝ                       # insert at position 10 of the string
                            ¤H                     # get the last char of the string and
                                                   # convert from hex
                              ®-©                  # subtract the random number
                                 16ǝ=              # insert at position 16 and print
                                     ®0‹#          # if the hp is less than 0, break
                                         s         # swap the other string to the stack top
                                          ]        # end loop
                                           н…ÿ w?  # print the winner

13

Python 3、131バイト

x,y="AB"
from random import*
X=Y=10
p=print
while X>0:p(x,"a",y);d=randint(1,6);p(x,"r",d);Y-=d;p(y,"h",Y);x,y,X,Y=y,x,Y,X
p(y,"w")

オンラインでお試しください!

officialaimmのおかげで-8バイト
-ChooJeremyのおかげで-2バイト


5
事前定義により、p=print約8バイト節約できます。
officialaimm

この時点でyが常に勝つため(ループ内でXのみが攻撃され、後でYにスワップされます)、yが失われたかどうかを確認する必要はありません。- ChooJeremy - 口コミより
NoOneIsHere

@NoOneIsHereメッセージを送ってくれてありがとう:D
HyperNeutrino

randint(1,6)id(X+Y)//3%6+1分布は完全に均一ではありませんが、に置き換えることができます。
ヴィンセント

@Vincentルールを短くすることさえできなければ、ルールを曲げることに意味がありません
...-HyperNeutrino

7

C(gcc)146 141バイト

f(A,B,r,t,a,b){for(A=B=10;r=1+clock()%6,A*B>0;t=!t)printf("%c a %c\n%c r %u\n%c h %i\n",a=65+t,b=66-t,a,r,b,t?A-=r:(B-=r));printf("%c w",a);}

オンラインでお試しください!

デゴルフ:

f(A,B,r,t,a,b){
    for(A=B=10; //Initialize HP
        r=1+clock()%6, // Get the number of processor cycles the program has consumed. This is relatively random, so I call it good enough.
        A*B>0;t=!t) // Flip t for change of turns
        printf("%c a %c\n%c r %u\n%c h %i\n", // Print the turn
            a=65+t,b=65+!t,a,r,b, // 65 is ASCII for 'A', 66 for 'B'
            t?A-=r:(B-=r)); // Deduct the damage.
    printf("%c w",a); // Print the winner
}

2
を使用してバイトを保存できますa=65+t,b=66-tか?
moopet

A*B>0数バイト節約できます。
オリビエグレゴワール

A*Bさらに節約できますが、私は急いでいます。夕方

ダイスシーケンス{6,4,3,1,5}にバグが見つかりました。bはヘルス-4で勝ちます。このバグをデモするためにサイコロ計算機を変更したTIOを参照してください 。
GPS

@GPSありがとう、今それをパッチします。

7

Python 3、127バイト

これは@HyperNeutrinoの回答の改善であり、コメントに収まりません。以下の説明を参照してください。

x,y="AB"
s=id(0)
X=Y=10
p=print
while X>0:p(x,"a",y);s=s**7%~-2**67;d=s%6+1;p(x,"r",d);Y-=d;p(y,"h",Y);x,y,X,Y=y,x,Y,X
p(y,"w")

オンラインでお試しください!


より短いパイソンダイスロールの壮大な探求

TL; DR:RSA暗号化を使用することにより、標準のPythonサイコロを4バイト削ることができます。

標準のpythonダイスロール(32バイト)を少し短くできるかどうかを確認したかったのです。

from random import*;randint(1,6)

特に、id(x)プログラムに非決定論的な値をもたらすのは非常に便利です。私の考えは、この値を何らかの方法でハッシュして、実際のランダム性を作成することでした。私はいくつかのアプローチを試みましたが、そのうちの1つが成果を上げました:RSA暗号化

RSA暗号化は、その単純さにより、数バイトしか必要としませんm**e%n。次に、前の値を暗号化することにより、次のランダム値を作成できます。(e,n)キーが利用可能であると仮定すると、サイコロは22バイトで書くことができます

s=id(0);s=s**e%n;s%6+1

つまり、有効なRSAキーを定義するのに約10バイト必要です。ここでラッキーになりました。私の実験中、メルセンヌプライム M67を使用し始めたのは、後でメルセンヌがリストにM67を含むミス犯したことを認識するためだけです。それはの製品であることが判明p=193707721してq=761838257287。モジュラスを見つけました:

n=~-2**67

ここで、指数とチャーマイケルトーティエント (p-1)*(q-1)は互いに素である必要があります。幸いなことに、再び、n個のトーティエントを分割していない最初の素数は一桁長い7.ダイスロールは、次に使って書くことができる28バイト(4バイト以下の標準的なアプローチよりは):

s=id(0);s=s**7%~-2**67;s%6+1

M67の良い点の1つは、生成されるランダム値の66ビットが通常の64ビットRNGより多いことです。また、RSAを使用すると、現在の値を複数回復号化することで時間を遡ることができます。暗号化キーと復号化キーは次のとおりです。

Encryption: (7,                    147573952589676412927)
Decryption: (42163986236469842263, 147573952589676412927)

私は間違いなく統計や暗号の専門家ではないので、このRNGが「良いランダム性」の基準をチェックするかどうかはわかりません。私が書いた小さなベンチマーク別のRNGを使用して1〜6のダイスロールの発生の標準偏差を比較します。提案されたソリューションは他のソリューションと同じように機能するようです。


3
印象的な仕事!:)
HyperNeutrino


4

Java(JDK 10)、180バイト

v->{var r="";int p=0,H[]={10,10},h=0;for(;H[0]*H[1]>0;)r+=r.format("%3$c a %4$c%n%3$c r %d%n%4$c h %d%n",h+=Math.random()*6-h+1,H[p]-=h,p+65,(p^=1)+65);return r+(char)(66-p)+" w";}

オンラインでお試しください!

クレジット


1
Java 10にはvar?o.Ô私は本当に、とにかく...すぐに新しいスペックのいくつかを調査する必要がありますすることができますint型アレイに、チャーの配列を変更することにより、4バイトのゴルフ:v->{var r="";int P[]={65,66},p=0,H[]={10,10},h=0;for(;H[0]*H[1]>0;)r+=r.format("%3$c a %4$c%n%3$c r %d%n%4$c h %d%n",h+=Math.random()*6-h+1,H[p]-=h,P[p],P[p^=1]);return r+=P[p^1]+" w";}
ケビンCruijssen

1
@KevinCruijssenうん、Java 10にはvarがあります。さらに読む必要はありません。それは基本的に私たちのゴルファーが使用できる唯一の変更です。そして、私はあなたが提案することはできません:結果の最後の行を確認してください:の65 w代わりになりA wます それが私がint ...声明からそれを抽出した理由です:数バイトをゴルフに;-)
オリビエグレゴワール

1
@KevinCruijssenここでいくつかの例をコンパイルし
オリビエグレゴワール



3

Ruby122120 96 92 91バイト

f=->x=?A,y=?B,m=10,n=m{p [x,?a,y],[x,?r,r=1+rand(6)],[y,?h,t=n-r]
t<1?p([x,?w]):f[y,x,t,m]}

Asone Tuhidのおかげで1バイト節約できました

オンラインでお試しください!


1
もうRubyの方法さえ知らないようです;)
AJFaraday

「アクションのすべての部分が同じ行にある必要があります。」ただし、タブ文字で同じ最適化を行うことは可能でしょうか?
AJFaraday

@AJFaraday形式で行を出力することは受け入れられます["A", "a", "B"]か?もしそうなら、私はこの 96バイトのソリューションを持っています。
クリスチャンルパスク

1行に1つずつ出力される場合。それでいいはずです。
AJFaraday

-1あなたが交換した場合、バイト?(p [x,?w]):?p([x,?w]):
Asone Tuhid

3

Java 8、230バイト

v->{for(int h=104,a=h,x=0,y=1,A=10,B=A,r=0,t=0,T;a<119;)System.out.printf("%c %3$c %c%n",(x=a>h|A*B<1?x^1:x)+65,y=(a<98?t=r+=Math.random()*6-r+1:a>h?(T=x<1?A-=t:(B-=t))<0?0:T:A*B<1?-16:(x^1)+17)+48,a=a<98?114:a>h?104:A*B<1?119:97);}

注:Javaの回答はすでにかなり短いため、必ず投票してください!ただし、私はまったく異なるアプローチを使用しているため、投稿する価値があると考えました。

説明:

オンラインでお試しください。

v->{                     // Method with empty unused parameter and no return-type
  for(int h=104,         //  Temp integer with unicode for 'h' to save bytes
          a=h,           //  Second part (Action)
          x=0,           //  First part
          y=1,           //  Third part
          A=10,          //  Score player A, starting at 10
          B=A,           //  Score player B, starting at 10
          r=0,           //  Random dice-roll
          t=0,           //  Previous dice-roll
          T;             //  Temp integer
      a<119;)            //  Loop until there is a winner
     System.out.printf(  //   Print
      "%c %3$c %c,%n",   //    The three parts with spaces, and a new-line
      (x=                //    First part:
         a>h             //     If the previous action is 'r',
         |A*B<1?         //     or there is a winner:
           x^1           //      Change A→B or B→A
         :               //     Else:
          x)             //      A/B remains unchanged
       +65,              //     Add 65 to convert 0/1 to 65/66 (unicode values of A/B)
      (y=                //    Third part:
         (a<98?          //     If the previous action was 'a'
           t=r+=Math.random()*6-r+1
                         //      Roll the dice, and save it in `t`
          :a>h?          //     Else-if the previous action was 'r':
           (T=x<1?       //      If the first part changed to player A:
            A-=t         //       Subtract the previous dice-roll from A
           :             //      Else:
            (B-=t))      //       Subtract the previous dice-roll from B
           <0?           //      If this score is below 0:
            0            //       Use 0
           :             //      Else:
            T            //       Use this score
         :               //     Else (the previous action was 'h'):
          A*B<1?         //      Is there a winner:
           -16           //       Change the third part to a space
          :              //      Else:
           (x^1)+17)     //       Change the third part to the other player
       +48,              //     Add 48 to convert it to unicode
       a=                //    Second part:
         a<98?           //     If the previous action was 'a': 
          114            //      Change it to 'r'
         :a>h?           //     Else-if the previous action was 'r':
          h              //      Change it to 'h'
         :               //     Else (the previous action was 'h'):
          A*B<1?         //      If either score is 0:
           119           //       Use 'w'
          :              //      Else:
           97);}         //       Use 'a'


2

バッチ、174バイト

@set/aA=B=10
@set c=A
@set d=B
:g
@set/ar=%random%%%6+1,h=%d%-=r
@echo %c% a %d%
@echo %c% r %r%
@echo %d% h %h%
@if %h% gtr 0 set c=%d%&set d=%c%&goto g
@echo %c% w

説明:%変数参照は解析時に置換されます。これには2つの便利な利点があります。

  • %d%-=r(間接参照)rという名前の変数から減算しますd
  • set c=%d%&set d=%c% 単純なスワップです。

2

PHP 7.1:159バイト

<?php $A=$B=10;$t='AB';while($A>0&&$B>0){$a=$t[0];$b=$t[1];$d=rand(1,6);$$b-=$d;echo"$a a $b\n$a r $d\n$b h {$$b}\n";$t=strrev($t);}echo($A>0?'A':'B')." w\n";

ここでブラウザで実行してください!

PHP 5.6:156バイト

<?php $A=$B=10;$t='AB';while($A>0&&$B>0){list($a,$b)=$t;$d=rand(1,6);$$b-=$d;echo"$a a $b\n$a r $d\n$b h {$$b}\n";$t=strrev($t);}echo($A>0?'A':'B')." w\n";

ここでブラウザで実行してください!

PHP 5.6ソリューションのフォーマットとコメントは次のとおりです。

<?php
// Initialize both HP counters
$A = $B = 10;

// Set the turn order as a string (which 5.6 allows to be unpacked into a list)
$t = 'AB';

// Run this loop as long as both players have HP
while ($A > 0 && $B > 0) {
    // Unpack the turn string into $a and $b variables; on the first run, $a = 'A'
    // and $b = 'B'. This is no longer possible in PHP 7.0, so the PHP 7.0
    // solution needed to use an array instead.
    list($a, $b) = $t;

    // Set damage to a random number between 1 and 6
    $d = rand(1, 6);

    // Subtract the damage from the referenced value $b. On the first turn, this
    // is 'B', so this ends up subtracting $d from $B. Next turn, $b will be 'A',
    // so it'll subtract $d from $A
    $$b -= $d;

    // Echo the string (interpolated values)
    echo "$a a $b\n$a r $d\n$b h {$$b}\n";

    // Reverse the turn order string ('AB' becomes 'BA', which will affect the
    // call to list in the first line of the while-loop)
    $t = strrev($t);
}

// Someone's run out of HP; figure out whom by figuring out who still has HP
echo ($A > 0 ? 'A' : 'B') . " w\n";

1

Bash、178バイト

A=10 B=10 e=echo
a(){ $e $1 a $2;d=$((RANDOM%6+1));$e $1 r $d;eval $2=$((${!2}-$d));$e $2 h ${!2};[ ${!2} -gt 0 ];}
while a A B && a B A;do cd;done;[ $A -gt 0 ]&&$e A w||$e B w

1

F#、238 235バイト

私はうまくやっていると思いましたが、あなたは私をはるかに上回っています!

let p=printfn
let mutable A=10
let mutable B=A
let x h a d=
 p"%s a %s"a d
 let i=(new System.Random()).Next(1,7)
 let j=h-i
 p"%s r %i"a i
 p"%s h %i"d j
 if j<=0 then p"%s w"a
 j
while A*B>0 do
 B<-x B"A""B"
 if B>0 then A<-x A"B""A"

オンラインでお試しください!

A> 0 && B> 0の代わりにA * B> 0を使用するという素晴らしいアドバイスをしてくれたRogemに感謝します(3バイトをオフにします)。

また、officialaimmに感謝します。Pythonの回答でprintfを事前に定義することについてのヒントは、私も数バイト削るのに役立ちました。


1
@OlivierGregoireから得たアドバイス:A*B>0あなたをさらに節約します。

それは絶対に素晴らしいです。大好きです。どうもありがとうございました!
Ciaran_McCarthy

1

Haskell、204バイト

Haskellでの私の試み、残念ながら競争力を高めることができませんでした

import System.Random
main=getStdGen>>= \g->putStr$q(randomRs(1,6)g)10(10::Int)"A ""B "
(!)=(++)
l="\n"
q(x:z)a b p o=p!"a "!o!l!p!"r "!show x!l!o!"h "!show n!l!if n<1then p!"w"else q z n a o p where n=b-x

オンラインでお試しください!

説明:

import System.Random  --import random module
main=                        --main function, program entry point
 getStdGen                   -- get the global random number generator
   >>= \g->                  --using the random generator g
       putStr $ q            --print the result of function q, passing in ..
          (randomRs (1,6) g) --an infinite list of random numbers, 1 to 6 generated by g
           10 (10::Int)      --the starting health of both players, 
                             --type annotation sadly seems to be required
           "A " "B "         --The names of the players,
                             --with an extra space for formatting
(!)=(++) --define the operator ! for list (String) concatenation, 
         -- we do this a lot so we save a bit by having a one byte operator
l="\n"   -- define l as the newline character

q      --define function q                         
 (x:z) --our list of random numbers, split into the next number (x) and the rest (z)
 a     -- the health of the active player
 b     -- the health of the player getting attacked
 p     -- the name of the active player
 o     -- the name of the player getting attacked
=
  p!"a "!o!l --create the attack action string with a newline
 !p!"r "!show x!l -- append the roll action
 !o!"h "!show n!l -- append the health remaining
 !           -- append the result of the following if
  if n<1     -- if the player being attacked has been defeated
  then p!"w" -- append the win string for the active player
  else q z n a o p  --otherwise append the result of calling q again with 
                    --rest of the random numbers, and the active players swapped
  where n=b-x -- define the attacked player's new health n
              -- their current health b - the random roll x

あなたは私たちを見ることができます Haskellでのゴルフのヒントをご覧。たとえばwhere m=b-x、ガードに入れることができます:|m<-b-x=
ライコニ

いくつかのパラメーターを再配置すると、ラムダと1組の括弧が失われる可能性がありますmain=putStr=<<q"A "10"B "10.randomRs(1,6::Int)<$>getStdGen。リストを使用して連結し、再定義を取り除くこともでき(++)ます。最後の場所は、b-xどこでも使うだけでは有益ではないようです。
アンス

1

ジュリア0.6、175バイト

p=println()
f(l="AB",h=[10,10],a=1)=(while min(h...)>0;d=3-a;p(l[a]," a ",l[d]);r=rand(1:6);h[d]-=r;p(l[a]," r ",r);p(l[d]," h ",max(h[d],0));a=d;end;p(l[findmax(h)[2]]," w"))

オンラインでお試しください!

長い、無料版:

function status(player, health)
    println("$player h $(max(0,health))")
end

function roll(player)
    x = rand(1:6)
    println("$player r $x")
    x
end

function play()
    players = ["A","B"]
    healths = [10, 10]
    attacker = 1

    while min(healths...) > 0
        println("$(players[attacker]) a $(players[3-attacker])")
        healths[3-attacker]-=roll(players[attacker])
        status(players[3-attacker], healths[3-attacker])

        attacker = 3 - attacker
    end

    winner = findmax(healths)[2]
    println("$(players[winner]) w")
end

TIOリンクに出力がないようです。
AJFaraday

ティオが嫌いな理由はわかりません。私のマシンでは問題なく動作します。時間があれば調べます。
niczky12

1

VBA、222の 185の 179バイト

この再帰的なソリューションには3つのサブが含まれます

  1. gは最初のターンを開始するゲーム開始です
  2. tはターンごと呼び出されます。再帰を使用します。
  3. pは、3回以上使用するとDebug.Printよりも短くなります(このソリューションでは4つだけです) 編集:これDebug.?は、Debug.PrintDebug.?x印刷するサブを呼び出すよりも短くなっています。
Sub g()
t "A",10,"B",10
End Sub
Sub t(i,j,x,h)
d=Int(Rnd()*6)+1
Debug.?i &" a "&x
Debug.?i &" r "&d
h=h-d
If h<1Then
Debug.?i &" w"
Else
Debug.?x &" h "&h
t x,h,i,j
End If
End Sub

これは楽しいチャレンジでした。VB6 / VBScript / VBAのTIOのようなオンラインインタープリターを知っている場合は、コメントを残してください。その後、実用的なソリューションへのリンクを投稿できます。

このコードをテストし、Microsoft Excel、Word、Access、またはOutlookをインストールする場合(Windowsのみ)、Alt + F11を押してVBA IDEを開きます。新しいコードモジュール(Alt + I、M)を挿入し、Option Explicitをクリアします。次に、コードを貼り付けてF5を押して実行します。結果がイミディエイトウィンドウに表示されます(表示されていない場合はCtrl + Gを押します)。

編集1: VBAエディターが自動的に追加する空白を削除。37バイト削減
編集2: Sub p()*を削除して、学習後の6バイトを節約することDebug.?は許容可能な代替手段Debug.Printです。Subを呼び出して処理するのDebug.?は、6回以上呼び出した後にのみバイトを節約します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.