Tic-Tac-Toe - X u O?


14

Antecedentes

Pase a "Tarea" si está familiarizado con Tic-Tac-Toe (¡creo que la mayoría lo está!)

Tic-Tac-Toe es un famoso juego de dos jugadores. Consiste en un tablero de 3x3 que se llena gradualmente por dos jugadores (aclaraciones a continuación); El primer jugador usa el personaje Xy el otro usa O. El ganador es el primero en obtener 3 caracteres ( Xo O) consecutivos e idénticos , ya sea horizontal, vertical o diagonal. En caso de que el tablero esté lleno y ninguno de los jugadores haya logrado obtener tres personajes consecutivos como se describe anteriormente, el juego termina en un empate. Tenga en cuenta que puede haber espacios vacíos al final del juego, en caso de que alguno de los jugadores gane en menos de 9 movimientos en total (esto no puede suceder en caso de empate).

Tarea

Dado un tablero de Tic-Tac-Toe al final de un juego (en forma de una cadena, una matriz, una lista plana de 9 valores ordenados, cualquier otro formato decente), determine quién gana el juego.

  • La entrada consistirá en valores distintos y consistentes , uno para X, uno para Oy otro que representa un espacio vacío.

  • Su programa debería poder generar 3 valores distintos, consistentes y no vacíos: uno en caso de que Xgane, otro en caso de que Ogane u otro si los jugadores están empatados.

    Por favor, especifique estos valores en su respuesta. Puede suponer que la entrada será un tablero Tic-Tac-Toe válido.

Casos de prueba

X, O, _Son los valores de entrada aquí; X wins, O winsy Tieson para la salida.

X O X
O X _
O _ X

Salida: X wins.

X _ O
X O _
X O X

Salida: X wins.

X O X
_ O X
_ O _

Salida: O wins.

X O X
O O X
X X O

Salida: Tie.


Como de costumbre, se aplican todas nuestras reglas estándar. Este es el , ¡gana el código más corto en bytes en cada idioma!


2
¡Sal de mi cerebro! Literalmente tuve una idea para un desafío de Noughts & Crosses que iba a Sanbox el lunes. ¡Entonces abro el sitio y veo esto!
Shaggy

1
@ Shaggy Para citar a alguien de la serie "Rápido y furioso": ¡ Demasiado lento! ; p
Sr. Xcoder

Está bien, mi idea era una versión jugable, suponiendo que aún no se haya hecho.
Shaggy

44
@Laikoni No creo que sea un engaño, ya que esto tiene una entrada y salida mucho más flexibles y también tiene cuadros vacíos, y esto también te permite asumir que la entrada es una placa válida.
Erik the Outgolfer

1
@Joshua Se trata de hacer un juego de tres en raya. Esto se trata de calificar uno.
DonielF

Respuestas:


6

Jalea ,  16 15  14 bytes

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

Un enlace monádico que acepta una lista de listas (las filas o columnas) con los valores:

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

Resultados devueltos:

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

Nota: usando un valor de cero para _, y valores iguales pero opuestos para Xy O, este valor (aquí 0.155) puede estar en el rango (1/6, 1/7)(exclusivo en ambos extremos): solo elegí un valor en ese rango que dio un resultado de punto flotante representable con precisión para los casos ganadores.

Pruébalo en línea!

¿Cómo?

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)

Sí, creo que cualquier respuesta de lenguaje esotérico debería tener una explicación (¡y también me gustaría ver explicaciones para los idiomas normales!)
Jonathan Allan

¡Gracias por agregarlo! Muy buen enfoque, mucho más inteligente de lo que he pensado ... Agradable
Sr. Xcoder

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 se representa como 1
  • O se representa como 2
  • _ se representa como 0

Salida

  • X gana se representa como "111"
  • O gana se representa como "000"
  • La corbata se representa como "T"

Explicación

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 prueba

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


"Su programa debería poder generar 3 valores distintos, consistentes y no vacíos ", por lo que no puede generar una cadena vacía para el empate.
RedClover

1
@ Soaku Mi mal, me perdí esa parte de las reglas.
Herman L


3

Python 3 , 73 bytes

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

Pruébalo en línea!


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

Pruébalo en línea!


Toma la entrada como una cadena separada de nueva línea de XO_

Salidas:

  • {'XXX'}para X,
  • {'OOO'} para O
  • {} por un empate

Funciona cortando la cadena en filas, columnas y diagonales:

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']

luego 'XXX'y 'OOO'se verifican contra las rodajas.

Toma la entrada como una cadena separada de nueva línea de XO_

Salidas:

  • {'XXX'}para X,
  • {'OOO'} para O
  • {} por un empate

Funciona cortando la cadena en filas, columnas y diagonales:

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']

luego 'XXX'y 'OOO'se verifican contra las rodajas.


Python segmentando FTW De todos modos, 81 bytes , debería funcionar, creo.
Totalmente humano el

@icrieverytim [2::2]corta 3579, mientras [2:8:2]da357
TFeld

Python 3, 73 bytes .
Jonathan Frech

3

R, 118 116 115 bytes

Gracias a @ user2390246 por dos bytes adicionales.

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

