Bestimme den Sieg in Tictactoe

19

Lass uns Code Golf spielen!

Bei einem Tic-Tac-Toe-Board-Status (Beispiel :)

|x|x|o|
|x|o|x|
|o|o|x|

Bestimmen Sie, ob ein Spiel winein loseoder ist cat. Ihr Code sollte eine dieser Optionen mit einem bestimmten Status ausgeben. Das obige Spiel sollte ausgegeben werdenlose

Um es klar auszudrücken: Ein Gewinn ist definiert als 3 xSekunden hintereinander (diagonal, horizontal, vertikal). Eine Niederlage ist 3 oSekunden hintereinander, während eine catPartie in keiner hintereinander ist.

Um die Dinge interessant zu machen, müssen Sie Ihre Eingabestruktur für den Zustand bestimmen, den Sie dann erklären müssen. Zum Beispiel xxoxoxooxist ein gültiger Zustand wie oben, wo jedes der Zeichen von links nach rechts, von oben nach unten gelesen wird. [['x','x','o'],['x','o','x'],['o','o','x']]ist das Spiel in mehrdimensionaler Anordnung in ähnlicher Weise zu lesen. Während 0x1a9das Hex für 110101001eine geeignete Komprimierung ist, 1kann es für xs manipuliert werden und 0kann für manipuliert werden o.

Aber das sind nur ein paar Ideen, ich bin mir sicher, dass Sie viele von Ihnen haben könnten.

Grundregeln:

  1. Ihr Programm muss in der Lage sein, jeden lebensfähigen Zustand zu akzeptieren.
  2. Die Eingabeform muss einen beliebigen Zustand abbilden können.
  3. "Der Gewinnzustand muss aus der Tafel ermittelt werden"
  4. Nehmen Sie eine komplette Karte an
  5. Winvorher losezum Beispiel im Fall 'xxxoooxxx'

Die niedrigste Anzahl an Charakteren gewinnt

Dylan Madisetti
quelle
1
Ich mag diese Eingabestruktur:, (win|lose|cat) [xo]{9}bei der das erste Wort angibt, ob das Spiel ein Gewinn, eine Niederlage oder eine Katze (?) Für Spieler x ist. Kann jeden Staat vertreten.
Runer112
2
Kann ich eine Regel vorschlagen wie "Der Gewinnstatus muss vom Board bestimmt werden" oder "Die Eingabe darf außer dem Boardstatus keine Informationen enthalten"?
undergroundmonorail
3
Gehen wir nur von legalen Spielen aus? Wenn ja, wären bestimmte Zustände unmöglich, dh XXX OOO XXX, aber ansonsten schließen einige Vollpension-Zustände dies als viertes unmögliches Ergebnis ein, wobei X gewinnt, aber O auch gewinnt.
Aufstand
10
warum "Katze" aus Interesse?
Chris
7
@DylanMadisetti: noch nie gehört und googlign für "win lose cat" kam mit nichts auf. Ich wäre persönlich mit Krawatte oder Malen gegangen. Oder im Falle dieses Spiels vielleicht "Unvermeidlichkeit". ;-) Was die Konkurrenz angeht, macht es mir allerdings nicht viel aus. Eine Zeichenfolge ist eine Zeichenfolge. ;-)
Chris

Antworten:

11

Ruby 2.0, 85 Zeichen

Hier ist eine einfache Bitmasken-basierte Lösung in Ruby:

d=gets.hex
$><<[292,146,73,448,56,7,273,84].map{|m|d&m<1?:lose:d&m<m ?:cat: :win}.max

Die Karte wird als Hex-Zahl dargestellt, die aus neun Bits besteht, die den neun Quadraten entsprechen. 1 ist ein X, 0 ist ein O. Dies ist genau wie das 0x1a9Beispiel in der Frage, obwohl die0x optional ist!

Es gibt wahrscheinlich eine bessere Möglichkeit, die Bitmasken zu erstellen, als nur eine große Liste fest zu codieren. Ich nehme gerne Vorschläge entgegen.

Sehen Sie hier, wie es auf Ideone läuft .

Paul Prestidge
quelle
1
Ihre Liste enthält 273zweimal. Und die maxIdee gefällt mir sehr gut !
Ventero
1
Oh @Ventero, immer mit den dunklen Optimierungen (danke)
Paul Prestidge
Auf einer Tafel können leere Stellen sein. Ihr Eingabeformat berücksichtigt dies nicht und kann daher keinen funktionsfähigen Spielstatus darstellen.
Stephen Ostermiller
2
@StephenOstermiller Regel 4: Nehmen Sie ein komplettes Board an. Sie haben Recht, dass diese Regel möglicherweise gegen die Regeln 1 und 2 verstößt. Wenn Sie jedoch alle Kommentare zu der Frage lesen, die meiner Meinung nach im Sinn der Frage liegt (unvollständige Bretter werden nicht behandelt, während vollständige, aber illegale Bretter). Allerdings denke ich, dass Oktal ein benutzerfreundlicheres Eingabeformat wäre als Hex.
Level River St
1
Verstanden, ich dachte, komplett bedeutete etwas anderes.
Stephen Ostermiller
10

Mathematica, 84 Zeichen

