Tentukan pemenang Tic-Tac-Toe (berbasis putaran)

26

Mari bermain golf kode!

Tantangannya adalah menemukan pemenang permainan Tic-Tac-Toe.

Ini telah dilakukan berkali-kali dengan memberikan papan yang memiliki satu pemenang yang jelas tetapi di sini adalah twist:

Sel-sel diberi nomor seperti ini:

1|2|3
-+-+-
4|5|6
-+-+-
7|8|9

Anda mendapatkan larik 9 gerakan seperti itu:

{3, 5, 6, 7, 9, 8, 1, 2, 3}

Ini diuraikan sebagai berikut:

  • Pemain 1 menandai sel 3
  • Pemain 2 menandai sel 5
  • Pemain 1 menandai sel 6
  • Pemain 2 menandai sel 7
  • Pemain 1 menandai sel 9
  • Pemain 1 telah menang

Catatan: Permainan tidak berhenti setelah satu pemain menang, mungkin saja pemain yang kalah berhasil mendapatkan tiga berturut-turut setelah pemain yang menang, tetapi hanya kemenangan pertama yang diperhitungkan.

Tugas Anda sekarang untuk mendapatkan 9 angka sebagai input dan output pemain yang menang dan putaran di mana kemenangan terjadi. Jika tidak ada yang menang, hasilkan sesuatu yang konstan pilihan Anda. Anda dapat menerima input dan memberikan output melalui rata-rata / format standar.

Selamat bersenang-senang!

Beberapa contoh lagi seperti yang diminta:

{2,3,4,5,6,7,1,8,9} => Player 2 wins in round 6
{1,2,4,5,6,7,3,8,9} => Player 2 wins in round 8
{1,2,3,5,4,7,6,8,9} => Player 2 wins in round 8
Grunzwanzling
sumber
11
Selamat datang di PPCG! Ini adalah posting pertama yang bagus, tetapi biasanya kita tidak suka format input / output yang sangat ketat . Apakah Anda ingin menghapus "Player X menang di ronde Y" dan biarkan kami menampilkan dalam format yang wajar, seperti daftar [X, Y]? Dalam hal seri, dapatkah kita menghasilkan nilai konsisten lainnya? Saya sarankan begitu, karena mencetak string yang tepat itu tidak benar-benar bagian dari golf. Untuk ide tantangan di masa depan, saya sarankan menggunakan kotak pasir . :-)
Mr. Xcoder
Maaf, salah saya. Saya pikir itu benar sekarang.
Grunzwanzling
Baca tantangan sampai akhir, saya katakan bahwa mungkin ada hasil seri dan Anda dapat menampilkan sesuatu pilihan Anda ketika itu terjadi. Saya mengembalikan {2,6} ketika pemain 2 menang di babak 6 dan {0,0} ketika tidak ada yang menang.
Grunzwanzling
Bisakah kita menggunakan semuanya 0-diindeks? (sel, pemain, putaran)
Arnauld
1
"Anda mendapatkan larik 9 gerakan seperti itu: {3, 5, 6, 7, 9, 8, 1, 2, 3}" - haruskah 3benar - benar muncul dua kali?
Jonathan Allan

Jawaban:

8

Retina , 114 byte

