Tic-Tac-Toe - X чи O?


14

Фон

Перейдіть до "Завдання", якщо ви знайомі з Tic-Tac-Toe (я думаю, що більшість!)

Tic-Tac-Toe - відома гра для двох гравців. Він складається з дошки 3x3, яка поступово заповнюється двома гравцями (пояснення нижче); Перший гравець використовує символ, Xа другий використовує O. Переможець першим отримує 3 послідовних і однакових символи ( Xабо O), горизонтально, вертикально або по діагоналі. Якщо дошка заповнена і жодному з гравців не вдалося отримати трьох поспіль персонажів, як зазначено вище, гра закінчується внічию. Зауважте, що в кінці гри можуть бути порожні місця, якщо будь-який з гравців виграє менше ніж 9 ходів (це не може відбутися у разі нічиєї).

Завдання

З огляду на дошку Tic-Tac-Toe в кінці гри (у вигляді рядка, матриці, плоского списку з 9 упорядкованих значень, будь-якого іншого гідного формату), визначте, хто виграє гру.

  • Вхід буде складатися з чітких і послідовних значень: одне для X, одне за Oінше, яке представляє порожнє місце.

  • Ваша програма повинна мати можливість виводити 3 чіткі, послідовні та непорожні значення: одне у випадку Xвиграшу, інше у випадку Oвиграшу чи інше, якщо гравці зв'язані.

    Вкажіть, будь ласка, ці значення у своїй відповіді. Можна припустити, що введенням буде дійсна плата Tic-Tac-Toe.

Випробування

X, O, _Є вхідними значеннями тут; X wins, O winsі Tieдля виходу.

X O X
O X _
O _ X

Вихід: X wins.

X _ O
X O _
X O X

Вихід: X wins.

X O X
_ O X
_ O _

Вихід: O wins.

X O X
O O X
X X O

Вихід: Tie.


Як завжди, діють усі наші стандартні правила. Це , виграє найкоротший код у байтах на кожній мові!


2
Вийди з мого мозку! Буквально якраз виникла ідея для виклику Noughts & Crossross, який я збирався Sanbox у понеділок. Тоді я тріщини відкриваю сайт і бачу це!
Shaggy

1
@Shaggy Навести когось із серії "Швидкі та люті": Занадто повільно! ; p
Містер Xcoder

Добре, моя ідея була для відтворюваної версії, припускаючи, що цього ще не зроблено.
Кудлатий

4
@Laikoni Я не думаю, що це дуп, оскільки це має більш гнучкі введення та виведення, а також має порожні поля, і це також дозволяє припустити, що вхід є дійсною дошкою.
Erik the Outgolfer

1
@Joshua Це про те, щоб зробити гру «Тік-так-носок». Йдеться про оцінку одного.
DonielF

Відповіді:


6

Желе ,  16 15  14 байт

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

Монадічне посилання, що приймає список списків (рядків - або стовпців) зі значеннями:

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

Повернення результатів:

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

Примітка: використовуючи значення нуля для _та рівних, але протилежних значень для Xі O, це значення (тут 0.155) може бути в діапазоні (1/6, 1/7)(винятково на обох кінцях) - я вибрав лише значення в цьому діапазоні, яке дало чітко представлений результат з плаваючою точкою для виграшних випадків.

Спробуйте в Інтернеті!

Як?

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)

Так, я думаю, що будь-які відповіді на езотеричну мову повинні мати пояснення (і мені подобається бачити пояснення і для звичайних мов!)
Джонатан Аллан

Дякуємо, що додали його! Дуже хороший підхід, набагато розумніший за те, що я хотів би ... Ніцца
містер Xcoder

6

Javascript (ES6), 103 87 байт

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

Вхідні дані

  • X представлений як 1
  • O представлений як 2
  • _ представлено як 0

Вихідні дані

  • X виграш представлений як "111"
  • O виграші представлені як "000"
  • Краватка представлена ​​як "T"

Пояснення

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

Тестові справи

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


"Ваша програма повинна вміти виводити 3 чіткі, послідовні та не порожні значення ", тому ви не можете виводити порожню рядок для прив'язки.
RedClover

1
@Soaku Моє погано, я пропустив цю частину правил.
Герман Л

4

Желе , 18 байт

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

Спробуйте в Інтернеті!

X= 1, O= -1, _= 0
X win = [1, 1, 1], O win = [-1, -1, -1], Tie = 0
Введіть як список 3 списків з 3 елементів у (1, -1, 0)кожному.


Нічого собі приємно ... Коли ви закінчите гольф, додайте значення вводу-виводу та пояснення :-)
Містер Xcoder

Ось подібний підхід з трохи коротшим тестом. Бере X= 1, O= 2, _= 3, повертає 1(X виграє), 2(O виграє) або 3(ніта).
Арнольд

@Arnauld дякую за скорочення
Erik the Outgolfer

3

Python 3 , 73 байти

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

Спробуйте в Інтернеті!


Python 2 , 100 95 92 87 82 77 байт

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

Спробуйте в Інтернеті!


Приймає дані як рядок, розділений новим рядком XO_

Виходи:

  • {'XXX'} для X,
  • {'OOO'} для O
  • {} за краватку

Працює, розбиваючи рядок у стовпці та діагоналі рядків:

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

то 'XXX'і'OOO' перевіряються на шматочки.

Приймає дані як рядок, розділений новим рядком XO_

Виходи:

  • {'XXX'}для X,
  • {'OOO'} для O
  • {} за краватку

Працює, розбиваючи рядок у стовпці та діагоналі рядків:

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

потім 'XXX'і'OOO' перевіряються на шматочки.


Нарізка Python FTW У будь-якому випадку, 81 байт , повинен працювати, я думаю.
повністюлюдський