a=Input[];Which[Max@#>2,win,Min@#<1,lose,1>0,cat]&@{Tr@a,Tr@Reverse@a,Tr/@a,Total@a}

Eingabeformat: {{1, 1, 0}, {1, 0, 1}, {0, 0, 1}}

Alephalpha
quelle
Was passiert hier?
Siehe auch
3
@TheRare Start von rechts. Tr@aist die Spur des Feldes (Summe über Diagonale), Tr@Reverse@aist die Spur des umgedrehten Feldes (einige über Antidiagonale), Tr/@awird Trauf jede Zeile angewendet, was Ihnen die Summe über jede Zeile Total@agibt , gibt Ihnen die Summe über jede Spalte. Sie haben also im Grunde alle 8 Zeilen, die Sie überprüfen müssen. Dann wird das WhichDing darauf angewendet (im Grunde genommen eine if/elseif/elseAussage), wobei #diese Liste von 8 Werten repräsentiert. ifes gibt einen, den 3du gewinnst, else ifes gibt einen, den 0du verlierst, else if 1>0(wahr) cat.
Martin Ender
6

Bash: 283 262 258

Mit einer relativ benutzerfreundlichen Oberfläche.

t(){ sed 's/X/true/g;s/O/false/g'<<<$@;}
y(){ t $(sed 's/X/Q/g;s/O/X/g;s/Q/O/g'<<<$@);}
f(){($1&&$2&&$3)||($1&&$5&&$9)||($1&&$4&&$7)||($2&&$5&&$8)||($3&&$5&&$7)||($3&&$6&&$9)||($4&&$5&&$6)||($7&&$8&&$9)}
f $(t $@)&&echo win||(f $(y $@)&&echo lose)||echo cat

Ausführen bash tictactoe.sh O X O X O X X O X

Hinweis: Die Liste der 9 Positionen ist eine Standardmatrixdarstellung. Es spielt keine Rolle, ob die Tafel in Spalten- oder Zeilenmajor dargestellt wird, von links nach rechts oder von oben nach unten gelesen wird - Spiele mit Nullen und Kreuzen (oder Tic Tac Toe, wenn Sie darauf bestehen) sind symmetrisch, daher sollte die Eingabereihenfolge irrelevant sein zum Ergebnis bei jeder korrekten Implementierung, solange die Eingabe linear ist.

Edit: Danke an hjk für den kürzeren Syntaxvorschlag.

Randalieren
quelle
Überlegen t() { ... }statt function t? Kann dort einige Zeichen speichern. :)
hjk
Ich hatte die alternative Funktionssyntax völlig vergessen - danke!
Aufstand
Leerzeichen sind nicht erforderlich <<<, um weitere vier Zeichen zu speichern.
Michael Mior
4

Befunge 93 - 375

Nimmt eine Binärzeichenfolge als Eingabe.

99>~\1-:!!|>v  
>0v>v>v   >^$>v
^+ + +    0<:p:
>#+#+#+    ^246
^+ + +    0<265
>#+#+#+    ^pp6
^+ + +    0<2++
 #+#+#+     55p
   0 0      552
  >^>^>0v   +46
v+ + +  <   ppp
>0 + + + v  444
   v!!-3:<< 246
  v_"ni"v   ppp
  0v" w"<   :+:
  \>,,,,@   266
  ->,,,@    555
  !^"cat"_^ 645
  !>:9-! ^  +:+
  >|        p:p
   >"eso"v  6p6
 @,,,,"l"<  246
            p2p
            >^ 
  v       <^  <

Liest die Zeichenfolge. Bruteforce schreibt es (den am weitesten rechts stehenden Streifen) als Matrix zwischen

^+ + + 
>#+#+#+
^+ + + 
>#+#+#+
^+ + + 
 #+#+#+

Gitter hinzufügen (idk). Bestimmt die Summe der Spalten, Zeilen und zwei Diagnosen. Vergleicht diese Werte mit 3 ("gewinnen") oder 0 ("verlieren"). Wenn alle Werte gleich 1 oder 2 sind, wird gezogen ("katze").

AndoDaan
quelle
4

GolfScript, 27 Zeichen

70&.{~"win""lose"if}"cat"if

Das Eingabeformat ist eine Zeichenfolge, die aus acht oktalen Ziffern besteht, wobei jede (redundant) drei aufeinanderfolgende Quadrate auf der Karte codiert:

  • Die ersten drei Ziffern codieren jeweils eine einzelne Reihe der Tafel von oben nach unten und von links nach rechts.
  • Die folgenden drei Ziffern codieren jeweils eine einzelne Spalte der Tafel von links nach rechts und von oben nach unten.
  • Die letzten beiden Ziffern codieren jeweils eine der Diagonalen (zuerst von links oben nach rechts unten, dann von links unten nach rechts oben).

Um eine Folge (Zeile / Spalte / Diagonale) von drei Quadraten als Oktalziffer zu codieren, ersetzen Sie jede xin der Folge durch eine 1 und jede odurch eine 0 und interpretieren Sie die resultierende Folge von Einsen und Nullen als Binärzahl zwischen 0 und 7 inklusive.

Dieses Eingabeformat ist ziemlich redundant (alle Kartenpositionen sind mindestens zweimal codiert, die mittlere Position ist viermal codiert), es repräsentiert jedoch eindeutig jeden möglichen Zustand einer vollständig gefüllten Tic-Tac-Toe-Karte und codiert die Karte nicht direkt Gewinner in den Eingang.

Die Eingabe kann optional Leerzeichen oder andere Trennzeichen zwischen den Ziffern enthalten. Tatsächlich kümmert sich das Programm nur darum, ob die Eingabezeichenfolge die Ziffern 7oder enthält 0.

Zum Beispiel die Beispieltafel:

|x|x|o|
|x|o|x|
|o|o|x|

kann durch die Eingabe dargestellt werden:

651 643 50

Der Einfachheit halber finden Sie hier ein GolfScript-Programm, mit dem Sie ein ASCII-Grafikkartenlayout, wie in der obigen Aufforderung gezeigt, in eine für dieses Programm geeignete Eingabezeichenfolge konvertieren können:

."XOxo"--[{1&!}/]:a[3/.zip"048642"{15&a=}%3/]{{2base""+}%}%" "*

Dieser Konverter ignoriert alle Zeichen außer xund oin beiden Fällen in seiner Eingabe. Es wird eine einstellige Zeichenfolge (mit Leerzeichen wie oben gezeigt) erstellt, die in das obige Gewinnermittlungsprogramm eingespeist werden kann, sodass die Verkettung dieser beiden Programme verwendet werden kann, um den Gewinner direkt von der ASCII-Zeichenfläche aus zu ermitteln.

