Tic-Tac-Toe - X o O?


14

sfondo

Passa a "Task" se hai familiarità con Tic-Tac-Toe (penso che la maggior parte lo sia!)

Tic-Tac-Toe è un famoso gioco a due giocatori. Consiste in una tavola 3x3 che viene riempita gradualmente da due giocatori (chiarimenti di seguito); Il primo giocatore usa il personaggio Xe l'altro usa O. Il vincitore è il primo a ottenere 3 personaggi consecutivi e identici ( Xo O), in orizzontale, in verticale o in diagonale. Nel caso in cui il tavolo sia pieno e nessuno dei giocatori è riuscito a ottenere tre personaggi consecutivi come sopra descritto, il gioco termina in parità. Nota che potrebbero esserci dei punti vuoti alla fine della partita, nel caso in cui uno dei giocatori vinca in meno di 9 mosse in totale (ciò non può accadere in caso di pareggio).

Compito

Dato un tabellone Tic-Tac-Toe alla fine di una partita (sotto forma di una stringa, una matrice, un elenco piatto di 9 valori ordinati, qualsiasi altro formato decente), determina chi vince la partita.

  • L'input consisterà in valori distinti e coerenti , uno per X, uno per Oe un altro che rappresenta un punto vuoto.

  • Il tuo programma dovrebbe essere in grado di produrre 3 valori distinti, coerenti e non vuoti: uno nel caso Xvince, un altro nel caso Ovince o un altro se i giocatori sono in parità.

    Si prega di specificare questi valori nella risposta. Puoi presumere che l'ingresso sarà una scheda Tic-Tac-Toe valida.

Casi test

X, O, _Sono i valori di ingresso qui; X wins, O winsE Tiesono per l'uscita.

X O X
O X _
O _ X

Uscita: X wins.

X _ O
X O _
X O X

Uscita: X wins.

X O X
_ O X
_ O _

Uscita: O wins.

X O X
O O X
X X O

Uscita: Tie.


Come al solito, si applicano tutte le nostre regole standard. Questo è , il codice più corto in byte in ogni lingua vince!


2
Esci dal mio cervello! Letteralmente ho avuto un'idea per una sfida di Noughts & Crosses che stavo per Sanbox lunedì. Poi apro il sito e vedo questo!
Shaggy,

1
@Shaggy Per citare qualcuno della serie "Fast and Furious": Troppo lento! ; p
Mr. Xcoder,

Va bene, la mia idea era per una versione giocabile, supponendo che non sia già stato fatto.
Shaggy,

4
@Laikoni Non penso che sia un duplicato, dal momento che questo ha input e output molto più flessibili e ha anche caselle vuote, e questo ti permette anche di supporre che l'input sia una scheda valida.
Erik the Outgolfer,

1
@Joshua Si tratta di creare un gioco Tic-tac-toe. Si tratta di classificarne uno.
Doniel,

Risposte:


6

Gelatina ,  16 15  14 byte

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

Un collegamento monadico che accetta un elenco di elenchi (le righe - o le colonne) con i valori:

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

Risultati di ritorno:

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

Nota: utilizzando un valore zero per _ e valori uguali ma opposti per Xe O, questo valore (qui 0.155) può essere compreso nell'intervallo (1/6, 1/7)(esclusivo ad entrambe le estremità) - Ho scelto solo un valore in quell'intervallo che ha dato un risultato in virgola mobile rappresentabile con precisione per i casi vincenti.

Provalo online!

Come?

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ì, penso che qualsiasi risposta in lingua esoterica dovrebbe avere una spiegazione (e mi piace anche vedere spiegazioni per le lingue normali!)
Jonathan Allan,

Grazie per averlo aggiunto! Ottimo approccio, molto più intelligente di quello che ho pensato di ... Bello
Mr. Xcoder

6

Javascript (ES6), 103 87 byte

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

Ingresso

  • X è rappresentato come 1
  • O è rappresentato come 2
  • _ è rappresentato come 0

