Tic-Tac-Toe - X ou O?


14

fundo

Pule para "Tarefa" se você estiver familiarizado com o Tic-Tac-Toe (acho que a maioria está!)

Tic-Tac-Toe é um famoso jogo para dois jogadores. Consiste em um tabuleiro 3x3 que é preenchido gradualmente por dois jogadores (esclarecimentos abaixo); O primeiro jogador usa o personagem Xe o outro usa O. O vencedor é o primeiro a obter 3 caracteres consecutivos e idênticos ( Xou O), na horizontal, na vertical ou na diagonal. Caso o tabuleiro esteja cheio e nenhum dos jogadores tenha conseguido três personagens consecutivos, como descrito acima, o jogo termina em empate. Observe que pode haver vagas vazias no final do jogo, caso um dos jogadores ganhe menos de 9 jogadas no total (isso não pode acontecer em caso de empate).

Tarefa

Dado um tabuleiro Tic-Tac-Toe no final de um jogo (na forma de uma string, uma matriz, uma lista simples de 9 valores ordenados, qualquer outro formato decente), determine quem vence o jogo.

  • A entrada consistirá em valores distintos e consistentes , um para X, um para Oe outro que representa um ponto vazio.

  • Seu programa deve ser capaz de gerar 3 valores distintos, consistentes e não vazios: um no caso de Xvitória, outro no caso de Ovitória ou outro se os jogadores estiverem empatados.

    Especifique esses valores na sua resposta. Você pode assumir que a entrada será uma placa Tic-Tac-Toe válida.

Casos de teste

X, O, _São os valores de entrada aqui; X wins, O winsE Tiesão para a saída.

X O X
O X _
O _ X

Saída: X wins.

X _ O
X O _
X O X

Saída: X wins.

X O X
_ O X
_ O _

Saída: O wins.

X O X
O O X
X X O

Saída: Tie.


Como sempre, todas as nossas regras padrão se aplicam. Este é o , o código mais curto em bytes em todos os idiomas vence!


2
Saia do meu cérebro! Literalmente, só tinha uma idéia para um desafio de Noughts & Crosses que eu iria à Sanbox na segunda-feira. Então eu abro o site e vejo isso!
Shaggy

1
@ Shaggy Para citar alguém da série "Velozes e Furiosos": Muito devagar! ; p
Mr. Xcoder

Tudo bem, minha ideia era para uma versão jogável, supondo que isso ainda não tenha sido feito.
Shaggy

4
@Laikoni: Eu não acho que seja um tolo, já que isso tem entradas e saídas muito mais flexíveis e também possui caixas vazias, e isso também permite que você assuma que a entrada é uma placa válida.
Erik the Outgolfer

1
@ Joshuaua É sobre fazer um jogo Tic-tac-toe. Trata-se de classificar um.
DonielF

Respostas:


6

Geléia ,  16 15  14 bytes

U,Z;ŒD$€ẎḄỊÐḟḢ

Um link monádico que aceita uma lista de listas (as linhas - ou colunas) com os valores:

X = 0.155; O = -0.155; _ = 0

Retornando resultados:

X wins = 1.085; O wins = -1.085; Tie = 0

Nota: usando um valor zero para _ , e valores iguais mas opostos para Xe O, esse valor (aqui 0.155) pode estar no intervalo (1/6, 1/7)(exclusivo nos dois extremos) - eu só escolhi um valor nesse intervalo que desse um resultado de ponto flutuante precisamente representável para os casos de vitória.

Experimente online!

Quão?