Hier ist auch ein Umkehrwandler, um zu demonstrieren, dass der Eingang tatsächlich die Karte eindeutig darstellt:

.56,48>-- 3<{2base-3>{"ox"=}%n}%"|".@@*+);

Ps. Hier ist eine Online-Demo dieser Lösung.

Ilmari Karonen
quelle
2
Das Eingabeformat wirkt wie ein Trick, da ein Großteil der Arbeit beim Erstellen der Eingabe anfällt.
Arkku
@Arkku: Nun ja, aber die Frage besagt ausdrücklich, dass "Sie Ihre Eingabestruktur für den Staat bestimmen müssen - was Sie dann erklären müssen." Es wird sogar eine bitgepackte Hex-Zeichenfolge als Beispiel für ein gültiges Eingabeformat angezeigt. Der einzige Unterschied zu meinem Eingabeformat besteht darin, dass ich einige Bits neu anordne und dupliziere.
Ilmari Karonen
6
Es ist genau die Vervielfältigung, die wie ein Betrug erscheint. ( zum Beispiel, ist es nicht direkt den Gewinner als das Vorhandensein von 7 oder 0 im Eingang kodieren)
Arkku
Das ist zwar eine clevere Codierung, sie ist redundant, macht die Suche nach der Lösung jedoch wesentlich effizienter als jede nicht redundante Codierung!
ARRG
3

Python 2 - 214 Bytes

b=eval(raw_input())
s=map(sum,b)
w,l='win','lose'
e="if min(s)<1:print l;a\nif max(s)>2:print w;a"
exec e+'\ns=map(sum,zip(*b))\n'+e
m=b[1][1]
for i in 0,2:
 if m==b[0][i]==b[2][abs(i-2)]:print[l,w][m];a
print'cat'

Ich bin mir sicher, dass Verbesserungen vorgenommen werden müssen.

Zu rennen:

python2 tictactoe.py <<< '[[1,1,1],[1,0,1],[0,1,0]]'

welches repräsentiert diese Tafel:

X|X|X
-----
X|O|X
-----
0|X|0

Ausgänge mit NameErrorAusnahme in jedem Fall außer cat.

untergrundbahn
quelle
Whoa, ich wusste nie darüber Bescheid <<<! +1 nur dafür.
Greg Hewgill
@ GregHewgill Es ist ziemlich praktisch. ./whatever <<< 'blah blah blah'ist das gleiche wie, echo -n 'blah blah blah' | ./whateveraber ohne einen ganzen separaten Prozess für echo.
undergroundmonorail
@undergroundmonorail echoin bashist eigentlich eine eingebaute, so gabelt keinen neuen Prozess
Bob
@ GregHewgill Es heißt Herestring
3

Haskell, 146 Zeichen

Um die Dinge interessant zu machen, müssen Sie Ihre Eingabestruktur für den Zustand bestimmen, den Sie dann erklären müssen.

IN ORDNUNG :). Meine Darstellung einer Tafel ist eine dieser 126 Zeichen

ĻŃŇʼnŊœĻŃŇʼnŊřŚşšŢťŦŨųŷŹźŢťŦŨųŷŹƒſƁƂƅƆƈƏƑ

Hier ist die Lösung in 146 Zeichen:

main=interact$(\x->case(head x)of h|elem h "ĻŃœťŦŨųŷŹƁƂƅƈƕƠƤƳƿǂdžǞǤǵǾȀȳȿɁɅɑɒɘɝɠɤɵɽʀʐʽʾː˭ˮ˰˴˼̌"->"lose";h|elem h "ƏƝƞƹǁLjǑǝȍȺɆɈɶɾʎʸ"->"cat";h->"win")

Und so funktioniert es als Hash-Skript:

import Data.List (subsequences, (\\))
import Data.Char (chr)

-- A set of indexes [0-8] describing where on the board pieces of a single color have been played
-- For example the board "OxO;Oxx;xxO" is indexes [0,2,3,8]
type Play = [Int]

-- There are 126 filled tic tac toe boards when X plays first.
--      (This is a combination of 4 OHs among 9 places : binomial(9 4) = 126)
-- perms returns a list of all such possible boards (represented by the index of their OHs).
perms = filter (\x -> 4 == length x) $ subsequences [0..8]

-- We now create an encoding for plays that brings them down to a single char.
-- The index list can be seen as an 9 bit binary word [0,2,3,8] -> '100001101'
-- This, in turn is the integer 269. The possible boards give integers between 15 and 480.
-- Let's call those PlayInts
type PlayInt = Int

permToInt [] = 0
permToInt (x:xs) = (2 ^ x) + permToInt xs 

-- Since the characters in the range 15-480 are not all printable. We offset the chars by 300, this gives the range 
-- ĻŃŇʼnŊœŗřŚşšŢťŦŨųŷŹźſƁƂƅƆƈƏƑƒƕƖƘƝƞƠƤƳƷƹƺƿǁǂDždžLjǏǑǒǕǖǘǝǞǠǤǯDZDzǵǶǸǽǾȀȄȍȎȐȔȜȳȷȹȺȿɁɂɅɆɈɏɑɒɕɖɘɝɞɠɤɯɱɲɵɶɸɽɾʀʄʍʎʐʔʜʯʱʲʵʶʸʽʾˀ˄ˍˎː˔˜˭ˮ˰˴˼̌
-- Of all distinct, printable characters
uOffset = 300

-- Transform a PlayInt to its Char representation
pIntToUnicode i = chr $ i + uOffset

-- Helper function to convert a board in a more user friendly representation to its Char
-- This accepts a representation in the form "xooxxxoxo"
convertBoard s = let play = map snd $ filter (\(c, i) -> c == 'o') $ (zip s [0..]) :: Play 
    in pIntToUnicode $ permToInt play

--
-- Now let's cook some data for our final result
--  

