Simule uma 'batalha' no jogo de cartas 'Oorlog'

15

Vamos criar uma simulação para um aspecto do jogo de cartas, que eu pessoalmente conheço pelo nome holandês 'Oorlog' (traduzido para 'Guerra').

Como funciona o 'Oorlog'?

Dois baralhos de cartas (cada um incluindo dois coringas) são igualmente divididos entre a quantidade de jogadores jogando. Cada jogador embaralha seu próprio estoque, coloca-o de cabeça para baixo na frente deles e todos os jogadores abrem a primeira carta do estoque ao mesmo tempo.
O vencedor dessa 'batalha' é determinado pelos valores das cartas seguindo estas regras: Joker / Ace vence King; O rei derrota a rainha; Rainha derrota Jack; Jack derrota 10; 10 derrotas 9; .... Além disso, 2 e 3 derrotam Ace / Joker. A última regra pode levar a um ciclo em que 2 ou 3 bate em Ace ou Joker, Ace ou Joker em alguma outra carta, que por sua vez bate em 2 ou 3. Nesse caso, os 2 ou 3 vencem a batalha.
(O terno é irrelevante neste jogo de cartas.)

Quando dois ou mais jogadores têm as mesmas cartas mais altas, eles têm uma 'guerra'. Isso significa que eles colocam uma carta de cabeça para baixo e, em seguida, cada uma abre uma nova carta de suas ações, procurando novamente quem tem a carta mais alta. Isso continua até que um único jogador vença toda a batalha.
(Todas as cartas dessa batalha vão para a pilha de descarte do jogador que venceu a batalha. Então todo mundo abre uma nova carta. Quando o estoque de um jogador está sem cartões, ele vira a pilha de descarte de cabeça para baixo e continua com essa nova ação. Isso continua até que um jogador esteja sem todas as suas cartas e depois o jogador com a maior quantidade de cartas vencer.)

Exemplo de 'batalhas' com três jogadores:

  1. 4, 8, Jack:
    Jack vence.
  2. 7, Ace, Rainha:
    Ace vence.
  3. 10, 10, rei: o
    rei vence.
  4. 3, Coringa, 2:
    3 vitórias.
  5. Ás, Coringa, 2:
    2 vitórias.
  6. 3, Rainha, Ace:
    3 vitórias.
  7. Rainha, Rainha, 9:
    Rainha e Rainha estão tendo uma 'guerra', então continua com duas novas cartas: 4, 8;
    8 vitórias.
  8. 4, 4, 4:
    Todos estão tendo uma 'guerra', por isso continua com três novas cartas: 8, Ace, 2;
    2 vitórias.
  9. Jack, 5, Jack:
    Jack e Jack estão tendo uma 'guerra', então continua com duas novas cartas: 5, 5;
    5 e 5 também são iguais, então a 'guerra' continua novamente com duas novas cartas: 10, Rei;
    King vence.
  10. Coringa, Coringa, Ace:
    Todos estão tendo uma 'guerra', por isso continuam com três novas cartas: 9, 7, 9;
    9 e 9 também são iguais, então a 'guerra' continua com duas novas cartas: Valete 3;
    Jack vence.

Então, para o desafio do código:

Entrada:

STDIN com uma matriz ou uma seqüência de caracteres que simula uma matriz (sua chamada - mesmo que seu idioma suporte matrizes). Essa matriz contém as cartas de uma batalha em ordem cronológica (consulte os casos de teste para uma compreensão mais clara disso).

Resultado:

STDOUT o índice do jogador que venceu a batalha.
Você pode escolher se você quer um (ou seja, zero indexados 0, 1ou 2) ou one-indexada saída (ou seja 1, 2, 3).

Regras do desafio:

  • A entrada será uma única matriz / sequência que representa uma matriz. Portanto, você não pode ter uma matriz de matrizes para simplificá-la. Você também não pode ter itens substitutos para os cartões que não participam da guerra.
  • Usamos notações numéricas para os cartões de rosto em vez da notação por letras. Então Ace / Coringa = 1; Jack = 11; Rainha = 12; e rei = 13.
  • Neste desafio, podemos assumir que estamos sempre jogando com 3 jogadores .
  • Os três primeiros indicam o início da 'batalha'. Quando dois ou mais jogadores têm uma 'guerra', as cartas contínuas na matriz indicam sua batalha (consulte os casos de teste para uma compreensão mais clara disso).

