左中右(LCR)码高尔夫


10

在一个聚会上,我被介绍给游戏LCR。现在这不是一个伟大的游戏,因为没有技能,只有随机的机会。但是这让我开始思考,我可以编写代码,然后用R编写了一个快速程序来对游戏进行建模。

维基百科修改了游戏规则,以匹配我们的游戏方式:

每个玩家至少获得3个筹码。玩家轮流掷出三个六边形的骰子,每个骰子的一侧都标有“ L”,“ C”,“ R”,而在其余三个面上标有一个点。对于投出的每个“ L”或“ R”,玩家必须分别向其左侧或右侧传递一个筹码给玩家。“ C”表示到中心(底池)的筹码。点不起作用。

如果玩家剩下的筹码少于三个,则他们仍在游戏中,但筹码数量是他们在回合中掷骰子的数量,而不是全部掷出三个。当玩家的筹码为零时,他们在回合中通过骰子,但可能会从其他人那里获得筹码,并相应地进行下一回合。获胜者是最后一个将筹码放入中心的玩家。

比赛:使用您选择的语言编写一个程序,该程序输入玩家人数和起始筹码数量,并模拟LCR游戏,显示每个玩家滚动后的游戏状态。

例如,一个游戏可能输出为:

[[[3,3,3,3],0],[[1,4,3,4],0],[[1,4,3,4],0],[[1,4,1,4],2],[[1,4,1,2],4],
[[0,4,1,3],4],[[0,3,2,3],4],[[0,3,0,3],6],[[0,3,1,1],7],[[0,3,1,1],7],
[[2,0,1,1],8],[[2,0,0,1],9],[[2,0,0,0],10],[[0,1,0,0],11],
[[1,0,0,0],11],[[1,0,0,0],11],[[1,0,0,0],11],[[0,0,0,0],12]]

ht:乔纳森·艾伦

输出不必看起来完全像这样,但是应该容易分辨骰子掷骰,每个玩家拥有多少筹码以及每回合中锋拥有多少筹码。

这是代码高尔夫球,所以最短的代码获胜。


3
“识别骰子掷骰应该很容易”-从掷骰子状态隐含(因此易于辨别),因为掷骰子是回合的,所以与掷骰子的玩家一样。我认为这个示例输出具有所有必要的条件:[[[3,3,3,3],0],[[1,4,3,4],0],[[1,4,3,4],0],[[1,4,1,4],2],[[1,4,1,2],4],[[0,4,1,3],4],[[0,3,2,3],4],[[0,3,0,3],6],[[0,3,1,1],7],[[0,3,1,1],7],[[2,0,1,1],8],[[2,0,0,1],9],[[2,0,0,0],10],[[0,1,0,0],11],[[1,0,0,0],11],[[1,0,0,0],11],[[1,0,0,0],11],[[0,0,0,0],12]]-是这样吗?
乔纳森·艾伦,

1
@JonathanAllan,对我有用。
CT大厅,

1
@KevinCruijssen,好问题,我想我会允许任一种。
CT大厅

1
@CTHall在这种情况下,我已经编辑了我的两个答案(Java和05AB1E),并包含了有无。:)
凯文·克鲁伊森

1
我几乎想在Runic上做到这一点,其中每个指令指针都充当给定的播放器。不知道我能做到(即使忽略玩家输入的数量),但如果可以的话,它会很整洁。
Draco18s不再信任

Answers:


4

Emacs Lisp,279字节

(defmacro n(i)`(incf(nth ,i c)))
(defun f(p s)(g(let((a'(0)))(dotimes(i p)(push s a))(princ a))0 p))
(defun g(c v p)(dotimes(i(min(nth v c)3))(decf(nth v c))(case(random 6)(0(n(mod(1- v)p)))(1(n(mod(1+ v)p)))(2(n p))(t(n v))))(princ c)(or(eq(-sum c)(nth p c))(g c(mod(1+ v)p)p)))

将此功能用作(f 4 3)

可读性更好的版本:

(defmacro n (i) `(incf (nth ,i c)))