U,Z;ŒD$€ẎḄỊÐḟḢ - Link: list of lists (as described above)
U              - upend (reverse each row)
  Z            - transpose (get the columns)
 ,             - pair the two
      $€       - last two links as a monad for each of them:
    ŒD         -   diagonals (leading diagonals - notes: 1. only one is of length 3;
               -              2. the upend means we get the anti-diagonals too)
        Ẏ      - tighten (make a single list of all the rows, columns and diagonals)
         Ḅ     - from binary (vectorises) (note that [0.155, 0.155, 0.155]
               -                           converts to 4*0.155+2*0.155+1*0.155 = 1.085
               -                           and [-0.155, -0.155, -0.155]
               -                           converts to 4*-0.155+2*-0.155+1*-0.155 = -1.085
               -                           while shorter lists or those of length three
               -                           with any other mixtures of 0.155, -0.155 and 0
               -                           yield results between -1 and 1
               -                           e.g. [.155,.155,0] -> 0.93)
           Ðḟ  - filter discard if:
          Ị    -   insignificant (if abs(z) <= 1) (discards all non-winning results)
             Ḣ - head (yields the first value from the list or zero if it's empty)

Sim, acho que quaisquer respostas linguagem esotérica deve ter uma explicação (e eu gostaria de ver explicações para línguas normais também!)
Jonathan Allan

Obrigado por adicioná-lo! Abordagem muito boa, muito mais inteligente do que o que eu
pensava

6

Javascript (ES6), 103 87 bytes

a=>"012+345+678+036+147+258+048+246T".replace(/\d/g,n=>a[n]||!1).match(/(\d)\1\1|T/)[0]

Entrada

  • X é representado como 1
  • O é representado como 2
  • _ é representado como 0

Resultado

  • X vitórias é representado como "111"
  • O ganha é representado como "000"
  • O empate é representado como "T"

Explicação

a=>
    "012+345+678+036+147+258+048+246" // List of indexes for each row
    .replace(/\d/g,n=>a[n]||!1)       // Replace all digits with the value of the cell
    .match(/(\d)\1\1|$/)[0]           // Find the first row filled with the same value

Casos de teste

f=
a=>"012+345+678+036+147+258+048+246T".replace(/\d/g,n=>a[n]||!1).match(/(\d)\1\1|T/)[0]
console.log(f([1,2,1,2,1,0,2,0,1]))
console.log(f([1,0,2,1,2,0,1,2,1]))
console.log(f([1,2,1,0,2,1,0,2,0]))
console.log(f([1,2,1,2,2,1,1,1,2]))


"Seu programa deve ser capaz de gerar 3 valores distintos, consistentes e não vazios ", para que você não possa gerar uma string vazia para empate.
RedClover

1
@ Soaku Meu mal, eu perdi essa parte das regras.
Herman L

4

Gelatina , 18 bytes

UŒD;;Z;ŒDµSA⁼3µÐfḢ

Experimente online!

X= 1, O= -1, _= 0
X vence = [1, 1, 1], O vence = [-1, -1, -1], Empate = 0
Entrada como lista de 3 listas de 3 elementos em (1, -1, 0)cada.


Wow agradável ... Quando você terminar de golfe, por favor, adicione os valores de I / O e uma explicação :-)
Mr. Xcoder

Aqui está uma abordagem semelhante com um teste um pouco mais curto. Retorna X= 1, O= 2, _= 3, retorna 1(X vence), 2(O vence) ou 3(empata).
Arnauld

@Arnauld graças para o encurtamento
Erik a Outgolfer

3

Python 3 , 73 bytes

lambda b:{'XXX','OOO'}&{*b.split(),b[::4],b[1::4],b[2::4],b[::5],b[2::3]}

Experimente online!


Python 2 , 100 95 92 87 82 77 bytes

lambda b:{'XXX','OOO'}&set(b.split()+[b[::4],b[1::4],b[2::4],b[::5],b[2::3]])

Experimente online!


Recebe a entrada como uma sequência separada por nova linha de XO_

Saídas:

  • {'XXX'} para X,
  • {'OOO'} para O
  • {} para um empate

Funciona dividindo a string em linhas, colunas e diagonais:

The board:
    1 2 3
    4 5 6
    7 8 9
which is '123\n456\n789' is sliced into:

['123', '456', '789', '147', '258', '369', '159', '357']
rows: b.split() -> ['123', '456', '789']
cols: [b[::4],b[1::4],b[2::4]] -> ['147', '258', '369']
diag: [b[::5],b[2::3]] -> ['159', '357']

então 'XXX'e'OOO'são verificados nas fatias.

Recebe a entrada como uma sequência separada por nova linha de XO_

Saídas:

  • {'XXX'}para X,
  • {'OOO'} para O
  • {} para um empate

Funciona dividindo a string em linhas, colunas e diagonais:

The board:
    1 2 3
    4 5 6
    7 8 9
which is '123\n456\n789' is sliced into:

['123', '456', '789', '147', '258', '369', '159', '357']
rows: b.split() -> ['123', '456', '789']
cols: [b[::4],b[1::4],b[2::4]] -> ['147', '258', '369']
diag: [b[::5],b[2::3]] -> ['159', '357']

então 'XXX'e 'OOO'são verificados nas fatias.


Python cortando FTW De qualquer forma, 81 bytes , deve funcionar, eu acho.
totallyhuman

@icrieverytim [2::2]corta para 3579, enquanto [2:8:2]dá #357
TFeld 2/17

Python 3, 73 bytes .
Jonathan Frech

3

R, 118 116 115 bytes

Obrigado a @ user2390246 por dois bytes extras.

function(M,b=table,u=unlist(c(apply(M,1,b),apply(M,2,b),b(diag(M)),b(M[2*1:3+1]))))`if`(any(u>2),names(u[u>2]),"T")

Ligeiramente não destruído:

function(M){
    u=unlist(c(apply(M,1,table), #Contingency table of the rows
             apply(M,2,table), #of the columns
             table(diag(M)), #of the diagonal
             table(M[2*1:3+1]))) #of the opposite diagonal
    `if`(any(u>2),names(u[u>2]),"T") #Give name of element that occurs more than twice in any setting
 }