Regras gerais:

  • Isso é marcado como , e a resposta mais curta em bytes vence.
    Isso não significa que idiomas que não praticam código de golfe não devem entrar. Tente encontrar uma resposta de código-golfe o mais curta possível para 'toda' linguagem de programação.
  • Mencione qual indexação (zero ou um indexado) você usou para a saída.

Casos de teste:

Test case 1:  [4, 8, 11]                 ->  2 (or 3)
Test case 2:  [7, 1, 12]                 ->  1 (or 2)
Test case 3:  [10, 10, 13]               ->  2 (or 3)
Test case 4:  [3, 1, 2]                  ->  0 (or 1)
Test case 5:  [1, 1, 2]                  ->  2 (or 3)
Test case 6:  [3, 12, 1]                 ->  0 (or 1)
Test case 7:  [12, 12, 9, 4, 8]          ->  1 (or 2)
Test case 8:  [4, 4, 4, 8, 1, 2]         ->  2 (or 3)
Test case 9:  [11, 5, 11, 5, 5, 10, 13]  ->  2 (or 3)
Test case 10: [1, 1, 1, 9, 7, 9, 11, 3]  ->  0 (or 1)
Test case 11: [13, 13, 4, 1, 3]          ->  1 (or 2)
Test case 12: [13, 4, 13, 2, 3]          ->  2 (or 3)
Kevin Cruijssen
fonte
4
O nome em inglês é de fato Guerra (menos os curingas e menos a regra de 2 e 3 batidas de ás).
Martin Ender
@MartinEnder também, quando há um empate, os dois jogadores jogam 3 cartas com a face para baixo e a quarta com a face para cima. O quarto decide o vencedor da rodada, e as cartas viradas para baixo são os "espólios da guerra". Além disso, o jogo não continua até que um jogador tenha todas as cartas? Não sei se essa era uma regra local ou não, mais alguém se lembra disso? É assim que me lembro de jogar.
Magic Octopus Urn
1
@MagicOctopusUrn Lembro-me de virar as pilhas de descarte para continuar jogando até que um jogador tivesse tudo.
Kamil Drakari
1
@KamilDrakari yeah! Foi assim que joguei também. Eu estava na Louisiana crescendo tocando isso.
Magic Octopus Urn
@MagicOctopusUrn Minha experiência é em Minnesota, e como agora temos dois pontos de dados, acho seguro dizer que toda a América é a mesma.
Kamil Drakari

Respostas:

4

q - 142 caracteres

