ระบุผู้ชนะ Tic-Tac-Toe (รอบฐาน)


26

มาเล่นโค้ดกอล์ฟกัน!

ความท้าทายคือการหาผู้ชนะของเกม Tic-Tac-Toe

สิ่งนี้ทำมาแล้วหลายครั้งโดยให้บอร์ดที่มีผู้ชนะเพียงคนเดียว แต่นี่คือการบิด:

เซลล์มีหมายเลขดังนี้:

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

คุณจะได้รับการเคลื่อนไหว 9 อย่างดังนี้:

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

นี่คือการแยกวิเคราะห์ดังนี้:

  • ผู้เล่น 1 ทำเครื่องหมายเซลล์ 3
  • ผู้เล่น 2 ทำเครื่องหมายเซลล์ 5
  • ผู้เล่น 1 ทำเครื่องหมายเซลล์ 6
  • ผู้เล่น 2 ทำเครื่องหมายเซลล์ 7
  • ผู้เล่น 1 คนทำเครื่องหมายเซลล์ 9
  • ผู้เล่น 1 ได้รับรางวัล

หมายเหตุ: เกมไม่หยุดหลังจากผู้เล่นคนใดคนหนึ่งชนะอาจเกิดขึ้นได้ว่าผู้เล่นที่แพ้จะได้สามแถวติดต่อกันหลังจากผู้เล่นที่ชนะ แต่จะนับเฉพาะการชนะครั้งแรกเท่านั้น

ตอนนี้งานของคุณคือการรับตัวเลข 9 ตัวเป็นอินพุทและเอาท์พุทผู้เล่นที่ชนะและรอบที่การชนะเกิดขึ้น หากไม่มีใครชนะเอาท์พุทบางอย่างคงที่ที่คุณเลือก คุณสามารถรับอินพุตและให้เอาต์พุตผ่านค่าเฉลี่ย / รูปแบบมาตรฐานใด ๆ

มีความสุข!

ตัวอย่างเพิ่มเติมตามที่ร้องขอ:

{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

11
ยินดีต้อนรับสู่ PPCG! นี่คือการโพสต์แรกที่ดี แต่เรามักจะไม่ชอบอินพุต / รูปแบบการออกข้อ คุณจะพิจารณาลบ"ผู้เล่น X ชนะในรอบ Y"และให้เราแสดงผลในรูปแบบที่สมเหตุสมผลเช่นรายการ[X, Y]หรือไม่ ในกรณีที่เสมอกันเราสามารถส่งออกค่าที่สอดคล้องอื่น ๆ แทนได้หรือไม่? ฉันขอแนะนำเพราะการพิมพ์สตริงที่แน่นอนนั้นไม่ได้เป็นส่วนหนึ่งของการเล่นกอล์ฟ สำหรับแนวคิดในอนาคตความท้าทายที่ผมขอแนะนำให้ใช้Sandbox :-)
Mr. Xcoder

ขอโทษฉันไม่ดี ฉันคิดว่ามันถูกต้องแล้ว
Grunzwanzling

อ่านความท้าทายจนถึงที่สุดฉันพูดได้ว่าอาจจะมีการเสมอกันและคุณสามารถเอาท์พุทที่คุณเลือกเมื่อมันเกิดขึ้น ฉันกลับ {2,6} เมื่อผู้เล่น 2 ชนะในรอบ 6 และ {0,0} เมื่อไม่มีใครชนะ
Grunzwanzling

เราสามารถใช้ดัชนีทุกอย่าง 0 ดัชนีได้ไหม? (เซลล์, ผู้เล่น, รอบ)
Arnauld

1
"คุณจะได้รับการเคลื่อนไหว 9 อย่างดังนี้: {3, 5, 6, 7, 9, 8, 1, 2, 3}" - ควร3ปรากฏขึ้นสองครั้งจริง ๆ หรือไม่
Jonathan Allan

คำตอบ:


8

เรติน่า , 114 ไบต์

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

ลองออนไลน์! ตามคำตอบของฉันไปที่Tic-Tac-Toe - X หรือ O? . เอาท์พุตX<N>หากผู้เล่นคนแรกชนะหลังจากNครบรอบO<N>ถ้าผู้เล่นคนที่สองชนะTถ้าไม่ชนะ คำอธิบาย:

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

สร้างบอร์ดภายในและทำเครื่องหมายการเคลื่อนไหวแต่ละครั้งด้วยผู้เล่นที่ย้าย

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

ใช้การย้าย

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

ค้นหาผู้ชนะและหากพบผู้ชนะให้แทนที่บอร์ดด้วยผู้ชนะและจำนวนการเคลื่อนไหวที่เหลืออยู่

.*¶
T