@icrieverytim [2::2]скибочки 3579, а [2:8:2]дає357
TFeld


3

R, 118 116 115 байт

Дякуємо @ user2390246 за два зайвих байти.

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

Трохи незворушений:

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
 }

Повертається, Xякщо виграє X, Oякщо виграє O та Tу разі нічия

Спробуйте в Інтернеті!


1
M[c(3,5,7)]коротша для протилежної діагоналі
користувач2390246

3

Perl 5 , 58 байт

56 байт код + 2 fpr -p0.

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

Спробуйте в Інтернеті!

Виходи Xі Oна виграші, або Tна нічию. Включає купу коду колонтитулу / колонтитула для тестування всіх одночасно.


Альтернативно, 58 байт

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

Спробуйте в Інтернеті!


2

Python 2 , 124 118 117 115 байт

  • Збережено шість байтів завдяки Еріку Погоровому ; використовуючи рядок, щоб уникнути коми.
  • Збережено один байт завдяки панові Xcoder ; гольф [j*3:j*3+3]до [j*3:][:3].
  • Збережено два байти за допомогою магічного числа для стискання рядка.
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]

Спробуйте в Інтернеті!

Значення вводу / виводу

  • X представлено як 1
  • O представлено як 2
  • _ представлено як None

[8,0,3,6,1,4,7,2,5,8,0,4,8,2,4,6]->map(int,'8036147258048246')
Ерік Аутгольфер

@EriktheOutgolfer Дякую Я намагався гольфувати цілий список, використовуючи map(ord,"..."), хоча nulбайт посеред рядка не вийшов ...
Джонатан Фрех

117 байт . [j*3:j*3+3]є [j*3:][:3]. Як бічна нота - j*3+3це те саме -~j*3, що і 118 байт.
Містер Xcoder

@JonathanFrech У вас, здається, у вас є додаткова 01234567...
Erik the Outgolfer

1
@ Mr.Xcoder Спасибі Дізналися про новий гольф нарізки сьогодні.
Джонатан Фрех

2

Пітон 3 , 173 байти

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)

Спробуйте в Інтернеті!

  • Введення як матриця 1 == X, 0 == O, -1 == _

  • Вихід як одне значення: 2 == X, 1 == O, 0 == TIE

-8 байтів завдяки Еріку Переможнику


Ви можете замінити перший рядок lambda x:h(x,1)*2or+h(x,0)на -8 байт і 0 == TIE(що гарніше imo).
Ерік Аутгольфер

@EriktheOutgolfer класно, спасибі
HyperNeutrino

2

PHP, 70 байт

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

Припускає -n(за замовчуванням перекладача). Додатково потрібно -R(виконати <code>для кожного рядка введення), що рахується як один.

Введення проводиться в одному рядку (точно так само, як і в описі проблеми, за винятком всього пробілу).

Вихід такий: 1→ X Wins, -1→ O Wins, 0→ Tie.

Спробуйте в Інтернеті!


Вам не потрібно мати цілі рядки, ви можете вибрати вихідні значення. 'X Wins'може бути змінено на 'X'(або навіть ціле число - сказати 1). Те саме стосується 'O wins'і Tie. Як сказано, 109 байт .
Містер Xcoder

@ Mr.Xcoder дякую за роз’яснення.
примо

1

Сітківка , 49 байт

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

Спробуйте в Інтернеті! Вводиться як 11-символьний рядок розміром 9 Xs, Os або -s у трьох групах з трьох, розділених ;s, хоча посилання включає заголовок, який переводить задані тестові випадки у цей формат. Працює шляхом зіставлення виграшної лінії безпосередньо, використовуючи балансуючу групу, щоб забезпечити три рівні відповідні символи. (Відповідні відстані - 0 (горизонтальна лінія), 4 (зворотна діагональ), 5 (вертикальна лінія) або 6 (діагональ); інші відстані потраплятимуть у ;або витягнутися за межі рядка.)


1

Java 8, 112 108 106 104 90 102 93 байт

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

+12 байт (90 → 102) за рахунок виправлення помилок лише перевірки однієї діагоналі замість обох ..
-9 байт (102 → 93), використовуючиreplaceAll замістьmatches .

Вхідні дані в форматі XOX OX_ O_X, вихід X, Oабо T.

Пояснення:

Спробуйте тут.

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)

Зразки пояснення:

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

Сітківка , 51 байт

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

Порт моєї відповіді Java 8 . Вхідні дані в форматі XOX OX_ O_X, вихід X, Oабо T.

Пояснення:

Спробуйте тут.

.*(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 байти

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

Безголівки:

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

Пояснення

Кодування:

X = 2
O = 3
_ = 1

Наша стратегія на високому рівні - це спершу створити матрицю, у кожному з рядків якої можлива перемога. Рядок один - діагональний /, рядок 2 - діагональний \, наступні три рядки - це рядки, а останні три рядки - стовпці. Ця частина виконується фразою (використовуючи пункт Змінити }):

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

Нарешті ми беремо GCD кожного ряду:

+./"1

Завдяки нашому кодуванню, будь-який рядок із пропуском матиме GCD 1, як і будь-який рядок, який містить будь-яку суміш Xs та Os, оскільки 2 і 3 є спільними. Отже, все, що нам потрібно зробити далі - це знайти максимальний елемент:>./

Якщо гра зрівняється, це буде 1. Якщо гравець виграє, це буде номер цього гравця.

Спробуйте в Інтернеті!


0

JavaScript, 66 байт

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

Зберігати це просто.

  • Введення: Рядок або масив чисел чи рядків із 0відповідним порожнім пробілом, 1X та 2O.
  • Вихід: 0 за нічию, 1за перемогу X, 2за перемогу O.

Розгорнутий, злегка прокоментований:

( [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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.