Алиса и Боб ссорятся


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
@ Боб Мэллори, на самом деле, отвлекает. Это Ева, которую ты должен остерегаться.
AJFaraday

3
@ msh210 хорошо, важная деталь в кодовом гольфе состоит в том, что каждый принимает один и тот же вызов, но вот логика: - если бы вы играли в Dungeons and Dragons, вы бы сказали: «Я собираюсь пнуть гоблина», тогда вы 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")

Попробуйте онлайн!

-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, хотя распределение не совсем равномерное.
Винсент

@ Винсент Я не вижу смысла в нарушении правил, если это даже не помогает сделать его короче ...
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}. б побеждает со здоровьем -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: можно сократить 4 байта от стандартного броска кубиков питона, используя шифрование RSA.

Я хотел посмотреть, можно ли немного укоротить стандартный бросок кубика питона ( 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. Здесь мне повезло. Во время своих экспериментов я начал использовать простое число Мерсенна М67 только для того, чтобы потом осознать, что Мерсенн допустил ошибку, включив М67 в свой список. Оказывается, является продуктом 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)

Я определенно не эксперт в области статистики или криптографии, поэтому я не могу точно сказать, проверяет ли этот ГСЧ критерии «хорошей случайности». Я написал небольшой тест, который сравнивает стандартное отклонение вхождений от 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.Ô Мне действительно нужно в ближайшее время изучить некоторые из новых спецификаций. В любом случае, вы можете сыграть в гольф 4 байта, изменив массив символов на int-массив: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";}
Кевин Круйссен,

1
@KevinCruijssen Да, у Java 10 есть вар. Не нужно читать дальше, это единственное изменение, которое можно использовать для нас, игроков в гольф. И нет, я не могу сделать то, что вы предлагаете: проверьте последнюю строку результата: он становится 65 wвместо A w. Вот почему я извлек это из int ...заявления: в гольф несколько байтов ;-)
Оливье Грегуар,

1
@KevinCruijssen Я выполнил несколько примеров здесь: codegolf.stackexchange.com/a/159922/16236
Оливье Грегуар,



3

Рубин , 122 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]}

Сохранено 1 байт благодаря Asone Tuhid .

Попробуйте онлайн!


1
Как будто я даже не знаю, как Руби больше;)
AJFaraday

Боюсь, ваша альтернатива не работает: «Все части действия должны быть на одной линии». Хотя, возможно ли сделать такую ​​же оптимизацию с помощью символа табуляции?
AJFaraday

@AJFaraday Будет ли приемлемо выводить строки в формате ["A", "a", "B"]? Если так, у меня есть это 96-байтовое решение.
Кристиан Лупаску

Если они выводятся по одному на строку. Это должно сделать.
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%-=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

Баш, 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"

Попробуйте онлайн!

Спасибо Rogem за блестящий совет использовать A * B> 0 вместо A> 0 && B> 0 (снимает 3 байта).

Спасибо также officialaimm, чей намек на предопределение printf в ответе Python помог мне также сбрить несколько байтов.


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

Вы можете взглянуть на наши советы по игре в гольф на Хаскелле . Например, where m=b-xможно положить в охрану |m<-b-x=.
Лайкони

Вы можете потерять лямбда и один набор скобок переставив некоторые параметры: 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. Т вызывается для каждого хода . Использует рекурсию.
  3. p короче, чем Debug.Print, если его использовать более 3 раз (только 4 в этом решении). Редактировать: Теперь, когда я узнал, что Debug.?это приемлемая альтернатива Debug.Print, Debug.?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

Это было забавное испытание. Если вам известен такой онлайн-переводчик, как TIO для VB6 / VBScript / VBA, пожалуйста, оставьте комментарий. Тогда я могу опубликовать ссылку на рабочее решение.

Если вы хотите протестировать этот код и установить Microsoft Excel, Word, Access или Outlook (только для Windows), нажмите Alt + F11, чтобы открыть IDE VBA. Вставьте новый модуль кода (Alt + I, M) и очистите Option Explicit. Затем вставьте код и нажмите F5, чтобы запустить его. Результаты должны появиться в «Немедленном окне» (нажмите Ctrl + G, если вы его не видите).

Редактировать 1: Удалены пробелы, в которые автоматически добавляется редактор VBA. Уменьшено на 37 байт
Редактировать 2: Удален Sub p () * для сохранения 6 байтов после обучения, что Debug.?является приемлемой альтернативой Debug.Print. Вызов Sub для обработкиDebug.? только сохраняет байты после более чем шести вызовов.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.