Produzione

  • X vittorie è rappresentato come "111"
  • O vittorie è rappresentato come "000"
  • La cravatta è rappresentata come "T"

Spiegazione

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

Casi test

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


"Il tuo programma dovrebbe essere in grado di produrre 3 valori distinti, coerenti e non vuoti ", quindi non puoi produrre stringhe vuote per il legame.
RedClover,

1
@Soaku Mio male, ho perso quella parte delle regole.
Herman L

4

Gelatina , 18 byte

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

Provalo online!

X= 1, O= -1, _= 0
X wins = [1, 1, 1], O wins = [-1, -1, -1], Tie = 0
Inserimento come elenco di 3 elenchi di 3 elementi in (1, -1, 0)ciascuno.


Wow Nice ... Quando hai finito di giocare a golf, aggiungi i valori I / O e una spiegazione :-)
Mr. Xcoder

Ecco un approccio simile con un test leggermente più breve. Prende X= 1, O= 2, _= 3, restituisce 1(X vince), 2(O vince) o 3(pareggio).
Arnauld,

@Arnauld grazie per l'accorciamento
Erik the Outgolfer,

3

Python 3 , 73 byte

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

Provalo online!


Python 2 , 100 95 92 87 82 77 byte

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

Provalo online!


Accetta input come una stringa separata da nuova riga di XO_

Uscite:

  • {'XXX'} per X,
  • {'OOO'} per O
  • {} per un pareggio

Funziona tagliando la stringa in righe colonne e diagonali:

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

quindi 'XXX'e'OOO'vengono confrontati con le sezioni.

Accetta input come una stringa separata da nuova riga di XO_

Uscite:

  • {'XXX'}per X,
  • {'OOO'} per O
  • {} per un pareggio

Funziona tagliando la stringa in righe colonne e diagonali:

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

quindi 'XXX'e 'OOO'vengono confrontati con le sezioni.


Python slicing FTW Comunque, 81 byte , dovrebbe funzionare, credo.
totalmente umano il

@icrieverytim [2::2]taglia a 3579, mentre [2:8:2]357
TFeld

Python 3, 73 byte .
Jonathan Frech,

3

R, 118 116 115 byte

Grazie a @ user2390246 per due byte extra.

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

Leggermente non golfato:

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
 }

Restituisce Xse X vince, Ose O vince e Tin caso di pareggio.

Provalo online!


1
M[c(3,5,7)]è più corto per la diagonale opposta
user2390246

3

Perl 5 , 58 byte

56 byte codice + 2 fpr -p0.

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

Provalo online!

Uscite Xe Oper vittorie o Tper pareggio. Include un sacco di codice intestazione / piè di pagina per testare tutto in una volta.


Alternativa, 58 byte

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

Provalo online!


2

Python 2 , 124 118 117 115 byte

  • Hai salvato sei byte grazie a Erik the Outgolfer ; usando una stringa per evitare le virgole.
  • Salvato un byte grazie a Mr. Xcoder ; giocare [j*3:j*3+3]a golf a[j*3:][:3] .
  • Salvato due byte usando un numero magico per comprimere la stringa.
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]

Provalo online!

Valori di input / output

  • X è rappresentato come 1
  • O è rappresentato come 2
  • _ è rappresentato come None

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

@EriktheOutgolfer Grazie. Stavo cercando di giocare a golf nella lista di numeri interi usando map(ord,"..."), anche se un nulbyte nel mezzo di una stringa non ha funzionato ...
Jonathan Frech,

117 byte . [j*3:j*3+3]lo è [j*3:][:3]. Come nota a margine, j*3+3è lo stesso di -~j*3, ma anche 118 byte.
Mr. Xcoder,

@JonathanFrech Sembra che tu abbia un extra 01234567...
Erik the Outgolfer

1
@ Mr.Xcoder Grazie. Oggi ho imparato un nuovo golf da affettare.
Jonathan Frech,