(.)(.)
$1O$2X
^
123;;456;;789¶X
{`(.)(.*¶)(.)\1
$3$2
}`.*(.)(.)*\1(?<-2>.)*(?(2)(?!))\1.*¶(..)*
$1$#3
.*¶
T
T`d`Rd

Cobalah online! Berdasarkan jawaban saya untuk Tic-Tac-Toe - X atau O? . Keluaran X<N>jika pemain pertama menang setelah Ngiliran, O<N>jika pemain kedua menang, Tjika tidak ada yang menang. Penjelasan:

(.)(.)
$1O$2X
^
123;;456;;789¶X

Membuat papan internal, dan juga menandai setiap gerakan dengan pemain yang bergerak.

{`(.)(.*¶)(.)\1
$3$2

Berlaku bergerak.

}`.*(.)(.)*\1(?<-2>.)*(?(2)(?!))\1.*¶(..)*
$1$#3

Mencari kemenangan, dan jika ada yang ditemukan, ganti papan dengan pemenang dan jumlah gerakan yang tersisa.

.*¶
T

Jika gerakannya habis dan tidak ada yang menang maka pertandingan itu seri.

T`d`Rd

Hitung jumlah putaran dari jumlah gerakan yang tersisa.

Neil
sumber
4
Ini adalah salah satu dari lebih .... jawaban yang menggairahkan yang saya lihat di sini.
Lord Farquaad
6

MATL , 39 byte

3:g&+XIx"IX@oXK@(XIt!yXdyPXd&hK=Aa?KX@.

Output adalah

  • 1dan R, di baris terpisah, jika pengguna 1 menang di babak R ;
  • 0dan R, di baris terpisah, jika pengguna 2 menang di babak R ;
  • kosong jika tidak ada yang menang.

Cobalah online! Atau verifikasi semua kasus uji .

Penjelasan

3:       % Push [1 2 3]
g        % Convert to logical. Gives [true true true]
&+       % Matrix of all pairs of additions. Gives a 3×3 matrix, which represents
         % the board in its initial state, namely all cells contain 2. This value
         % means "cell not used yet". 1 will represent "cell marked by user 1",
         % and 0 will represent "cell marked by user 2"
XI       % Copy into clipboard I
x        % Delete
"        % Implicit input: array with moves. For each move
  I      %   Push current board state
  X@     %   Push iteration index (starting at 1), that is, current round number
  o      %   Modulo 2: gives 1 or 0. This represents the current user
  XK     %   Copy into clipboard K
  @      %   Push current move ((that is, cell index)
  (      %   Write user identifier (1 or 0) into that cell. Cells are indexed
         %   linearly in column-major order. So the board is transposed compared
         %   to that in the challenge, but that is unimportant
  XI     %   Copy updated board into clipboard I
  t!     %   Duplicate and transpose
  y      %   Duplicate from below: push copy of board
  Xd     %   Extract main diagonal as a 3×1 vector
  y      %   Duplicate from below: push copy of transposed board
  PXd    %   Flip vertically and extract main diagonal. This is the anti-diagonal
         %   of the board
  &h     %   Concatenate stack horizontally. This concatenates the board (3×3),
         %   transposed board (3×3), main diagonal (3×1 vector) and anti-diagonal
         %   (3×1) into an 3×8 matrix
  K=     %   Push current user identifier. Test for equality with each entry of the
         %   3×8 matrix
  A      %   For each column, this gives true if all its entries are true. Note 
         %   that the first three columns in the 3×8 matrix are the board columns;
         %   the next three are the board rows; and the last two columns are the
         %   main diagonal and anti-diagonal. The result is a 1×8 vector
  a      %   True if any entry is true, meaning the current user has won
  ?      %   If true
    K    %     Push current user identifier
    X@   %     Push current round number
    .    %     Break for loop
         %   Implicit end
         % Implicit end
         % Implicit display
Luis Mendo
sumber
5

Javascript (ES6), 130 byte

m=>m.reduce((l,n,i)=>l||(b[n-1]=p=i%2+1,"012,345,678,036,147,258,048,246".replace(/\d/g,m=>b[m]).match(""+p+p+p)&&[p,i+1]),0,b=[])

f=m=>m.reduce((l,n,i)=>l||(b[n-1]=p=i%2+1,"012,345,678,036,147,258,048,246".replace(/\d/g,m=>b[m]).match(""+p+p+p)&&[p,i+1]),0,b=[])
console.log(JSON.stringify(f([3,5,6,7,9,8,1,2,3])))
console.log(JSON.stringify(f([2,3,4,5,6,7,1,8,9])))
console.log(JSON.stringify(f([1,2,4,5,6,7,3,8,9])))
console.log(JSON.stringify(f([1,2,3,5,4,7,6,8,9])))

Penjelasan

m=>m.reduce((l,n,i)=>               // Reduce the input array with n as the current move
  l||(                              //  If there is already a winner, return it
  b[n-1]=p=i%2+1,                   //  Set the cell at b[n-1] to the current player p
  "012,345,678,036,147,258,048,246" //  For every digit in the list of possible rows:
    .replace(/\d/g,m=>b[m])         //   Replace it with the player at the cell
    .match(""+p+p+p)                //  If any of the rows is filled with p:
      &&[p,i+1]                     //   Return [p, current move]
),0,b=[])
Herman L.
sumber
Maukah Anda memberikan penjelasan atau versi tanpa ungolfed? Saya tertarik untuk memahami solusi Anda.
Jack
4

Java (OpenJDK 8) , 445 byte

int[] t(int[]m){int[][]f=new int[3][3];boolean z=false;for(int i=0;i<9;i++){f[m[i]%3][m[i]/3]=z?2:1;if(f[m[i]%3][0]==(z?2:1)&&f[m[i]%3][1]==(z?2:1)&&f[m[i]%3][2]==(z?2:1)||f[0][m[i]/3]==(z?2:1)&&f[1][m[i]/3]==(z?2:1)&&f[2][m[i]/3]==(z?2:1)||m[i]%3+m[i]/3==2&&f[0][2]==(z?2:1)&&f[1][1]==(z?2:1)&&f[2][0]==(z?2:1)||m[i]%3==m[i]/3&&f[0][0]==(z?2:1)&&f[1][1]==(z?2:1)&&f[2][2]==(z?2:1)){return(new int[]{(z?2:1),++i});}z=!z;}return(new int[]{0,0});}

Cobalah online!

Nilai kembali {1,8} berarti pemain 1 menang di babak 8. Nilai kembali {0,0} berarti menggambar.

Grunzwanzling
sumber
5
Kecuali Anda menghapus semua spasi yang tidak perlu, jawaban ini dianggap tidak valid karena kurangnya upaya bermain golf. Selain itu, tidak terlalu disarankan untuk menjawab tantangan Anda secepat itu, dan Anda mungkin ingin menambahkan tautan TIO sehingga kami dapat menguji kode Anda.
Tn. Xcoder
Tautan referensi: Pesaing serius , bersaing dalam tantangan Anda sendiri
user202729
Maaf, saya menyalin hal yang salah. Ini sebenarnya jauh lebih pendek
Grunzwanzling
Anda dapat melihat tips untuk bermain golf di Jawa untuk menghapus beberapa byte. Misalnya falsebisa diganti dengan 1<0, dan spasi setelah yang pertama ]bisa dihilangkan.
user202729
442 byte . Juga alasan mengapa bagian "Header" dan "Footer" ada di TIO adalah bahwa Anda tidak perlu berkomentar //Code that was submitteddan //End of code.
user202729
2

Kotlin , 236 byte

i.foldIndexed(l()to l()){o,(a,b),p->fun f(i:(Int)->Int)=b.groupBy(i).any{(_,v)->v.size>2}
if(f{(it-1)/3}|| f{it%3}|| listOf(l(1,5,9),l(3,5,7)).any{b.containsAll(it)}){return p%2+1 to o}
b to a+p}.let{null}
fun l(vararg l:Int)=l.toList()

Yg diperindahkan

    i.foldIndexed(l() to l()) { o, (a, b), p ->
        fun f(i: (Int) -> Int) = b.groupBy(i).any { (_, v) -> v.size > 2 }
        if (f { (it - 1) / 3 } || f { it % 3 } || listOf(l(1, 5, 9), l(3, 5, 7)).any { b.containsAll(it) }) {
            return p % 2 + 1 to o
        }
        b to a + p
    }.let { null }
fun l(vararg l:Int)= l.toList()

Uji

fun f(i: List<Int>): Pair<Int, Int>? =
i.foldIndexed(l()to l()){o,(a,b),p->fun f(i:(Int)->Int)=b.groupBy(i).any{(_,v)->v.size>2}
if(f{(it-1)/3}|| f{it%3}|| listOf(l(1,5,9),l(3,5,7)).any{b.containsAll(it)}){return p%2+1 to o}
b to a+p}.let{null}
fun l(vararg l:Int)=l.toList()

data class Test(val moves: List<Int>, val winner: Int, val move: Int)

val tests = listOf(
        Test(listOf(3, 5, 6, 7, 9, 8, 1, 2, 3), 1, 5),
        Test(listOf(2, 3, 4, 5, 6, 7, 1, 8, 9), 2, 6),
        Test(listOf(1, 2, 4, 5, 6, 7, 3, 8, 9), 2, 8),
        Test(listOf(1, 2, 3, 5, 4, 7, 6, 8, 9), 2, 8)
)

fun main(args: Array<String>) {
    tests.forEach { (input, winner, move) ->
        val result = f(input)
        if (result != winner to move) {
            throw AssertionError("$input ${winner to move} $result")
        }
    }
}

TIO

TryItOnline

jrtapsell
sumber
1

Python 2 , 170 byte

q=map(input().index,range(1,10))
z=zip(*[iter(q)]*3)
o='',
for l in[q[2:7:2],q[::4]]+z+zip(*z):
 r=[n%2for n in l];y=all(r)*2+1-any(r)
 if y:o+=[max(l)+1,y],
print min(o)

Cobalah online! atau Coba semua test case

#swap cell number / turn
q=map(input().index,range(1,10))
#split in 3 parts (rows)
z=zip(*[iter(q)]*3)
#starting value for the list with the results
#since string are "greater" than lists, this will
#be the output value when there is a draw
o='',
#iterate over diagonals, rows and columns
for l in[q[2:7:2],q[::4]]+z+zip(*z):
 #use %2 to separate between player 1 and 2
 r=[n%2 for n in l]
 #store in y the value of the player if the trio is a valid win, 0 otherwise
 #it's a win if all moves are from the same player
 y=all(r)*2+1-any(r)
 #if y has a valid player, add the highest turn of the trio, and the player to o
 if y:o+=[max(l)+1,y],
#output the smaller turn of the valid winning trios
print min(o)
tongkat
sumber
1

Jelly , 38 byte

;⁵s2ZṬḤ2¦SṖs3µ,ṚJị"$€;;ZEÐfṀḢµ$ƤµTḢ,ị¥

Cobalah online!

Kemenangan pemain 1: Kemenangan [round, 1]
pemain 2: [round, 2]
Tie:[0, 0]

Erik the Outgolfer
sumber
1

Python 3.6+, 137 byte

n=m=c=z=0
for a in input():m+=1<<~-int(a);c+=1;z=z or f'{c&1}:{c}'*any(m&t==t for t in[7,56,448,73,146,292,273,84]);n,m=m,n
print(z or-1)

Format output adalah winner number:roundatau -1untuk seri. Player 2 is 0Player 1 is 1. Input dalam bentuk string tak terhingga dari angka kuadrat 1-diindeks.

mypetlion
sumber
1

Jelly , 35 byte

9s3,ZU$$;ŒD$€Ẏf€⁸L€3e
s2ZÇƤ€ZFTḢ;Ḃ$

Tautan monadik mengambil daftar gerakan dan mengembalikan daftar, di [move, player]mana para pemain diidentifikasi sebagai 1(pertama yang bertindak) dan 0(kedua untuk bertindak).

Cobalah online!

Bagaimana?

9s3,ZU$$;ŒD$€Ẏf€⁸L€3e - Link 1: any winning play?: list of player's moves:
9s3                   - (range of) nine split into threes = [[1,2,3],[4,5,6],[7,8,9]]
       $              - last two links as a monad:
      $               -   last two links as a monad:
    Z                 -     transpose = [[1,4,7],[2,5,8],[3,6,9]]
     U                -     upend     = [[7,4,1],[8,5,2],[9,6,3]]
   ,                  -  pair = [[[1,2,3],[4,5,6],[7,8,9]],[[7,4,1],[8,5,2],[9,6,3]]]
           $€         - last two links as a monad for €ach:
         ŒD           -   diagonals = [[1,5,9],[2,6],[3],[7],[4,8]] or [[7,5,3],[4,2],[1],[9],[8,6]]
        ;             -  concatenate = [[1,2,3],[4,5,6],[7,8,9],[1,5,9],[2,6],[3],[7],[4,8]] or [[7,4,1],[8,5,2],[9,6,3],[7,5,3],[4,2],[1],[9],[8,6]]
             Ẏ        - tighten = [[1,2,3],[4,5,6],[7,8,9],[1,5,9],[2,6],[3],[7],[4,8],[7,4,1],[8,5,2],[9,6,3],[7,5,3],[4,2],[1],[9],[8,6]]
                      -    i.e.:    row1    row2    row3    diag\   x     x   x   x     col1    col2    col3    diag/   x     x   x   x
                      -    where x's are not long enough to matter for the rest...
                ⁸     - chain's left argument, list of player's moves
              f€      - filter to keep those moves for €ach of those lists to the left
                 L€   - length of €ach result
                   3e - 3 exists in that? (i.e. were any length 3 when filtered down to only moves made?)

s2ZÇƤ€ZFTḢ;Ḃ$ - Main link: list of the moves  e.g. [2,3,4,5,6,7,1,8,9]
s2            - split into twos                    [[2,3],[4,5],[6,7],[1,8],[9]]
  Z           - transpose                          [[2,4,6,1,9],[3,5,7,8]]
    Ƥ€        - for Ƥrefixes of €ach:
   Ç          -   call last link (1) as a monad     [0,0,0,0,0] [0,0,1,1]
      Z       - transpose                          [[0,0],[0,0],[0,1],[0,1],[0]]
       F      - flatten                            [0,0,0,0,0,1,0,1,0]
        T     - truthy indices                     [          6   8  ]
         Ḣ    - head (if empty yields 0)           6
            $ - last two links as a monad:
           Ḃ  -   modulo by 2 (evens are player 2) 0
          ;   -   concatenate                      [6,0]
Jonathan Allan
sumber
0

Python 2, 168 byte

import itertools as z
f=lambda g:next(([i%2+1,i+1]for i in range(9) if any(c for c in z.combinations([[0,6,1,8,7,5,3,2,9,4][j]for j in g[i%2:i+1:2]],3)if sum(c)==15)),0)

Output (pemain, putaran) atau 0 untuk seri.

Memetakan game ke dalam kotak ajaib 3-oleh-3 dan mencari set 3 Os atau X yang berjumlah 15.

aPaULT
sumber
0

Bersih , 244 ... 220 byte

import StdEnv
f[a,b]i#k= \l=or[and[isMember(c+n)(take i l)\\c<-:"123147159357"%(j,j+2)]\\j<-[0,3..9]&h<-:"\0\0",n<-[h-h,h,h+h]]
|k a=(1,i*2-1)|i>4=(0,0)|k b=(2,i*2)=f[a,b](i+1)
@l=f(map(map((!!)l))[[0,2..8],[1,3..7]])1

Cobalah online!

String yang diiterasi menjadi hberisi yang tidak dapat dicetak, dan setara dengan "\003\001\000\000".

Suram
sumber
0

Python 2 , 140 136 134 byte

lambda a,i=0:i<9and(any(set(a[i%2:i+1:2])>=set(map(int,t))for t in'123 456 789 147 258 369 159 357'.split())and(i%2+1,i+1)or f(a,i+1))

Cobalah online!

EDIT: 4 byte + 2 byte thx untuk Eric the Outgolfer.

Menghasilkan tuple (playerNumber, roundNumber) atau False jika tidak ada pemenang.

Chas Brown
sumber
134 bytes
Erik the Outgolfer
@Erik - Yah, aku seharusnya sudah melakukannya; tapi saya melawan flu dan mata saya sakit :). Terima kasih!
Chas Brown
Baiklah, cepat sembuh. :)
Erik the Outgolfer