(defun f(p s)
  (g
   (let ((a '(0)))
     (dotimes (i p)
       (push s a))
     (princ a))
   0
   p))

(defun g (c v p)
  (dotimes (i (min (nth v c) 3))
    (decf (nth v c))
    (case (random 6)
      (0 (n (mod (1- v) p)))
      (1 (n (mod (1+ v) p)))
      (2 (n p))
      (t (n v))))
    (princ c)
    (or (eq (-sum c) (nth p c))
    (g c (mod (1+ v) p) p)))

输出示例:

(3 3 3 3 0)(1 4 3 4 0)(2 2 4 4 0)(2 2 2 5 1)(4 2 2 3 1)(2 2 2 4 2)(2 1 3 4 2)(2 2 0 4 4)(2 2 0 4 4)(1 2 0 4 5)(2 1 0 4 5)(2 1 0 4 5)(2 1 1 3 5)(0 1 1 3 7)(1 0 1 3 7)(1 0 1 3 7)(1 0 3 1 7)(1 0 3 1 7)(1 0 3 1 7)(1 1 2 1 7)(1 1 3 0 7)(0 1 3 0 8)(1 0 3 0 8)(1 1 1 1 8)(1 1 2 0 8)(0 1 2 1 8)(0 1 2 1 8)(0 1 1 1 9)(0 1 1 1 9)(0 1 1 1 9)(0 1 1 1 9)(0 1 1 1 9)(0 1 1 0 10)(0 1 1 0 10)(0 0 1 0 11)(0 0 1 0 11)(0 0 1 0 11)(0 0 1 0 11)(0 0 1 0 11)(0 0 0 0 12)

3

爪哇8,281个 277 275 274 253字节

当回合玩家还剩0筹码时输出相同状态的版本:

p->n->{java.util.Arrays A=null;int c[]=new int[p],i=0,t,r,s=1,u,f=9;for(A.fill(c,n);s>0;f=0,System.out.print(A.toString(c)))for(t=c[++i%p],t=t>3?3:t;t-->f;r*=Math.random(),c[i%p]-=1-r/3,s=c[u=(i+r-1+p)%p]+=1-r&1-r/4,c[u]=s<0?0:s,s=A.stream(c).sum())r=6;}

从阵列中的第三个玩家开始。

在线尝试。

跳过剩下0个筹码(274字节)的玩家的版本:

p->n->{java.util.Arrays A=null;int c[]=new int[p],i=p,t,r,s=1,u,f=9;for(A.fill(c,n);s>0;f=0,System.out.print(A.toString(c))){for(t=c[i%p],t=t>3?3:t;t-->f;r*=Math.random(),c[i%p]-=1-r/3,s=c[u=(i+r-1+p)%p]+=1-r&1-r/4,c[u]=s<0?0:s)r=6;for(s=A.stream(c).sum();s>0&c[++i%p]<1;);}}

从数组中的第一个播放器开始。

在线尝试。

-7个字节,感谢@OlivierGrégoire

解释(第二版):

p->n->{                      // Method with two integer parameters and no return-type
  java.util.Arrays A=null;   //  Create a static Arrays-object to save bytes
  int c[]=new int[p],        //  Integer-array with chips of each player (0 by default)
      i=p,                   //  Index integer, starting at the amount of players
      t,                     //  Temp integer to roll 3 dice
      r,                     //  Temp integer for the dice-result
      s=1,u,                 //  Temp integers (and `s` is also the total-sum integer)
      f=9;                   //  Flag integer, starting at a single digit above 3
  for(A.fill(c,n);           //  Give each player in the array the chips
      s>0                    //  Loop as long as the total-sum is not 0 yet
      ;                      //    After every iteration:
       f=0,                  //     Set the flag to 0
       System.out.print(A.toString(c))){
                             //     Print the current state
    for(t=c[i%p],            //   Set `t` to the current player's chips
        t=t>3?3:t;           //   If this is larger than 3: set it to 3 instead
        t-->f                //   Loop that many times (1, 2, or 3)
                             //   (the flag is used to skip this loop the first iteration,
                             //   so we can print the initial state)
        ;                    //     After every iteration:
         r*=Math.random(),   //      Roll the dice in the range [0,5]
         c[i%p]-=r<3?        //      If the dice-roll is 0, 1 or 2:
                  1          //       Remove a chip from this player
                 :0,         //      Else: Leave the chip-amount the same
         s=c[u=(i+r-1+p)%p]  //      If the dice-roll is 0, go to the player left
                             //      If the dice-roll is 2, go to the player right
             +=1-r&1-r/4,    //       And add a chip to this player
         c[u]=s<0?0:s)       //      Change negative amount of chips to 0
      r=6;                   //    Reset the dice-roll to 6 so we can roll again
    for(s=A.stream(c).sum(); //   Calculate the total sum of the chips of the players
        s>0&                 //   If this sum is larger than 0:
         c[++i%p]<1;);}}     //    Determine the next player in line with at least 1 chip

1
可以在没有(小型)高尔夫的情况下离开我的投票:D s=0;for(int C:c)s+=C;(21字节)可以替换为s=A.stream(c).sum();(20字节)
OlivierGrégoire19年

另外,不确定是否完全可以:c[i%p]-=r<3?1:0c[i%p]-=1-r/3。这将节省2个字节。
奥利维尔·格雷戈尔(OlivierGrégoire),

1
@OlivierGrégoire啊,巧妙地重用Afrom的方法java.util.Arrays。:D并将其放在循环中以保存在分号上,它是-2字节。并且1-r/3确实是正确的(请参阅此处)。谢谢。
凯文·克鲁伊森

循环比较递减的好方法。我可能会偷。
Stackstuck

1
忽略我之前删除的评论:我的真值表已关闭。这是固定的值:(s=c[u=(i+r-1+p)%p]+=1-r&1-r/4与相比节省2个字节s=c[u=(i+r%2*2-1+p)%p]+=r<2?1:0
OlivierGrégoire19年

2

Python 2中159个 148字节的

from random import*
n,c=input()
g=[c]*n;i=0
while sum(g):exec"r=randrange(6);g[i]-=1;g[i-[0,1,~-n][max(0,r-3)]]+=r>0;"*min(3,g[i]);i=(i+1)%n;print g

在线尝试!

每卷后打印所有玩家筹码


很好的尝试,但是代码没有显示中心的筹码量。
CT大厅

3
@CTHall中心的筹码始终等于n*c - sum(players)。如果我需要明确地写出来,我会
–TFeld

确实如此。我会允许的
CT大厅

2

果冻,39 个字节

+2以修复重复行为(¡必须在前面加上一个nilad,所以«3Ḣ$-> ⁸FḢ«3

如果我们可以定义要旋转的输出列表,以使属于先前行动过的玩家的筹码在左边,我们可以消除最右边的6个字节等于33个字节(但是,我认为读取它有点尴尬)。

ẋµ’1¦‘.,2ŻX¤¦$¹Ø.X¤?⁸FḢ«3¤¡ṙ1µSпṙ"JC$$

双向链接,左侧接受每人筹码,右侧接受玩家数,从游戏开始时以及每回合(包括在其中0筹码迫使通过的回合)中得出玩家的筹码数列表。

在线尝试!

怎么样?

每个玩家轮流玩一次硬币,最多三次,具体取决于他们的筹码数量。当玩家翻转头,他们做什么,但如果他们翻转尾巴,他们再滚一个三个的骰子失去了一个芯片,L,C或R.(注意,0翻转,当一个球员有0芯片相当于掠过。)
这是重复直到玩家筹码的总和为0。
该实现将玩家每转一圈向左旋转一位,然后将结果状态旋转回所有对齐的状态,就好像它们没有对齐一样。

ẋµ’1¦‘.,2ŻX¤¦$¹Ø.X¤?⁸«3Ḣ¤¡ṙ1µSпṙ"JC$$ - Link: chipsPerPlayer, C; numberOfPlayers, P
ẋ                                      - repeat C P times (making a list of P Cs)
                              п       - collect up results in a list while...
                             S         - ...п condition: sum (while players have chips)
 µ                          µ          - ...п do: the monadic chain:
                         ¡             -   repeat...
                        ¤              -   ...¡ number of times: nilad and link(s) as a nilad:
                    ⁸                  -     chain's left argument (the chip list)
                     «3                -     minimum with three (vectorises)
                       Ḣ               -     head -- i.e. min(left-most player's chips, 3)
                   ?                   -   ...¡ action: if...
                  ¤                    -     ...? clause: nilad and link(s) as a nilad:
               Ø.                      -       the list [0,1]
                 X                     -       random choice (0 is falsey while 1 is truthy)
             $                         -     ...? then: last two links as a monad:
    ¦                                  -       sparsely apply...
   1                                   -       ...¦ to indices: one (the left-most)
  ’                                    -       ...¦ action: decrement (player lost a chip)
            ¦                          -       sparsely apply...
           ¤                           -       ...¦ to indices: nilad and link(s) as a nilad:
      .,2                              -         literal pair of literals .5 and two = [.5,2]
         Ż                             -         prepend a zero = [0,0.5,2]
          X                            -         random choice
                                       -         -- Note application to index .5 is a no-op
                                       -                 index 0 is the right-most entry (L) 
                                       -                 index 2 is the second entry (R) 
                          ṙ1           -   rotate the list left by one for the next п loop
                                     $ - last two links as a monad:
                                    $  -   last two links as a monad:
                                  J    -     range of length -- i.e. [1,2,3,...,turns+1]
                                   C   -     complement = 1-x        [0,-1,-2,...,-turns]
                                 "     -   zipped-appliction of:
                                ṙ      -     rotate left by
                                       -   -- i.e. rotate 1st left by 0, 2nd left by -1, ...)

我对人们如何使用这些看起来像线噪的语言编码感到印象深刻。:)但是我只知道几种语言,所以也许会有更多经验。
CT厅

2
您可以在Wiki上查看该教程,这非常好。一旦我发布了代码细目分类,您将有望遵循我所做的工作……
Jonathan Allan

...这是一种巧妙的错误行为?根据规格,您需要掷出所有三个骰子,而不仅仅是掷一枚硬币。除非描述错误并且代码正确。
Stackstuck

@Stackstuck-描述概述有点误导,每次都掷硬币;我会解决的-谢谢。FWIW代码故障描述是正确的-硬币翻转分支Ø.X¤?嵌套在重复至三倍的指令内⁸«3Ḣ¤¡
乔纳森·艾伦,

啊好吧。很高兴我能帮上忙。
Stackstuck

1

C#,356?+13?字节数

using System;如果需要计算的话,下面的代码总共需要+13个字节。否则,只需在任何课程中对其进行拨叫并致电即可L(players, starting chips);

static int i,j,k,l;public static void L(int p,int s){var r=new Random();var x=new int[p];for(i=0;i<p;i++)x[i]=s;
for(i=0;i<s*p;){for(j=0;j<p;j++){for(l=0;l<x[j]&l<3;l++){k=r.Next(-1,5);if(k<2){if(k==0){x[j]--;i++;}else{x[(p+j+k)%p]++;x[j]--;}}}Console.Write(a(x)+i);}}}public static string a(int[] x){var n="|";for(l=0;l<x.Length;)n+=x[l++]+" ";
return n;}

2,2游戏的示例输出:

|1 3 0|2 2 0|1 3 0|1 3 0|0 4 0|0 3 1|0 3 1|2 1 1|1 2 1|1 2 1|0 3 1|0 3 1|0 3 1|1 1 2|1 1 2|1 1 2|0 2 2|1 1 2|0 1 3|1 0 3|0 1 3|0 1 3|0 1 3|1 0 3|1 0 3|1 0 3|0 1 3|1 0 3|0 1 3|0 0 4

少打高尔夫球的版本:

using System;
//class omitted.
static int i,j,k,l;
public static void LCR(int pl, int sc){
var r=new Random();
var state = new int[pl];
for(i=0;i<pl;i++)state[i]=sc;
for(i=0;i<sc*pl;){
    for(j=0;j<pl;j++){
        for(l=0;l<state[j] && l<3;l++){
            k=r.Next(-1,5);
            if(k<2){
                if(k==0){state[j]--;i++;}else{state[(pl+j+k)%pl]++;state[j]--;}
            }
        }
        Console.Write(a(state)+i);
    }
}
}
public static string a(int[] x){
    var n="|";
    for(l=0;l<x.Length;)n+=x[l++]+" ";
    return n;
}

好吧,这是我在这里的第一个答案。请不要吃我。
Stackstuck

啊,德拉特 我将数组打印行为与Java混淆了。我只是...马上修订。
Stackstuck

好的,这是固定的,输出肯定可以工作。
Stackstuck

...哦,不,还有一个错误。
Stackstuck

人们在行为实际上是剩余的时候说模,应该……不要那样做。在那里,我90%确信现在可以使用。
Stackstuck

1

C#(Visual C#中交互式编译器)201个 199字节

n=>m=>{var r=new Random();var j=Enumerable.Repeat(n,m).ToList();for(int i=0;j.Any(c=>c>0);i++,Print(j))for(int k=0,x=r.Next(6);k++<Math.Min(j[i%m],3);j[((x<1?-1:1)+i+m)%m]+=x<2?1:0,j[i%m]-=x<3?1:0);}

在线尝试!

startingChips=>playerNum=>{
//Instantiate a new random number generator
var rng = new Random();
//Create a list of chips
var players = Enumerable.Repeat(startingChips, playerNum ).ToList();
//Loop as long any player still has chips
for(int turnNum = 0;players.Any(c=>c>0);
//And print the result every iteration
i++,Print(j))
//Get a random number within the range of 0-5 and loop for...
for(int k = 0,randomNum = rng.Next(6);
//either 3 or the amount of chips we have, whichever is smaller
k++<Math.Min(players[turnNum % playerNum ],3);
//Increment either the right player if the random number is 1, else increment the right player if it is 0
players[((randomNum<1?-1:1)+ turnNum + playerNum ) % playerNum ]+=x<2?1:0,
//Decrement current player if the die roll is under 3
players[ turnNum % playerNum ]-=x<3?1:0);}

1

木炭,61字节

≔⁰ηWΣθ«≔Eθ⭆⌊⟦κ׳⁼λη⟧‽⁶ιUMθ⁻⁺⁺κ№§ι⊕λ3№§ι⊖λ5LΦ§ιλ›μ2≔﹪⊕ηLθη⟦⪫θ,

在线尝试!链接是详细版本的代码。在输出骰子掷骰和剩余筹码之间进行交替(输出中既不包括初始筹码数量,也不包括中间的筹码数量)。说明:

≔⁰η

从第一个玩家开始。

WΣθ«

重复直到没有人剩下任何筹码。

≔Eθ⭆⌊⟦κ׳⁼λη⟧‽⁶ι

为当前玩家累积最多三个骰子。这些骰子标记为0-5,其中0-2代表点,3传递到左侧,4传递到中心,5传递到右边。

UMθ⁻⁺⁺κ№§ι⊕λ3№§ι⊖λ5LΦ§ιλ›μ2

将右边玩家的筹码数与左边玩家的筹码数相加,但减去玩家自己过去的筹码数。

≔﹪⊕ηLθη

前进到下一个玩家。

⟦⪫θ,

输出玩家持有的新筹码数。

每个人同时滚动骰子实际上更简单,可以以50字节完成,包括打印骰子卷和剩余筹码:

WΣθ«≔Eθ⭆⌊⟦κ³⟧‽⁶ιUMθ⁻⁺⁺κ№§ι⊕λ3№§ι⊖λ5LΦ§ιλ›μ2⟦⪫ι,⪫θ,

在线尝试!链接是详细版本的代码。


我不确定,但这似乎并不能说明每个角色而不是每个回合后持有的筹码数量。
CT厅

@CTHall哦,你的意思是每个玩家单独掷骰,然后更新筹码数量?抱歉,我忽略了这一点。如果有时间,我会尽快更新答案。
尼尔,

1

05AB1E(旧版)58 50 49 52 字节

当回合玩家还剩0筹码(50 49 52 字节)时输出相同状态的版本:

и[=ÐO_#¾è3‚Ws\F5ÝΩ©3‹iε¾¹%NQ-}®≠iε®<¾+¹%NQ+}}}}D0›*¼

在线尝试。

跳过剩余筹码为0的玩家的版本(58 57 60 字节):

и[=DO_#[D¾èDĀ#\¼}3‚Ws\F5ÝΩ©3‹iε¾¹%NQ-}®≠iε®<¾+¹%NQ+}}}}D0›*¼

在线尝试。

通过使用旧版本,这两个字节都增加了3个字节,因为新的05AB1E版本存在一个奇怪的错误。它应与工作Ws\(推最小而不弹出;交换;丢弃列表)替换为ß(弹出列表,并推最小值)和0›与替换(如果大于0检查)d(检查是否非负/大于或等于0)在新版本,但是由于某些原因,列表顺序在尾部¼!..:S 之后更改(新版本也非常慢,并且在60秒后超时,直到完成结果。..>)

第一个输入是玩家数量,第二个输入是每个玩家的筹码数量。

解释(第二版):

и                    # Create a list with a size of the (first) implicit input,
                     # filled with the second (implicit) input
[                    # Start an infinite loop:
 =                   #  Print the list with trailing newline, without popping the list
 DO_#                #  If the total amount of chips is 0: stop the infinite loop
 [                   #  Start an inner infinite loop:
  D¾è                #   Get the chips of the I'th player (I is 0 by default)
     D               #   Duplicate this
      Ā#             #   If it is NOT 0: stop the inner infinite loop
        \            #   Remove the duplicated chips for the next iteration
         ¼           #   And increase I by 1
 }                   #  After the inner infinite loop:
 3Ws\               #  If the amount of chips is larger than 3: use 3 instead
      F              #  Loop that many times:
       5ÝΩ           #   Roll a random dice in the range [0,5]
       ©3i          #   If the dice-roll is 0, 1, or 2:
           ε¾¹%NQ-}  #    Remove a chip from the I'th player
           ®≠i       #    If the dice-roll is NOT 1:
              ε®<¾+  #     Go to the player left if 0; or right if 2
              ¹%NQ+} #     And increase that player's chips by 1
      }}}            #  Close both if-statements and the loop
         D0›*        #  Make any negative amount of chips 0
             ¼       #  Increase I by 1

我不确定它是否正常运行。看来玩家可以在转牌中获得筹码,这是不应该发生的。
CT厅

@CTHall您确定吗?您在四个TIO版本中的哪个版本中看到了?我只检查了最后一个(遗留版本会跳过0个筹码的玩家),但是增加玩家的唯一时间是轮到另一个玩家时。这是添加了调试行的最后一个,因此您可以看到轮到哪个(0索引)播放器。
凯文·克鲁伊森

1
遗留问题似乎是正确的,但非遗留问题似乎有我提到的错误。
CT厅

@CTHall啊,你确实是对的。我看到一行[2, 3, 3, 3]后跟[2, 2, 2, 6]..:S,我将看看是否能找到原因并解决。如果没有,我总是可以删除它,而只能使用旧版,因为无论如何它会输出更多。.由于某种原因,新版本的循环非常慢。
>>>

@CTHall我已经能够查明问题,但无法解决。由于某种原因,增加全局范围后,列表的顺序会立即更改counter_variable。我试图在一个简单的示例中重现此问题,但无法。它与无限循环内的嵌套if语句和映射有关,但这绝对很奇怪。无论如何,我已经删除了该版本,现在仅保留了旧版(和更快的)版本,可以正常使用。
凯文·克鲁伊森
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.