Ligeramente no golfista:

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
 }

Devuelve Xsi X gana, Osi O gana y Ten caso de empate.

Pruébalo en línea!


1
M[c(3,5,7)]es más corto para la diagonal opuesta
user2390246

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

Pruébalo en línea!

Salidas Xy Opara victorias, o Tpara un empate. Incluye un montón de código de encabezado / pie de página para probar todo a la vez.


Alternativa, 58 bytes

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

Pruébalo en línea!


2

Python 2 , 124 118 117 115 bytes

  • Guardado seis bytes gracias a Erik the Outgolfer ; usando una cadena para evitar comas.
  • Salvó un byte gracias al Sr. Xcoder ; jugando golf [j*3:j*3+3]a[j*3:][:3] .
  • Se guardaron dos bytes usando un número mágico para comprimir la cadena.
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]

Pruébalo en línea!

Valores de entrada / salida

  • X se representa como 1
  • O se representa como 2
  • _ se representa 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 Gracias. Estaba tratando de jugar golf en la lista de enteros usando map(ord,"..."), aunque un nulbyte en medio de una cadena no funcionó ...
Jonathan Frech

117 bytes . [j*3:j*3+3]es [j*3:][:3]. Como nota al margen, j*3+3es lo mismo que -~j*3, pero eso es 118 bytes también.
Sr. Xcoder

@JonathanFrech Parece que tienes un extra 01234567...
Erik the Outgolfer

1
@ Mr.Xcoder Gracias. Aprendí un nuevo golf rebanador hoy.
Jonathan Frech

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)

Pruébalo en línea!

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

  • Salida como un solo valor: 2 == X, 1 == O, 0 == TIE

-8 bytes gracias a Erik the Outgolfer


Puede reemplazar la primera línea con lambda x:h(x,1)*2or+h(x,0)-8 bytes y 0 == TIE(que es más bonita).
Erik the Outgolfer

@EriktheOutgolfer genial, gracias
HyperNeutrino 01 de

2

PHP, 70 bytes

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

Asume -n (valores predeterminados del intérprete). Además requiere -R(ejecutar<code> para cada línea de entrada), contado como uno.

La entrada se toma en una sola línea (exactamente como en la descripción del problema, excepto con todos los espacios en blanco eliminados).

La salida es la siguiente: 1→ X gana, -1→ O gana,0 → Tie.

Pruébalo en línea!


No necesita tener todas las cadenas, puede elegir sus valores de salida. 'X Wins'se puede cambiar a 'X'(o incluso un número entero, por ejemplo 1). Lo mismo se aplica a 'O wins'y Tie. Dicho esto, 109 bytes .
Sr. Xcoder

@ Mr.Xcoder gracias por la aclaración.
primo

1

Retina , 49 bytes

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

Pruébalo en línea! Toma la entrada como una cadena de 11 caracteres de 9 Xs, Oso -s en tres grupos de tres separados por; s, aunque el enlace incluye un encabezado que traduce los casos de prueba dados a este formato. Funciona haciendo coincidir una línea ganadora directamente con un grupo de equilibrio para garantizar que los tres personajes coincidentes sean equidistantes. (Las distancias adecuadas son 0 (línea horizontal), 4 (diagonal inversa), 5 (línea vertical) o 6 (diagonal); otras distancias golpearían ;o se extenderían fuera de la cuerda).


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) debido a la corrección de errores de solo verificar una diagonal en lugar de ambas ...
-9 bytes (102 → 93) usandoreplaceAll lugar dematches .

De entrada en el formato XOX OX_ O_X, la producción X, OoT .

Explicación:

Pruébalo aquí.

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)

Explicación regex:

.*(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
..+
_

Pruébalo en línea!

... supongo que podrías llamar a esta fuerza bruta ... Pensé que podría haber algún mérito ...


0

Retina , 51 bytes

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

Puerto de mi respuesta Java 8 . De entrada en el formato XOX OX_ O_X, la producción X, Oo T.

Explicación:

Pruébalo aquí.

.*(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}),(,|:)

Sin golf:

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

Explicación

Codificación:

X = 2
O = 3
_ = 1

Nuestra estrategia de alto nivel es primero crear una matriz cada una de cuyas filas sea una posible victoria. La fila uno es diagonal /, la fila 2 es diagonal \, las tres filas siguientes son las filas y las tres filas finales son las columnas. Esta parte se logra mediante la frase (usando el ítem Modificar }):

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

Finalmente tomamos el MCD de cada fila:

+./"1

Gracias a nuestra codificación, cualquier fila con un espacio en blanco tendrá un MCD de 1, al igual que cualquier fila que contenga cualquier combinación de X y Os, porque 2 y 3 son primos. Entonces, todo lo que tenemos que hacer a continuación es encontrar el elemento máximo:>./

Si el juego es un empate, será 1. Si un jugador gana, será el número de ese jugador.

Pruébalo en línea!


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)

Manteniéndolo simple.

  • Entrada: una cadena o conjunto de números o cadenas, que 0corresponde a un espacio en blanco, 1una X y2 una O.
  • Salida: 0para un empate, 1para X victoria, 2para O victoria.

Ampliado, ligeramente 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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.