หากการเคลื่อนไหวหมดลงและไม่มีใครชนะเกมนั้นจะเสมอกัน

T`d`Rd

คำนวณจำนวนรอบจากจำนวนการเคลื่อนไหวที่เหลืออยู่


4
นี่เป็นอีกหนึ่งคำตอบ .... ที่ฉันได้เห็นที่นี่
ลอร์ด Farquaad

6

MATL , 39 ไบต์

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

ผลผลิตคือ

  • 1และRในแต่ละบรรทัดถ้าผู้ใช้ 1 ชนะในรอบR ;
  • 0และRในแต่ละบรรทัดถ้าผู้ใช้ 2 ชนะในรอบR ;
  • ว่างเปล่าถ้าไม่มีใครชนะ

ลองออนไลน์! หรือตรวจสอบกรณีทดสอบทั้งหมด

คำอธิบาย

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

5

Javascript (ES6), 130 ไบต์

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

คำอธิบาย

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

คุณจะให้คำอธิบายหรือคำอธิบายที่ไม่ดีออกไหม? ฉันสนใจที่จะเข้าใจวิธีการแก้ปัญหาของคุณ
แจ็ค

4

Java (OpenJDK 8) , 445 ไบต์

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});}

ลองออนไลน์!

ค่าส่งคืน {1,8} หมายถึงผู้เล่นที่ชนะ 1 ในรอบ 8 ค่าตอบแทน {0,0} หมายถึงการเสมอ


5
หากคุณไม่ลบระยะห่างที่ไม่จำเป็นออกทั้งหมดคำตอบนี้ถือว่าไม่ถูกต้องเนื่องจากขาดความพยายามในการเล่นกอล์ฟ ยิ่งกว่านั้นไม่แนะนำให้ตอบคำถามของคุณเองอย่างรวดเร็วและคุณอาจต้องการเพิ่มลิงค์TIOเพื่อให้เราสามารถทดสอบโค้ดของคุณได้
นาย Xcoder


ฉันขอโทษฉันคัดลอกสิ่งผิด ในความเป็นจริงมันสั้นลง
Grunzwanzling

คุณสามารถดูเคล็ดลับสำหรับการเล่นกอล์ฟในคำถาม Javaเพื่อลบบางไบต์ ตัวอย่างเช่นfalseสามารถถูกแทนที่ด้วย1<0และพื้นที่หลังจากที่แรก]สามารถลบได้
user202729

442 ไบต์ ยังเป็นเหตุผลว่าทำไม "หัว" และ "ส่วนท้าย" ส่วนที่มีอยู่บน TIO คือการที่คุณไม่จำเป็นต้องแสดงความคิดเห็นและ//Code that was submitted //End of code
user202729

2

Kotlin , 236 ไบต์

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

เชิดชู

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

ทดสอบ

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


1

Python 2 , 170 ไบต์

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)

ลองออนไลน์! หรือลองกรณีทดสอบทั้งหมด

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


1

Python 3.6+, 137 ไบต์

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)

รูปแบบผลลัพธ์เป็นwinner number:roundหรือ-1สำหรับเสมอ 2 ผู้เล่นเป็น0ผู้เล่นที่ 1 1คือ ป้อนในรูปแบบของสตริงที่ไม่ถูกลบของหมายเลขตาราง 1 ที่จัดทำดัชนี


1

เยลลี่ 35 ไบต์

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

การเชื่อมโยงการเอกรายการของการเคลื่อนไหวและการกลับรายการ[move, player]ที่ผู้เล่นที่มีการระบุว่าเป็น1(คนแรกที่จะทำหน้าที่) และ0(ที่สองจะทำหน้าที่)

ลองออนไลน์!

อย่างไร?

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]

0

Python 2, 168 ไบต์

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)

เอาต์พุต (ผู้เล่นกลม) หรือ 0 สำหรับการเสมอ

แมปเกมเข้าสู่เวทย์มนตร์สี่เหลี่ยมขนาด 3 คูณ 3 และมองหาชุด 3 Os หรือ Xs ที่รวมกันเป็น 15



0

Python 2 , 140 136 134 ไบต์

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

ลองออนไลน์!

แก้ไข: 4 ไบต์ + 2 ไบต์ขอบคุณไปยัง Eric the Outgolfer

แสดงผล tuple (playerNumber, RoundNumber) หรือ False หากไม่มีผู้ชนะ



@Erik - ใช่ฉันควรทำอย่างนั้นแล้ว แต่ฉันกำลังต่อสู้กับไข้หวัดใหญ่และดวงตาของฉันก็กำลังเจ็บปวด :) ขอบคุณ!
Chas Brown

ดีหายเร็ว ๆ :)
Erik the Outgolfer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.