-- All boards as chars
allUnicode = let allInts = map permToInt perms 
    in map pIntToUnicode allInts

-- Now let's determine which boards give which outcome.

-- These are all lines, columns, and diags that give a win when filled
wins = [
        [0,1,2],[3,4,5],[6,7,8], -- lines
        [0,3,6],[1,4,7],[2,5,8], -- columns
        [0,4,8],[2,4,6] -- diagonals
    ]

isWin :: Play -> Bool   
isWin ps = let triplets = filter (\x -> 3 == length x) $ subsequences ps -- extract all triplets in the 4 or 5 moves played
    in any (\t -> t `elem` wins) triplets -- And check if any is a win line

-- These are OH wins
oWins = filter isWin perms
-- EX wins when the complement board wins
xWins = filter (isWin . complement) perms
    where complement ps = [0..9] \\ ps
-- And it's stalemate otherwise
cWins = (perms \\ oWins) \\ xWins

-- Write the cooked data to files
cookData = let toString = map (pIntToUnicode . permToInt) in do
  writeFile "all.txt" allUnicode
  writeFile "cWins.txt" $ toString cWins
  writeFile "oWins.txt" $ toString oWins
  writeFile "xWins.txt" $ toString xWins

-- Now we know that there are 48 OH-wins, 16 stalemates, and 62 EX wins (they have more because they play 5 times instead of 4).
-- Finding the solution is just checking to which set an input board belongs to (ungolfed :)
main = interact $ \x -> case (head x) of -- Only consider the first input char
    h | elem h "ĻŃœťŦŨųŷŹƁƂƅƈƕƠƤƳƿǂdžǞǤǵǾȀȳȿɁɅɑɒɘɝɠɤɵɽʀʐʽʾː˭ˮ˰˴˼̌" -> "lose" -- This string is == oWins
    h | elem h "ƏƝƞƹǁLjǑǝȍȺɆɈɶɾʎʸ" -> "cat" -- And this one == cWins
    h -> "win"
ARRG
quelle
3

JavaScript, 420 Zeichen

if((s&0x3F000)==0x3F000||(s&0x00FC0)==0x00FC0||(s&0x0003F)==0x0003F||(s&0x030C3)==0x030C3||(s&0x0C30C)==0x0C30C||(s&0x30C30)==0x30C30||(s&0x03330)==0x03330||(s&0x30303)==0x30303)return 'win'
if((s&0x3F000)==0x2A000||(s&0x00FC0)==0x00A80||(s&0x0003F)==0x0002A||(s&0x030C3)==0x02082||(s&0x0C30C)==0x08208||(s&0x30C30)==0x20820||(s&0x03330)==0x02220||(s&0x30303)==0x20202)return 'lose'
if((s&0x2AAAA)==0x2AAAA)return 'cat'

sEnthält in dieser Version eine Ganzzahl, die den Status des Spielplans darstellt. Hierbei handelt es sich um ein Bit-Array mit einem Wert, bei dem zwei Bits für jedes Quadrat auf der Karte stehen:

  • 10 - X
  • 11 - O
  • 00 - Leeres Quadrat

Diese Lösung verwendet Bit-Manipulation, um jede der acht möglichen "Drei-in-einer-Reihe" -Konfigurationen zu testen (sie werden jeweils zweimal getestet, einmal für X und einmal für O).

Ich präsentiere dies mit einer kleinen Verkleinerung von meiner Tic-Tac-Toe-Website, auf der diese detectWinFunktion als Teil eines echten Tic-Tac-Toe-Spiels verwendet wird.

Stephen Ostermiller
quelle
6
Nun, das könnte man brachial nennen, um es zu erzwingen.
Siehe auch
2

Ruby, 84 Zeichen

$><<(gets.tr("01","10")[r=/0..(0|.0.)..0|000(...)*$|^..0.0.0/]?:win:~r ?:lose: :cat)

Einfache, auf RegExp basierende Lösung. Das Eingabeformat ist eine 9-stellige Binärzeichenfolge, z. B. 110101001für die in der Frage angegebene Beispielkarte.

Ruby, 78 Zeichen

$><<(gets.tr("ox","xo")[r=/o...(o|.o.)...o|ooo|o_.o._o/]?:win:~r ?:lose: :cat)

Eingabeformat: xxo_xox_oox

Ventero
quelle
1

Haskell, 169

main=interact$(\x->last$"cat":[b|(a,b)<-[("ooo","lose"),("xxx","win")],any(==a)x]).(\x->x++(foldr(zipWith(:))(repeat[])x)++map(zipWith(!!)x)[[0..],[2,1,0]]).take 3.lines

Eingabeformat: "X" wird nur durch x, "O" nur durch dargestellt o. In jeder Zeile sind die Zeichen gleichzeitig ohne Leerzeichen usw. Die Zeilen werden durch neue Zeilen getrennt.

Erzeugt alle möglichen Zeilen / Spalten / Diagonalen, filtert [("ooo","lose"),("xxx","win")]nach ihrer Existenz auf dem Brett und wählt dann das zweite Wort im Tupel aus, damit wir wissen, welche Spieler gewonnen haben. Wir gehen voran, "cat"damit wir das letzte Element der Liste als unseren Gewinner nehmen können. Wenn beide Spieler gewonnen haben, "win"wird der letzte sein (Listenverständnis behält Reihenfolge bei). Da "cat"es immer das erste ist, wenn ein Gewinner existiert, wird es ausgewählt, aber ansonsten existiert noch ein letztes Element, da das Voranstellen "cat"die Unversehrtheit garantiert.

BEARBEITEN: Rasiert 3 Zeichen durch Ändern des letzten Listenverständnisses auf map.

YawarRaza7349
quelle
1

C, ca. 150

Es ist Mitternacht hier und ich habe noch keine Tests durchgeführt , aber ich werde das Konzept trotzdem veröffentlichen. Ich werde morgen darauf zurückkommen.

