爱丽丝和鲍勃吵架


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、2、3、4、5或6。
  • 爱丽丝总是开始(鲍勃是老套,以一种老式的方式)。
  • 每转输出一个动作。
  • 您必须报告攻击,横滚,损坏和获胜的行为。
  • 战斗员是大写,行动是小写。
  • 它一定不能始终如一地产生相同的结果。
  • 输出战斗员,动作和值之间必须至少有一个空格字符。
  • 当对手的健康状况为零或更少时,进行胜利行动。
  • 动作的所有部分必须在同一行上。
  • 每行应该有一个动作。
  • 最少的字节数获胜。

加油!


9
爱丽丝(A)和鲍勃(B)这两个名字使我回想起网络安全等级。演员爱丽丝(A)用钥匙……等向鲍勃(B)发送数据包
魔术八爪鱼缸

21
@MagicOctopusUrn就是他们。他们通常试图交流。不幸的是,沟通中断时通常会发生冲突。
AJFaraday

7
我想念我们试图找出对马洛里隐藏秘密的日子……那是更简单的时期……
鲍勃

4
真的,@ Bob Mallory有点让人分心。前夕,您需要提防。
AJFaraday

3
@ msh210,代码高尔夫球中的重要细节是每个人都面临相同的挑战,但这是逻辑:-如果您在玩龙与地下城,您会说“我要踢地精”,那么您d进行有效性滚动,然后执行滚动结果。如果没人知道您要做什么,那么滚动就毫无意义。
AJFaraday

Answers:


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

在线尝试!

-8字节归功于Officialaimm
-2字节归功于ChooJeremy


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)146141字节

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

在线尝试!


简短的python骰子滚史诗般的追求

TL; DR:可以使用RSA加密将标准python骰子卷减少4个字节。

我想看看是否可以将标准python骰子骰(32个字节)缩短一些:

from random import*;randint(1,6)

特别id(x)是,将一些不确定性值引入程序非常方便。然后我的想法是以某种方式哈希此值以创建一些实际的随机性。我尝试了几种方法,其中一种获得了回报:RSA加密

RSA加密由于其简单性而仅需要几个字节:m**e%n。然后可以通过加密前一个随机值来创建下一个随机值。假设(e,n)密钥可用,那么骰子骰可以写成22个字节

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

这意味着我们大约有10个字节来定义有效的RSA密钥。在这里,我很幸运。在实验过程中,我开始使用Mersenne prime M67只是后来才意识到Mersenne犯了一个错误,其中包括M67。原来是p=193707721和的乘积q=761838257287。我找到了模数:

n=~-2**67

现在,指数和Charmichael (p-1)*(q-1)需求者必须是互质的。再次幸运的是,不除以n的全部的第一个质数只有一个数字长:7.然后,可以使用28个字节(比标准方法少4个字节)来写入骰子。

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

使用M67的一件好事是,生成的随机值具有66位,这比通常的64位RNG多。同样,使用RSA可以通过多次解密当前值来使时间回到过去。这是加密和解密密钥:

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

我绝对不是统计学或密码学方面的专家,因此我无法真正确定此RNG是否检查“良好随机性”的标准。我确实写了一个小的基准,用于比较使用不同RNG的1到6个骰子掷骰的标准偏差。似乎提出的解决方案与其他解决方案一样工作。


3
令人印象深刻的工作!:)
HyperNeutrino

4

JavaScript(ES6),122个字节

f=(h=[10,10,p=0])=>`${x='AB'[p]} a ${y='BA'[p]}
${x} r ${d=Math.random()*6+1|0}
${y} h ${H=h[p^=1]-=d}
${H<1?x+' w':f(h)}`

在线尝试!


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.Ô我真的需要尽快研究一些新规格。无论如何,您可以通过将char数组更改为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";}
Kevin Cruijssen

1
@KevinCruijssen是的,Java 10具有var。无需进一步阅读,这基本上是对我们高尔夫球手可用的唯一更改。不,我无法按照您的建议进行操作:检查结果的最后一行:它变为65 w而不是A w。这就是为什么我从int ...陈述中提取出来的原因:去打高尔夫球几个字节;-)
奥利维尔·格雷戈雷(OlivierGrégoire),

1
@KevinCruijssen我遵守了几个例子在这里:codegolf.stackexchange.com/a/159922/16236
奥利维尔·格雷瓜尔



3

Ruby122 120 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字节的解决方案。
Cristian Lupascu

如果它们每行输出一个。那应该做。
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

说明:%在解析时替换了变量引用。这有两个有用的好处:

  • %d%-=rr从命名的变量中减去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#,238235字节

我以为我过得不错,但是你们都远远超过了我!

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"

在线尝试!

感谢Rogem的出色建议,使用A * B> 0代替A> 0 && B> 0(占用3个字节)。

也感谢Officialaimm,他对在Python答案中预定义printf的提示也帮助我节省了几个字节。


1
我从@OlivierGregoire获得的建议:A*B>0可以为您节省更多。

那绝对是很棒的。爱它。非常感谢你!
Ciaran_McCarthy

1

哈斯克尔,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=
Laikoni '18

您可以通过重新设置一些参数来丢失lambda和一组括号main=putStr=<<q"A "10"B "10.randomRs(1,6::Int)<$>getStdGen。您还可以使用列表并将其合并以摆脱重新定义的麻烦(++)。最后一点似乎对仅b-x在任何地方使用都没有好处。
Angs

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

是的,我不知道为什么tio不喜欢它。在我的机器上工作正常。如果有时间,我会调查一下。
niczky12

1

VBA,222个 185个 179字节

此递归解决方案涉及3个子项

  1. g是第一回合开始游戏开始
  2. 转一圈都叫t 。它使用递归。
  3. 当使用3次以上时,p比Debug.Print短(此解决方案中只有4次) 编辑:现在,我知道这Debug.?是可接受的替代方法Debug.PrintDebug.?x比调用Sub进行打印要短。
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.?仅会在六个以上的调用后节省字节。

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.