Retorna Xse X vencer, Ose O vencer e Tem caso de empate.

Experimente online!


1
M[c(3,5,7)]é menor para a diagonal oposta #
user2390246 2/17/17

3

Perl 5 , 58 bytes

Código de 56 bytes + 2 fpr -p0.

$_=eval sprintf'/(.)(.{%s}\1){2}/s||'x4 .'0?$1:T',0,2..4

Experimente online!

Saídas Xe Ovitórias ou Tempate. Inclui um monte de código de cabeçalho / rodapé para testar tudo de uma vez.


Alternativa, 58 bytes

$}.="/(.)(.{$_}\\1){2}/s||"for 0,2..4;$_=eval$}.'0?$1:T'

Experimente online!


2

Python 2 , 124 118 117 115 bytes

  • Economizou seis bytes graças a Erik, o Outgolfer ; usando uma string para evitar vírgulas.
  • Economizou um byte graças ao Sr. Xcoder ; golfe [j*3:j*3+3]para [j*3:][:3].
  • Salva dois bytes usando um número mágico para compactar a sequência.
def T(B):
 for j in range(8):
	a,b,c=map(int,`0x197bf3c88b2586f4bef6`[j*3:][:3])
	if B[a]==B[b]==B[c]>0:return B[a]

Experimente online!

Valores de entrada / saída

  • X é representado como 1
  • O é representado como 2
  • _ é representado como None

[8,0,3,6,1,4,7,2,5,8,0,4,8,2,4,6]->map(int,'8036147258048246')
Erik the Outgolfer

@EriktheOutgolfer Thanks. Eu estava tentando golfe a lista inteiro usando map(ord,"..."), apesar de um nulbyte no meio de uma corda não deu certo ...
Jonathan Frech

117 bytes . [j*3:j*3+3]é [j*3:][:3]. Como uma observação lateral, j*3+3é o mesmo que -~j*3, mas também são 118 bytes.
Sr. Xcoder

@JonathanFrech Você parece ter um extra 01234567...
Erik the Outgolfer

1
@ Mr.Xcoder Obrigado. Aprendeu um novo golfe de corte hoje.
Jonathan Frech 30/09

2

Python 3 , 173 bytes

lambda x:h(x,1)*2or+h(x,0)
h=lambda x,y:g(x,y)or g(zip(*x),y)or x[0][0]==x[1][1]==x[2][2]==y or x[0][2]==x[1][1]==x[2][0]==y
g=lambda x,y:any(all(e==y for e in r)for r in x)

Experimente online!

  • Entrada como uma matriz de 1 == X, 0 == O, -1 == _

  • Saída como um valor único: 2 == X, 1 == O, 0 == TIE

-8 bytes graças a Erik the Outgolfer


Você pode substituir a primeira linha lambda x:h(x,1)*2or+h(x,0)por -8 bytes e 0 == TIE(o que é mais bonito).
Erik the Outgolfer

@EriktheOutgolfer legal, obrigado
HyperNeutrino 1/17/17

2

PHP, 70 bytes

for($c=95024101938;${${$i++&7}.=$argn[$c%9]}=1<$c/=3;);echo$XXX-$OOO;

Supõe -n(padrão do intérprete). Adicionalmente requer-R (executar <code>para cada linha de entrada), contada como uma.

A entrada é obtida em uma única linha (exatamente como na descrição do problema, exceto com todos os espaços em branco removidos).

A saída é a seguinte: 1 → X vence, -1→ O vence, 0→ Empate.

Experimente online!


Você não precisa ter as cadeias inteiras, pode escolher seus valores de saída. 'X Wins'pode ser alterado para 'X'(ou mesmo um número inteiro - digamos 1). O mesmo se aplica a 'O wins'e Tie. Dito isto, 109 bytes .
Sr. Xcoder 01/10/19

@ Mr.Xcoder obrigado pelo esclarecimento.
Primo1

1

Retina , 49 bytes

;
;;
.*(\w)(.)*\1(?<-2>.)*(?(2)(?!))\1.*
$1
..+
T

Experimente online!Recebe entrada como uma sequência de 11 caracteres de 9 Xs, Os ou -s em três grupos de três separados por ;s, embora o link inclua um cabeçalho que traduza os casos de teste fornecidos para esse formato. Funciona combinando uma linha vencedora diretamente usando um grupo de equilíbrio para garantir que os três caracteres correspondentes sejam equidistantes. (As distâncias adequadas são 0 (linha horizontal), 4 (diagonal reversa), 5 (linha vertical) ou 6 (diagonal); outras distâncias atingem um ;ou se estendem para fora da corda.)


1

Java 8, 112 108 106 104 90 102 93 bytes