Der Benutzer gibt zwei Oktalzahlen ein (ich wollte binär verwenden, aber soweit ich weiß, unterstützt C nur Oktal):

a stellt das mittlere Quadrat dar, 1 für ein X, 0 für ein O

b ist eine neunstellige Zahl, die die Umfangsquadrate darstellt, die in einer Ecke beginnen und in derselben Ecke enden (wobei nur diese Ecke wiederholt wird), 1 für ein X, 0 für ein O.

Es gibt zwei Möglichkeiten zu gewinnen:

  1. Das mittlere Quadrat ist X ( a= 1) und zwei gegenüberliegende Quadrate sind ebenfalls X ( b&b*4096ungleich Null).

  2. Drei benachbarte Perimeterquadrate sind X ( b/8 & b & b*8ungleich Null). Dies ist nur dann ein gültiger Gewinn, wenn das mittlere Quadrat ein Kantenquadrat und kein Eckquadrat ist. Daher ist es erforderlich, auch die Maske anzuwenden m, um die Eckquadratfälle zu vermeiden.

Das Verlieren wird anhand der Variablen c erkannt, die das Inverse von b ist.

int a,b,c,m=010101010;
main(){
    scanf("%o%o",a,b);c=b^0111111111;
    printf("%s",(a&&b&b*4096)|(b/8&b&b*8&m)?"win":((!a&&c&c*4096)|(c/8&c&c*8)?"lose":"cat"));
}
Level River St
quelle
Sie haben vergessen, die Maske min der Erkennung "Verlieren" anzuwenden - c/8&c&c*8. Ich habe Ihren Code (ohne die Funktion zu testen) wie folgt erneut golfen: int a,b;t(v){return a&&v&v<<12||v/8&v&v*8&0x208208;}main(){scanf("%o%o",a,b);printf("%s",t(b)?"win":t(b^0x1249249)?"lose":"cat");}(130 Zeichen). Der wiederholte Test war lang genug, um in eine Testfunktion zu extrahieren t(); dies beseitigt die Notwendigkeit für cund m; Die Konstanten wurden in Hex konvertiert, um jeweils ein Zeichen zu speichern.
Toby Speight
Es wurde nur festgestellt, dass der keine Formatzeichenfolge printfbenötigt - geben Sie einfach die Ergebniszeichenfolge als Format an - oder putses, da die Frage nach der Ausgabe nicht nach einer neuen Zeile fragt! (spart weitere 7 Zeichen).
Toby Speight
1

Bash, 107 103

Erzeugt ein sed-Skript und führt es aus.

E / A-Format: oxo-oox-xooAusgänge lose( -zum Trennen der Zeilen verwenden Sie a). Eingang auf stdin. Benötigt GNU sed für den cBefehl.

Ich habe Regel 5 wie folgt interpretiert: "Wenn sowohl Sieg als auch Niederlage möglich sind, wähle Sieg."

Haupt code

Dies ist die eigentliche Antwort.

Eigentlich nichts Interessantes. Es definiert, $bwie /cwinZeichen gespeichert werden sollen, definiert dann den Teil der Gewinnbedingung des Skripts und verwendet dann sed y/x/o/\;s$b/close/, um xnach ound cwinnach zu konvertieren close(wodurch die Verlustbedingungen erzeugt werden). Es sendet dann die beiden Dinge und ccat(die ausgegeben werden, catwenn keine Gewinn / Verlust-Bedingung erfüllt ist) an sed.

b=/cwin
v="/xxx$b
/x...x...x$b
/x..-.x.-..x$b
/x-.x.-x$b"
sed "$v
`sed y/x/o/\;s$b/close/<<<"$v"`
ccat"

Generierter Code

Dies ist das sed-Skript, das vom Bash-Skript generiert und ausgeführt wird.

Stimmt .mit einem beliebigen Zeichen in den regulären Ausdrücken überein und gibt danach cTEXTTEXT aus und wird beendet, wenn die reguläre Ausdrücke übereinstimmen.

Dies kann als eigenständiges sed-Skript ausgeführt werden. Es ist 125 Zeichen lang, Sie können es als eine andere Lösung zählen.

/xxx/cwin
/x...x...x/cwin
/x..-.x.-..x/cwin
/x-.x.-x/cwin
/ooo/close
/o...o...o/close
/o..-.o.-..o/close
/o-.o.-o/close
ccat

quelle
1

Python 3, 45

Die Eingabe erfolgt in ieiner Liste von Zahlen, die jede Zeile, Spalte und Diagonale des Spielplans darstellen, z.

X X O
O X O
O O X

wird vertreten durch [6, 2, 1, 4, 6, 1, 7, 4].

Code :('cat','lose','win')[2 if 7 in i else 0 in i]

Pseudonym117
quelle
1

Dart - 119

(Siehe dartlang.org ).

Originalversion mit RegExp: 151 Zeichen.

main(b,{w:"cat",i,p,z}){
 for(p in["olose","xwin"])
   for(i in[0,2,3,4])
     if(b[0].contains(new RegExp('${z=p[0]}(${'.'*i}$z){2}')))
       w=p.substring(1);
  print(w);
}

Die Eingabe in der Befehlszeile umfasst 11 Zeichen, z. B. "xxx | ooo | xxx". Jedes Nicht-XO-Zeichen kann als Trennzeichen verwendet werden.

Führende Leerzeichen und Zeilenumbrüche sollten weggelassen werden, bevor Zeichen gezählt werden, aber ich schneide die internen Leerzeichen weg, wo dies möglich ist. Ich wünschte, es gäbe eine kleinere Möglichkeit, die Teilzeichenfolge zu erstellen.

Recusive Bit-Base-Version: 119 Zeichen. Die Eingabe muss eine 9-Bit-Zahl sein, wobei 1 für 'x' und 0 für 'o' steht.

main(n){
  n=int.parse(n[0]);
  z(b,r)=>b>0?b&n==b&511?"win":z(b>>9,n&b==0?"lose":r):r;
  print(z(0x9224893c01c01e2254,"cat"));
}
lrn
quelle
1