2

Python 3 , 173 byte

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)

Provalo online!

  • Input come matrice di 1 == X, 0 == O, -1 == _

  • Output come valore singolo: 2 == X, 1 == O, 0 == TIE

-8 byte grazie a Erik the Outgolfer


Puoi sostituire la prima riga con lambda x:h(x,1)*2or+h(x,0)-8 byte e 0 == TIE(che è più carino imo).
Erik the Outgolfer,

@EriktheOutgolfer cool, grazie
HyperNeutrino

2

PHP, 70 byte

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

Presuppone -n(valori predefiniti dell'interprete). Inoltre richiede -R(esegui <code>per ogni riga di input), conteggiato come uno.

L'input viene preso su una sola riga (esattamente come nella descrizione del problema, tranne che con tutti gli spazi rimossi).

L'output è il seguente: 1→ X vittorie, -1→ O vittorie,0 → pareggio.

Provalo online!


Non è necessario disporre di intere stringhe, è possibile scegliere i valori di output. 'X Wins'può essere cambiato in 'X'(o anche un intero - diciamo 1). Lo stesso vale per 'O wins'e Tie. Detto questo, 109 byte .
Mr. Xcoder,

@ Mr.Xcoder grazie per il chiarimento.
primo

1

Retina , 49 byte

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

Provalo online! Prende l'input come una stringa di 11 caratteri di 9 Xs, Os o -s in tre gruppi di tre separati da ;s, sebbene il collegamento includa un'intestazione che traduce i casi di test dati in questo formato. Funziona abbinando una linea vincente direttamente usando un gruppo di bilanciamento per garantire che i tre personaggi corrispondenti siano equidistanti. (Le distanze appropriate sono 0 (linea orizzontale), 4 (diagonale inversa), 5 (linea verticale) o 6 (diagonale); altre distanze colpirebbero ;o si estenderebbero al di fuori della corda.)


1

Java 8, 112 108 106 104 90 102 93 byte

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

+12 byte (90 → 102) a causa della correzione di bug che controllava solo una diagonale anziché entrambi ..
-9 byte (102 → 93) usando replaceAllinvece dimatches .

Ingresso in formato XOX OX_ O_X, di output X, OoT .

Spiegazione:

Provalo qui.

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)

Spiegazione 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 byte

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

Provalo online!

... Immagino che potresti chiamare questa forza bruta ... Pensavo che potesse esserci qualche merito ...


0

Retina , 51 byte

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

Porta della mia risposta Java 8 . Ingresso in formato XOX OX_ O_X, di output X, Oo T.

Spiegazione:

Provalo qui.

.*(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 byte

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

Ungolfed:

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

Spiegazione

Codifica:

X = 2
O = 3
_ = 1

La nostra strategia di alto livello è innanzitutto quella di creare una matrice per ognuna delle quali le righe sono una possibile vittoria. La riga uno è diagonale /, la riga 2 è diagonale \, le tre righe successive sono le righe e le tre righe finali sono le colonne. Questa parte è realizzata dalla frase (usando Item Amend }):

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

Infine prendiamo il GCD di ogni riga:

+./"1

Grazie alla nostra codifica, qualsiasi riga con uno spazio vuoto avrà un GCD pari a 1, così come qualsiasi riga che contiene qualsiasi combinazione di X e O, poiché 2 e 3 sono coprimi. Quindi tutto ciò che dobbiamo fare è trovare l'elemento massimo:>./

Se il gioco è in pareggio, sarà 1. Se un giocatore vince, sarà il numero di quel giocatore.

Provalo online!


0

JavaScript, 66 byte

([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)

Mantenerlo semplice.

  • Input: una stringa, o matrice di numeri o stringhe, con 0corrispondenti a uno spazio vuoto, 1una X e 2una O.
  • Uscita: 0per un pareggio, 1per X vittoria, 2per O vittoria.

Ampliato, leggermente commentato:

( [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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.