b->b.replaceAll(".*(X|O)(\\1|...\\1...|.{4}\\1.{4}|..\\1..)\\1.*","$1").replaceAll("..+","T")

+12 bytes (90 → 102) devido à correção de erros de verificação de apenas uma diagonal em vez de ambas.
-9 bytes (102 → 93) usando em replaceAllvez dematches .

Entrada no formato XOX OX_ O_X, saída X,O ouT .

Explicação:

Experimente aqui.

b->{                   // Method with String as both parameter and return-type
  b.replaceAll(".*(X|O)(\\1|...\\1...|.{4}\\1.{4}|..\\1..)\\1.*",
                       //  If we found a line of X or O:
     "$1")             //   Replace it with either X or O
   .replaceAll("..+",  //  If there are now more than 2 characters left:
     "T")              //   Replace it with T
                       // End of method (implicit / single-line return-statement)

Regex de explicação:

.*(X|O)(\1|...\1...|.{4}\1.{4}|..\1..)\1.*
.*                                      .*# 0 or more trailing & leading chars
  (X|O)                               \1  # X or O next to those leading/trailing chars
       (\1                                # A single X or O in between (row found)
          |...\1...                       # 3 chars, X or O, 3 chars (column found)
                   |.{4}\1.{4}            # 4 chars, X or O, 4 chars (diagonal TLBR found)
                              |..\1..)    # 2 chars, X or O, 2 chars (diagonal TRBL found)

0

Retina , 127 bytes

.*(X|O)\1\1.*
$1
(X|O).. \1.. \1..
$1
.(X|O). .\1. .\1.
$1
..(X|O) ..\1 ..\1
$1
(X|O).. .\1. ..\1
$1
..(X|O) .\1. \1..
$1
..+
_

Experimente online!

... Eu acho que você poderia chamar isso de força bruta ... Pensei que poderia haver algum mérito nisso ...


0

Retina , 51 bytes

.*(X|O)(\1|...\1...|.{4}\1.{4}|..\1..)\1.*
$1
..+
T

Porta da minha resposta Java 8 . Entrada no formato XOX OX_ O_X, saída X, Oou T.

Explicação:

Experimente aqui.

.*(X|O)(\1|...\1...|.{4}\1.{4}|..\1..)\1.*
.*                                      .*# 0 or more trailing & leading chars
  (X|O)                               \1  # X or O next to those leading/trailing chars
       (\1                                # A single X or O in between (row found)
          |...\1...                       # 3 chars, X or O, 3 chars (column found)
                   |.{4}\1.{4}            # 4 chars, X or O, 4 chars (diagonal TL→BR found)
                              |..\1..)    # 2 chars, X or O, 2 chars (diagonal TR→BL found)

$1                                        #  Replace match of above with either X or O

..+                                       # If there are now 2 or more characters left:
T                                         #  Replace everything with T

0

J, 34 bytes

[:>./[:+./"1(2 1 0},:0 1 2}),(,|:)

Ungolfed:

[: >./ [: +./"1 (2 1 0} ,: 0 1 2}) , (, |:)

Explicação

Codificação:

X = 2
O = 3
_ = 1

Nossa estratégia de alto nível é a primeira a criar uma matriz, cujas linhas são uma vitória possível. A linha um é diagonal /, a linha 2 é diagonal \, as três linhas seguintes são as linhas e as três linhas finais são as colunas. Esta parte é realizada pela frase (usando o Item Amend }):

(2 1 0},:0 1 2}),(,|:)

Finalmente, pegamos o GCD de cada linha:

+./"1

Graças à nossa codificação, qualquer linha com um espaço em branco terá um GCD de 1, assim como qualquer linha que contenha qualquer combinação de Xs e Os, porque 2 e 3 são coprime. Então, tudo o que precisamos fazer a seguir é encontrar o elemento máximo:>./

Se o jogo for empatado, será 1. Se um jogador vencer, será o número desse jogador.

Experimente online!


0

JavaScript, 66 bytes

([a,b,c,d,e,f,g,h,i])=>e&(a&i|c&g|b&h|d&f)|a&(b&c|d&g)|i&(c&f|g&h)

Mantendo simples.

  • Entrada: Uma sequência, ou matriz de números ou sequências, 0correspondente a um espaço em branco, 1um X e 2um O.
  • Saída: 0por empate, 1por X vitória, 2por O vitória.

Expandido, levemente comentado:

( [a,b,c,d,e,f,g,h,i] ) => // Break apart the input into nine variables w/ destructuring
  // Run through all possible win conditions. 1&1&1 -> 1, 2&2&2 -> 2
  e & (             // All victories involving the middle square
    a & i | c & g | // Diagonal lines
    b & h | d & f   // Vertical/horizontal through the middle
  ) | 
  a & ( b & c | d & g ) | // Victories with the top-left square
  i & ( c & f | g & h )   // Victories with the bottom-right square
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.