CJam, 39 38 36 Zeichen

"ᔔꉚ굌궽渒䗠脯뗠㰍㔚귇籾〳㎪䬔⹴쪳儏⃒ꈯ琉"2G#b129b:c~

Dies ist ein konvertierter Basiscode für

q3/_z__Wf%s4%\s4%]`:Q3'o*#"win"{Q'x3*#"lose""cat"?}?

Das ist 52 Zeichen lang.

Die Eingabe ist einfach die Zeichenfolgendarstellung der Platine, beginnend von links oben und zeilenweise. Beispielsweise:

oxooxooox

was zu einer winAusgabe führt. Oder

oxooxoxox

was zu einer catAusgabe usw. führt

Der Code führt einfach die folgenden drei Dinge aus:

  • q3/_ - Teilen Sie die Zeichenfolge in Teile von 3, dh pro Zeile
  • _z - Kopieren Sie das Array pro Zeile und transponieren Sie es in ein Array pro Spalte.
  • __Wf%s4%- Kehren Sie jede Reihe um und bewegen Sie sich von links nach rechts. Dies ist die sekundäre Diagonale der Platine.
  • \s4% - Holen Sie sich die Hauptdiagonale der Tafel
  • ]` - Wickeln Sie alles in Array und fassen Sie das Array zusammen.

Jetzt haben wir alle möglichen 3er-Gruppen vom Brett. Wir überprüfen einfach die Existenz von "ooo" und "xxx", um das Ergebnis zu bestimmen.

Probieren Sie es hier online aus

Optimierer
quelle
1

GNU sed, 25 Bytes

Handelt es sich bei der Eingabe um eine redundante Darstellung des Bretts mit getrennten Ansichten für Spalten, Zeilen und Diagonalen, wie sie auch in anderen Antworten verwendet werden, ist sed sehr gut geeignet, um den Endzustand des Spiels mit den wenigsten Bytes zu überprüfen.

Eingabeformat: xxx ooo xxx xox xox xox xox xox (Kartenstatus aus der Frage des OP)

/xxx/cwin
/ooo/close
ccat

Wenn das Eingabeformat nicht redundant ist ( xxx ooo xxx), funktioniert der obige sed-Code nur, wenn die darunter stehende Zeile vorangestellt wird, wodurch das Programm 96 Byte lang wird (wobei das erforderliche rFlag gezählt wird).

s/(.)(.)(.) (.)(.)(.) (.)(.)(.)/& \1\4\7 \2\5\8 \3\6\9 \1\5\9 \3\5\7/
Seshoumara
quelle
1

Bash: 208 Zeichen

y(){ tr '01' '10'<<<$@;}
f(){ x=$[($1&$2&$3)|($1&$5&$9)|($1&$4&$7)|($2&$5&$8)|($3&$5&$7)|($3&$6&$9)|($4&$5&$6)|($7&$8&$9)]; }
f $@;w=$x
f $(y $@)
([ $x -eq 1 ]&&echo lose)||([ $w -eq 1 ]&&echo win)||echo cat

Ausführen bash tictactoe.sh 0 1 0 1 0 1 1 0 1

Inspiriert von dieser Antwort .

Michael Mior
quelle
0

VB.net

In diesem Beispiel wird provision als das folgende Bitmuster codiert

q  = &B_100101_100110_011010 ' 00 Empty, 01 = O, 10 = X

Nun können wir das Ergebnis (oder den Gewinner) wie folgt bestimmen.

Dim g = {21, 1344, 86016, 66576, 16644, 4161, 65379, 4368}
Dim w = If(g.Any(Function(p)(q And p)=p),"Lose",If(g.Any(Function(p)(q And p*2)=p*2),"Win","Cat"))
Adam Speight
quelle
0

J - 97 Bytes

Nun, der einfachste verfügbare Ansatz. Die Eingabe erfolgt als 111222333, wobei die Zahlen Zeilen darstellen. Lesen Sie von links nach rechts. Spieler ist xund Feind ist o. Leere Felder können alles außer xoder sein o.

f=:(cat`lose>@{~'ooo'&c)`('win'"_)@.('xxx'&c=:+./@(r,(r|:),((r=:-:"1)(0 4 8&{,:2 4 6&{)@,))3 3&$)

Beispiele: (Anm. Ist ein Kommentar)

   f 'xoxxoxxox' NB. Victory from first and last column.
win
   f 'oxxxooxxx' NB. Victory from last row.
win
   f 'ooxxoxxxo' NB. The example case, lost to a diagonal.
lose
   f 'xxooxxxoo' NB. Nobody won.
cat
   f 'xoo xx ox' NB. Victory from diagonal.
win

Ungolfed Code eine Erklärung

row   =: -:"1                        Checks if victory can be achieved from any row.
col   =: -:"1 |:                     Checks if victory can be achieved from any column.
diag  =: -:"1 (0 4 8&{ ,: 2 4 6&{)@, Checks if victory can be achieved from diagonals.
check =: +./@(row,col,diag) 3 3&$    Checks all of the above and OR's them.