{p:til 3;while[1<(#:)p;h:(n:(#:)p)#x;x:n _x;$[1~min h;p:$[max a:h in(2;3);$[1<(#:)(?:)h(&:)a;p(&:)h=3;p(&:)a];p(&:)h=1];p:p(&:)h=max h]];(*:)p}

Nota: zero indexado.

Não há noção de ler stdin em q, então você deve chamá-lo como uma função: {p:til 3;while[1<(#:)p;h:(n:(#:)p)#x;x:n _x;$[1~min h;p:$[max a:h in(2;3);$[1<(#:)(?:)h(&:)a;p(&:)h=3;p(&:)a];p(&:)h=1];p:p(&:)h=max h]];(*:)p}[1,2,3]

Muito longo, na verdade, mas existem muitos casos de canto. Ele mantém uma lista de jogadores ativos e consome a lista de cartas em um loop. A coisa mais problemática é detectar o vencedor correto em mãos como [13, 2, 3], desde 3batidas 2, como normal, mas tinha que ser duplicado para ser colocado em caso esquina.

C. Quilley
fonte
3

JavaScript (ES6), 146 bytes

f=a=>(b=a.splice(0,3)).filter(m=>m-n,n=Math.max(...b.includes(1)?b.filter(m=>m<4):b)).length>1?b.indexOf(n):f([...b.map(m=>m-n?0:a.shift()),...a])

Retorna um índice baseado em zero. 127 bytes se me for permitido o acordo inicial como uma matriz separada (isso também funciona para um número arbitrário de mãos, é claro):

f=(b,a)=>b.filter(m=>m==n,n=Math.max(...b.includes(1)?b.filter(m=>m<4):b)).length<2?b.indexOf(n):f(b.map(m=>m-n?0:a.shift()),a)
Neil
fonte
0

Java 8, 257 bytes

int c(int[]a){int t=0,f=0,q,r=0,i=-1,l=a.length,x[];for(;++i<3;t=a[i]>t?a[r=i]:t)a[i]+=a[i]==1?f++*0+13:0;for(;i-->0;t=f>0&a[i]<4?t!=3?a[r=i]:t>a[i]?a[r=i]:t:t);for(f=-1,x=new int[q=l<7?3:l>7?l-3:5];l>3&++i<q;)x[i]=t==a[i]|i>2?a[++f+3]:0;return l>3?c(x):r;}

Ok, meu desafio é mais difícil do que eu pensava que seria com tudo em uma única matriz como essa. ;) Mas como já faz mais de um ano que não publiquei este desafio, decidi tentar. Demorei um bom tempo com várias soluções alternativas e peculiaridades ... Então, definitivamente posso jogar golfe um pouco mais, mas analisarei isso outra vez. Isso já demorou muito mais do que eu esperava ..

Explicação:

Experimente aqui.

int c(int[]a){      // Method with integer-array parameter and integer return-type
  int t=0,f=0,q,    //  Temp integers
      r=0,          //  Result-integer
      i=-1,         //  Index-integer
      l=a.length,   //  Length of the input-array
      x[];          //  Temp array we use when there is a war
  for(;++i<3;       //  Loop (1) from 0 to 3 (exclusive)
      t=            //    After every iteration, change `t` to:
        a[i]>t?     //     If the current item is larger than `t`:
         a[r=i]     //      Use the current item (and save its index in `r`)
        :           //     Else:
         t)         //      Leave `t` the same
    a[i]+=a[i]==1?  //   If the current item is a 1 (Ace/Joker):
         f++*0      //    Increase `f` by 1,
         +13        //    and change the 1 to 14 (by increasing with 13)
        :           //   Else:
         0;         //    Leave the current item the same (by increasing with 0)
                    //  End of loop (1) (implicit / single-line body)
  for(;i-->0;       //  Loop from 2 down to 0 (inclusive)
    t=f>0&a[i]<4?   //   If a Joker/Ace was present, and the current item is 2 or 3:
       t!=3?        //    And if it's not a 3 (so either 2 or 14)
        a[r=i]      //     Change `t` to the current item (and save its index in `r`)
       :t>a[i]?     //    Else-if the current item is 2, and `t` is a Joker/Ace:
        a[r=i]      //     Change `t` to the current item (and save its index in `r`
       :            //    Else:
        t           //     Leave `t` the same
      :             //   Else:
       t            //    Leave `t` the same
  );                //  End of loop (2)
  for(f=-1,         //  Reset `f` to -1
      x=new int[    //  Create the temp array `x` with length:
       q=l<7?       //   If the current length is 6 or lower:
          3         //    New length after war is 3
         :l>7?      //   Else-if the current length is 8 or higher:
          l-3       //    New length after war is current length - 3
         :          //   Else(-if current length is 7)
          5];       //    New length after war is 5
      l>3&          //  If there is a war:
          ++i<q;)   //   Loop (3) from 0 to the new length (exclusive)
    x[i]=t==a[i]    //    If the current item is at war,
         |i>2?      //    or the current item is after the first 3 items:
          a[++f+3]  //     Fill the new array with the correct next item
         :          //    Else:
          0;        //     Fill the item of the new array with 0
                    //     (since it won't participate in the next round)
                    //   End of loop (3)
  return l>3?       //  If there was a war:
          c(x)      //   Recursive-call with the new array
         :          //  Else:
          r;        //   Return the index of the card that won
}                   // End of method
Kevin Cruijssen
fonte