f     =: (cat`lose >@{~ 'ooo'&check)`('win'"_)@.('xxx'&check)
Check if you have won ........................@.('xxx'&check)
 If yes, return 'win' .............. ('win'"_)
 If not                   (cat`lose >@{~ 'ooo'&check)
  Check if enemy won ................... 'ooo'&check
   If yes, return 'lose'   ---`lose >@{~
   If not, return 'cat'    cat`---- >@{~
seequ
quelle
0

Python 2, 120 Bytes

b=0b101001110
l=[448,56,7,292,146,73,273,84]
print(['Win'for w in l if w&b==w]+['Lose'for w in l if w&~b==w]+['Cat'])[0]

Oder Python, 115 Bytes von der Python-Shell (2 oder 3):

b=0b101001110;l=[448,56,7,292,146,73,273,84];(['Win'for w in l if w&b==w]+['Lose'for w in l if w&~b==w]+['Cat'])[0]

Die Kartenvariable wird auf das in der Frage beschriebene Binärformat gesetzt: 1für X 0für O von links nach rechts von oben nach unten. In diesem Fall 101001110stellt

XOX
OOX
XXO

Was zur Ausgabe führt: Cat

Cees Timmerman
quelle
Was ist das Eingabeformat?
Siehe auch
0

Python ( 73 62 Zeichen)

Die Eingabe besteht aus vier Zeichenfolgen in Kleinbuchstaben, die vier verschiedene Ansichten derselben Platine darstellen, die alle zu einer einzigen Zeichenfolge verknüpft sind: zeilenweise, spaltenweise, diagonal nach rechts und diagonal nach links.

AKTUALISIEREN

Vielen Dank an theRare für den Hinweis mit einem guten Gegenbeispiel! Jede Ansicht der Karte sowie jedes Segment (Zeile oder Spalte) innerhalb einer Karte muss durch ein Zeichen getrennt werden, das weder ein "x" noch ein "o" ist, damit die Struktur der Karte auch nach der Verkettung erhalten bleibt. Die Rahmen um jede Ansicht der Tafel sind eckige Klammern ("[" und "]"), und das Trennzeichen zwischen Zeilen / Spalten ist ein Pipe-Zeichen "|".

Dies macht den Algorithmus einfach - suchen Sie nach "xxx" oder "ooo" für einen Gewinn oder Verlust. Ansonsten ist es eine Krawatte (Katze).

ZB die Tafel (von links nach rechts, von oben nach unten) ...

X | X | X X | O | X O | X | O

... wird dargestellt als "[xxx | xox | oxo]" (in Zeilen) + "[xxo | xox | xxo]" (in Spalten) + "[xoo]" (rechts) + [xoo] "(links) diag) = "[xxx | xox | oxo] [xxo | xox | xxo] [xoo] [xoo]".

Diese Python-Anweisung gibt das Spielergebnis unter Berücksichtigung der Variablen s als Eingabe aus:

print 'win' if 'xxx' in s else 'lose' if 'ooo' in s else 'cat'
Bob
quelle
Funktioniert das fürs Board OXX XOO XOX(sollte es Katze sein)?
Siehe auch
Nein ... nein, tut es nicht. Guter Fang! Ich denke, meine Lösung war etwas zu einfach ... Ups!
Bob
Ich kann nicht sagen, dass mir diese Art von Lösung nicht in den Sinn gekommen ist. :)
Siehe auch
0

Haskell (69 Zeichen)

i x=take 4$(x>>=(\y->case y of{'7'->"win";'0'->"lose";_->""}))++"cat"

Dies erfordert die gleiche Eingabe wie in dieser Antwort beschrieben . Insbesondere besteht die Eingabe aus 8 Oktalwerten, die den Binärwert jeder Zeile, Spalte und Diagonale beschreiben. Der Code bewirkt, dass jede Instanz von 7 "gewinnt", jede Instanz von 0 "verliert" und alles andere entfernt wird. Dann fügt es "cat" zum Ende hinzu und entnimmt die ersten 4 Zeichen aus dem Ergebnis.

Es gibt 4 mögliche Antworten: "verlieren", "Katze", "gewinnen", gefolgt von einem "l" und "gewinnen", gefolgt von einem "c", was die Regeln nicht verbieten :)

Anwendungsbeispiel:

i "65153806" --outputs "lose"
TheBrownMotie
quelle
0

J: 83

(;:'lose cat win'){::~>:*(-&(+/@:(*./"1)@;@(;((<0 1)&|:&.>@(;|.)(,<)|:)))-.)3 3$'x'=

Verbrauch: hängen Sie einfach eine Schnur von x und von O an und passen Sie die magische Arbeit auf. z.B. 'xxxoooxxx'.

Das innere Verb (+/@:(*./"1)@;@(;((<0 1)&|:&.>@(;|.)(,<)|:))) fasst im Grunde genommen die ursprüngliche binäre Matrix zusammen, wobei die Transponierte zusammen mit den 2 Diagonalen eingeschlossen ist. Diese Ergebnisse werden zusammengefasst. Zeilensummen werden zur Ermittlung der Gewinne herangezogen und dann aufsummiert. Ich werde dieses Verb weiter nennen Inner.

Um den Gewinner zu finden, wird die Differenz der Punktzahlen zwischen der normalen und der inversen binären Matrix vom Hook genommen (-&Inner -.).

Der Rest des Codes erstellt einfach die Ausgaben und wählt die richtige aus.

jpjacobs
quelle
0

JavaScript, 133 , 114 Zeichen

r = '/(1){3}|(1.{3}){2}1|(1.{4}){2}1|(1\|.1.\|1)/';alert(i.match(r)?'WIN':i.match(r.replace(/1/g,0))?'LOSS':'CAT')

Die Eingabe iist eine einfache Zeichenfolge mit Begrenzern für die Zeilen, z100|001|100

Bearbeiten: Die Methode wurde aktualisiert, um die Einsen im regulären Ausdruck durch Nullen zu ersetzen und den Verlustfall zu überprüfen.

thomaux
quelle
Sie können die Leerzeichen =und Anführungszeichen um das Regex-Literal entfernen . Außerdem 1...ist ein Zeichen kürzer als 1.{3}.
Nyuszika7h
1
r.test(i)ist auch ein Zeichen kürzer als i.match(r).
Nyuszika7h
0

J - 56 (26?) Char

Die Eingabe erhält eine 3x3-Matrix mit neun Zeichen, da J dies als Datentyp LOL unterstützen kann.

(win`lose`cat{::~xxx`ooo<./@i.<"1,<"1@|:,2 7{</.,</.@|.)

Beispiele:

   NB. 4 equivalent ways to input the example board
   (3 3 $ 'xxoxoxoox') ; (_3 ]\ 'xxoxoxoox') ; ('xxo','xox',:'oox') ; (];._1 '|xxo|xox|oox')
+---+---+---+---+
|xxo|xxo|xxo|xxo|
|xox|xox|xox|xox|
|oox|oox|oox|oox|
+---+---+---+---+
   (win`lose`cat{::~xxx`ooo<./@i.<"1,<"1@|:,2 7{</.,</.@|.) 3 3 $ 'xxoxoxoox'
lose
   wlc =: (win`lose`cat{::~xxx`ooo<./@i.<"1,<"1@|:,2 7{</.,</.@|.)
   wlc (3 3 $ 'xoxoxooxo')
cat
   wlc (3 3 $ 'xxxoooxxx')
win

Wenn wir die Golfscriptish-Codierung von Oktalziffern zulassen, die den Status jeder Zeile, Spalte und Diagonale redundant darstellen, dann sind es nur 26 Zeichen:

   win`lose`cat{::~7 0<./@i.] 6 5 1 6 4 3 5 0
lose
   f=:win`lose`cat{::~7 0<./@i.]
   f  7 0 7 5 5 5 5 5
win
algorithmshark
quelle
0

T-SQL (2012), 110

select max(iif(@&m=0,'lose',iif(@&m=m,'win','cat')))from(VALUES(292),(146),(73),(448),(56),(7),(273),(84))z(m)

Die Eingabe ist eine Hex-Zahl. Dies ist so ziemlich eine Übersetzung der Ruby-Lösung in T-SQL, ziemlich nett und ordentlich.

Michael B
quelle
0

Javascript 1.6, 71 Zeichen

Ich gehe von einer Eingabe als Array aus, gamedie jede Zeile, jede Spalte und jedes Diag als 3-Zeichen-Zeichenfolge enthält. Ähnlich wie die Antwort von Bob , jedoch in einem Array, nicht als verkettete Zeichenfolge.

alert(game.indexOf("xxx")>=0?"win":game.indexOf("ooo")>=0?"lose":"cat")

Kommentar von EDIT @ nyuszika7h (67 Zeichen)

alert(~game.indexOf("xxx")?"win":~game.indexOf("ooo")?"lose":"cat")
JNF
quelle
Sie können ~game.indexOf("xxx")stattdessen game.indexOf("xxx")>=0dasselbe für das andere verwenden.
Nyuszika7h
0

Java 7, 260 Bytes

String c(int[]s){int a[]=new int[8],x=0,y;for(;x<3;x++){for(y=0;y<3;a[x]+=s[x*3+y++]);for(y=0;y<3;a[x+3]+=s[y++%3]);}for(x=0;x<9;y=s[x],a[6]+=x%4<1?y:0;a[7]+=x%2<1&x>0&x++<8?y:0);x=0;for(int i:a)if(i>2)return"win";for(int i:a)if(i<1)return"loose";return"cat";}

Ungolfed & Testfälle:

Probieren Sie es hier aus.

class M{
  static String c(int[] s){
    int a[] = new int[8],
        x = 0,
        y;
    for(; x < 3; x++){
      for(y = 0; y < 3; a[x] += s[x * 3 + y++]);
      for (y = 0; y < 3; a[x + 3] += s[y++ % 3]);
    }
    for(x = 0; x < 9; y = s[x],
                      a[6] += x % 4 < 1
                               ? y
                               : 0,
                      a[7] += x % 2 < 1 & x > 0 & x++ < 8
                               ? y
                               : 0);
    x = 0;
    for(int i : a){
      if(i > 2){
        return "win";
      }
    }
    for(int i : a){
      if(i < 1){
        return "loose";
      }
    }
    return "cat";
  }

  public static void main(String[] a){
    /*  xxo
        xox
        oox  */
    System.out.println(c(new int[]{ 1, 1, 0, 1, 0, 1, 0, 0, 1 }));
    /*  xxx
        ooo
        xxx  */
    System.out.println(c(new int[]{ 1, 1, 1, 0, 0, 0, 1, 1, 1 }));
    /*  xxo
        oox
        xox  */
    System.out.println(c(new int[]{ 1, 1, 0, 0, 0, 1, 1, 0, 1 }));
  }
}

Ausgabe:

loose
win
cat
Kevin Cruijssen
quelle
0

APL (NARS), 69 Zeichen, 138 Byte

{w←3 3⍴⍵⋄x←(+/1 1⍉⊖w),(+/1 1⍉w),(+⌿w),+/w⋄3∊x:'win'⋄0∊x:'lose'⋄'cat'}

Die Eingabe sollte eine 3x3-Matrix oder ein lineares Array von 9 Elementen sein, die nur 1 (für X) und 0 (für O) sein können. Das Ergebnis ist "cat", wenn niemand gewinnt, "lose", wenn O gewinnt, "win" "wenn X gewinnt. Es wird nicht geprüft, ob eine Karte ungültig ist oder ob ein Array weniger als 9 oder mehr Elemente enthält, oder ob jedes Element <2 ist.

Als Kommentar: Es würde die Eingabe in eine 3x3-Matrix konvertieren und ein Array mit dem Namen "x" erstellen, wobei Elemente die Summe jeder Zeile, Spalte und Diagonale sind.

Einige Tests zeigen Beispiele von anderen:

  f←{w←3 3⍴⍵⋄x←(+/1 1⍉⊖w),(+/1 1⍉w),(+⌿w),+/w⋄3∊x:'win'⋄0∊x:'lose'⋄'cat'}
  f 1 2 3
win
  f 0 0 0
lose
  f 1 0 1  1 0 1  1 0 1
win
  f 0 1 1  1 0 0  1 1 1
win
  f 0 0 1  1 0 1  1 1 0
lose
  f 1 1 0  0 1 1  1 0 0
cat
  f 1 1 0  0 1 0  0 0 1
win
  f 1 1 0  1 0 1  0 0 1
lose
RosLuP
quelle