คุณสามารถชนะด้วยการเคลื่อนไหวอีกสองครั้งที่ Three Men's Morris ได้ไหม?


16

โปรดปราน

ลำดับ 1 ( มอบรางวัล )

ฉันจะโยน 50 ตัวแทนสำหรับคำตอบแรกที่ถูกต้อง

ฉบับที่ 2 ( ได้รับรางวัล )

ฉันจะโยนอีก 100 ตัวแทนสำหรับคำตอบที่ถูกต้องสั้นที่สุด

หมายเลข 3 ( เปิดสำหรับการส่ง )

ฉันจะโยนใน 200 ตัวแทนสำหรับคนแรกที่มีคำตอบที่ถูกต้องสั้นลงอย่างมีนัยสำคัญ มีนัยสำคัญที่มากที่สุด 45% ของคำตอบที่สั้นที่สุดในปัจจุบัน ( 564 ไบต์ x 0.45 = สูงสุด 254 ไบต์ )


เกม

คุณจำเกมคลาสสิค " Nine Men's Morris " หรือเพียงแค่ " Mill " มีรูปแบบที่เรียกว่าThree Men's Morrisซึ่งมีลักษณะคล้ายกับนิ้วเท้าโอค - แทค

กฎระเบียบ

นี่คือบอร์ดเปล่าของเกม:

   a   b   c
1 [ ]–[ ]–[ ]
   | \ | / |
2 [ ]–[ ]–[ ]
   | / | \ |
3 [ ]–[ ]–[ ]

[ ]เป็นฟิลด์และ|–/\แสดงเส้นทางระหว่างฟิลด์เหล่านั้น

เกมนี้เล่นโดยผู้เล่นสองคน1และ2แต่ละคนมี 3 โทเค็นบนกระดาน เรื่องนี้เกิดขึ้นจริงแล้วและเราอยู่ในเกม เกมชนะถ้าผู้เล่นคนใดคนหนึ่งสามารถสร้างรูปแบบหนึ่งmillซึ่งเป็นแถวแนวตั้งหรือแนวนอนของโทเค็นของผู้เล่น 3 คน

สามารถย้ายโทเค็นบนกระดานไปตามสายเชื่อมต่อได้ตามกฎนี้:

ไปยังตำแหน่งว่างใด ๆ ที่อยู่ติดกัน (เช่นจากตำแหน่งขอบไปยังกึ่งกลางหรือจากกึ่งกลางไปยังตำแหน่งขอบหรือจากตำแหน่งขอบไปยังตำแหน่งขอบที่อยู่ติดกัน

ผู้เล่นจะต้องเคลื่อนที่ยกเว้นในกรณีที่ไม่มีตำแหน่งว่างข้างเคียงซึ่งในกรณีนี้การกระโดดข้าม

ความท้าทาย

คุณเป็นผู้เล่น1และท่าต่อไปของคุณคือ เขียนโปรแกรมหรือฟังก์ชั่นที่กำหนดว่า:

  • คุณสามารถบังคับให้ชนะด้วยการเคลื่อนไหว 2 หรือน้อยกว่า ( ชนะแน่นอน )
  • คุณสามารถชนะด้วย 2 หรือน้อยกว่าย้ายถ้าฝ่ายตรงข้ามของคุณทำผิดพลาด ( ชนะไปได้ )
  • คุณไม่สามารถชนะด้วยการเคลื่อนไหว 2 ครั้งหรือน้อยกว่าเพราะคุณต้องการการเคลื่อนไหวมากกว่านี้หรือเพราะการบังคับที่บังคับให้ฝ่ายตรงข้ามชนะ ( เป็นไปไม่ได้ที่จะชนะ )

ความต้องการ

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

อินพุต

ผู้เล่นจะถูกแทนด้วยและ1 กำหนดเขตข้อมูลฟรี คุณสามารถรับอินพุตเป็นเมทริกซ์หรืออาร์เรย์20

ชัดเจน

A         B         C         D
2 1 0  |  2 1 0  |  1 0 1  |  1 2 2
2 1 2  |  0 1 0  |  1 0 2  |  2 1 O
0 0 1  |  2 2 1  |  0 2 2  |  O O 1

A: [2,1,0,2,1,2,0,0,1]
B: [2,1,0,0,1,0,2,2,1]
C: [1,0,1,1,0,2,0,2,2]
D: [1,2,2,2,1,0,0,0,1]

เป็นไปได้

A         B         C
1 0 1  |  1 0 1  |  1 2 2
1 2 2  |  1 2 0  |  0 0 1
2 0 0  |  2 0 2  |  2 1 0

A: [1,0,1,1,2,2,2,0,0]
B: [1,0,1,1,2,0,2,0,2]
C: [1,2,2,0,0,1,2,1,0]

เป็นไปไม่ได้

A         B    
1 0 0  |  1 2 0
1 2 2  |  2 1 0
2 0 1  |  1 2 0

A: [1,0,0,1,2,2,2,0,1]
B: [1,2,0,2,1,0,1,2,0]

เอาท์พุต

โปรแกรมของคุณควรส่งออก / ส่งกลับยิ้ม:

  • ชนะแน่นอน: :)
  • ชนะที่เป็นไปได้: :|
  • ชนะไม่ได้: :(

ตัวอย่าง

ชนะแน่นอนในสองจังหวะ:

[2][1][ ] 1. [2][1][ ]
[2][1][2] -> [2][1][2]
[ ][ ][1]    [ ][1][ ]

[2][1][ ] 1. [2][1][ ]    [ ][1][ ] 2. [ ][ ][1]
[ ][1][ ] -> [ ][ ][1] -> [2][ ][1] -> [2][ ][1]
[2][2][1]    [2][2][1]    [2][2][1]    [2][2][1]

[1][ ][1] 1. [ ][1][1]    [ ][1][1] 2. [1][1][1]
[1][ ][2] -> [1][ ][2] -> [1][ ][2] -> [ ][ ][2]
[ ][2][2]    [ ][2][2]    [2][ ][2]    [2][ ][2]

ชนะได้ในสองจังหวะ:

[1][ ][1] 1. [ ][1][1]    [ ][1][1] 2. [1][1][1]
[1][2][ ] -> [1][2][ ] -> [1][2][2] -> [ ][2][2]
[2][ ][2]    [2][ ][2]    [2][ ][ ]    [2][ ][ ]

[1][ ][1] 1. [ ][1][1]    [ ][1][1] 2. [1][1][1]
[1][2][ ] -> [1][2][ ] -> [1][2][2] -> [ ][2][2]
[2][ ][2]    [2][ ][2]    [2][ ][ ]    [2][ ][ ]

[1][2][2] 1. [ ][2][2]    [2][ ][2] 2. [1][2][2]
[ ][ ][1] -> [1][ ][1] -> [1][ ][1] -> [1][1][1]
[2][1][ ]    [2][1][ ]    [2][1][ ]    [2][ ][ ]

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

[1][ ][ ]
[1][2][2]
[2][ ][1]

โบนัส

ในกรณีที่ชนะได้แน่นอนและโปรแกรมของคุณส่งสัญญาณการเคลื่อนที่ของวิธีหนึ่งสู่ความสำเร็จเช่นa1:a2(1 การเคลื่อนไหว) หรือa1:a2,a3:b2(การเคลื่อนไหว 2 ครั้ง) คุณสามารถถอน30%ของจำนวนไบต์


นี่คือรหัสกอล์ฟ - ดังนั้นคำตอบที่สั้นที่สุดในจำนวนไบต์ชนะ ช่องโหว่มาตรฐานไม่ได้รับอนุญาต


ขอขอบคุณที่ปีเตอร์เทย์เลอร์ที่ได้รับการแก้ไขข้อบกพร่องบางอย่างและถ้อยคำที่ดีขึ้นในSandbox


ที่เกี่ยวข้อง
insertusernamehere

1
ฉันชอบตาราง ascii / กราฟิค =)
ข้อผิดพลาด

1
จะเกิดอะไรขึ้นหากผู้เล่นไม่สามารถเคลื่อนไหวได้? เช่นใน[1,0,0,2,1,0,2,2,1]ผู้เล่น 2 ไม่สามารถเคลื่อนไหวได้ - นี่เป็นชัยชนะสำหรับผู้เล่น 1 หรือไม่
VisualMelon

1
@LeifWillerts ฉันอาจเข้าใจผิดว่าคุณหมายถึงอะไร แต่ในกรณีนี้ไม่มีผู้เล่นอยู่ในสถานะที่ชนะ - พวกเขาชนะเพียงแค่มีเส้นแนวนอนหรือแนวตั้ง (ไม่ใช่แนวทแยงมุม)
VisualMelon

3
มีตำแหน่งกระดานที่ถูกต้องเพียง 1,680 ตำแหน่งดังนั้นการเข้ารหัสสามารถให้มากกว่า 210 ไบต์ได้เล็กน้อย (น้อยกว่าหากพิจารณาความสมมาตร)
lirtosiast

คำตอบ:


1

Haskell, 580 564 441 bytes

นี่คือสิ่งที่ฉันสามารถตีกอล์ฟได้ในตอนนี้ ไม่แน่ใจว่าภาษาอื่นสามารถเอาชนะได้หรือไม่

เรียกmรายการที่ต้องการ[[2,1,0],[2,1,2],[0,0,1]](Definite A)

import Data.Array
r=[0..2]
p?f=[(x,y)|x<-r,y<-r,f!y!x==p]
p%f=all(==x)xs||all(==y)ys where(x:xs,y:ys)=unzip$p?f
s p x y f=f//[(y,f!y//[(x,p)])]
p#f=[s 0 x y$s p u v f|a@(x,y)<-p?f,b@(u,v)<-0?f,((x-u)*(y-v)==0&&abs(x+y-u-v)==1)||elem(1,1)[a,b]]
p&f|p#f>[]=p#f|0<1=[f]
e=any
i a p f=e(a$e(p%))(map(map(p&))(map((3-p)&)$p&f))||e(p%)(p&f)
l=listArray(0,2)
f(True,_)=":)"
f(False,True)=":|"
f _=":("
m=putStrLn.f.(\f->(i all 1 f,i e 1 f)).l.map l

รหัสทดสอบ:

da = [[2,1,0],[2,1,2],[0,0,1]]
db = [[2,1,0],[0,1,0],[2,2,1]]
dc = [[1,0,1],[1,0,2],[0,2,2]]
dd = [[1,2,2],[2,1,0],[0,0,1]]
pa = [[1,0,1],[1,2,2],[2,0,0]]
pb = [[1,0,1],[1,2,0],[2,0,2]]
pc = [[1,2,2],[0,0,1],[2,1,0]]
ia = [[1,0,0],[1,2,2],[2,0,1]]
ib = [[1,2,0],[2,1,0],[1,2,0]]
al = [da,db,dc,dd,pa,pb,pc,ia,ib]

mapM_ m al ผลตอบแทน:

:)
:)
:)
:)
:|
:|
:|
:(
:(

1
ถูกต้องแล้วฉันคิดว่า Will doublecheck และเล่นกอล์ฟอย่างถูกต้องในตอนเย็น (ซึ่งนี่คือก่อนสิ้นสุดระยะเวลาผ่อนผัน)
Leif Willerts

5

ค# - 739 663 ไบต์

เสร็จสิ้นโปรแกรมอ่านอินพุตจาก argv และทำงานได้ เรียกใช้เหมือนกัน

ThreeMill 1 2 1 1 2 0 0 0 2

หากวิธีการป้อนข้อมูลนี้ไม่เป็นที่ยอมรับฉันยินดีที่จะเปลี่ยนแปลง (ไม่เคยใช้ argv)

using System;using System.Linq;class P{static void Main(string[]A){var I=new[]{0,3,6,1,4,7,2,5,8};Func<string[],string>J=S=>S[0]+S[1]+S[2]+" "+S[3]+S[4]+S[5]+" "+S[6]+S[7]+S[8]+" ";Func<string[],string,int>W=(B,p)=>(J(B)+J(I.Select(i=>B[i]).ToArray())).Contains(p+p+p)?1:0;Func<string[],string,string[][]>V=(B,p)=>I.SelectMany(a=>I.Where(b=>a!=b&B[a]==p&B[b]=="0"&(a==4|b==4|a-b==3|b-a==3|((a-b==1|b-a==1)&a/3==b/3))).Select(b=>{var N=(string[])B.Clone();N[b]=p;N[a]="0";return N;})).DefaultIfEmpty(B).ToArray();int h,G;Console.WriteLine(":"+"(|))"[V(A,"1").Max(z=>((h=0)<(G=V(z,"2").Sum(j=>V(j,"1").Max(q=>W(q,"1")-W(q,"2"))+h++*0))?1:0)+(h>G?W(z,"1")*2:2))]);}}

ฉันไม่ชอบที่จะโพสต์เมื่อวานนี้เพราะฉันไม่สามารถตีมันลงได้มาก (ไม่ได้มีเวลามากและฉันอาจเลิกฝึกซ้อม) แต่เนื่องจากยังไม่ได้รับคำตอบฉันจึง ' ฉันจะโพสต์มันต่อไปแน่นอนว่าฉันไม่คาดหวังความโปรดปรานฉันอยากให้คนที่ใส่ความพยายามของพวกเขาก่อนโพสต์!

แก้ไข:แทนที่ bools ทั้งหมดด้วย ints ซึ่งหมายความว่าฉันสามารถใช้ประโยชน์จาก Linq ได้ดีขึ้นและจัดการเพื่อยุบลูปด้านหน้าทั้งสองทำให้ประหยัดได้มาก ฉันประหลาดใจเล็กน้อยที่hนับใช้งาน ... ++ เป็นเครื่องมือที่ละเอียดอ่อน

โปรแกรมนั้นง่ายมากเพียงแค่สำรวจทุกชุดที่เป็นไปได้ (เก็บสถานะบอร์ดในสตริง []) มันวนซ้ำการเคลื่อนไหวที่เป็นไปได้ทั้งหมดของเรา (กระดานที่เป็นผลมาจากมัน) และนับจำนวนการตอบสนองจากฝ่ายตรงข้ามของเราที่เราสามารถเอาชนะได้สำเร็จ ( G) (เช่นกระดานที่เราชนะและเขาไม่ได้) นอกจากนี้ยังนับจำนวนคำตอบที่เป็นไปได้ (h) ถ้าเราสามารถชนะใด ๆ มันก็เป็นไปได้และเราบวก 1 เข้ากับผลรวมหากเราสามารถชนะได้ทั้งหมดมันแน่นอนและเราบวก 2 เข้ากับผลรวม จำนวนสูงสุดคือผลลัพธ์ที่ดีที่สุดเท่าที่จะเป็นไปได้และเราจัดทำดัชนีลงในสตริง "(|))" เพื่อส่งคืนใบหน้าที่เหมาะสม โปรดทราบว่าเราต้องการส่วนเสริม ")" เนื่องจากผลรวมสามารถเป็น 2 หรือ 3 ได้ถ้าแน่นอน (อาจเป็นไปได้ว่าเราไม่สามารถเอาชนะคำตอบใด ๆ ที่ชนะไปแล้วในครั้งแรกดังนั้นการตรวจสอบที่เป็นไปได้คือ ตาดทำให้เข้าใจผิด)

โปรแกรมตรวจสอบชัยชนะโดยการสร้างสายจากกระดานนั่นคือแถวและคอลัมน์ที่คั่นด้วยช่องว่างและเพียงแค่มองหาสายอักขระ 3 ตัวของผู้เล่นในสายนี้ (เช่น "201 201 021 220 002 111" คือ ชนะสำหรับเรา)

using System;
using System.Linq; // all important

class P
{
    static void Main(string[]A) // transform to int?
    {
        var I=new[]{0,3,6,1,4,7,2,5,8}; // vertical indexes
        Func<string[],string>J=S=>S[0]+S[1]+S[2]+" "+S[3]+S[4]+S[5]+" "+S[6]+S[7]+S[8]+" "; // joins the strings up, so that there is a space separating each group of three (including at end)
        Func<string[],string,int>W=(B,p)=>(J(B)+J(I.Select(i=>B[i]).ToArray())).Contains(p+p+p)?1:0; // checks if a particular player wins
        Func<string[],string,string[][]>V=(B,p)=>I.SelectMany(a=>I // for each imagineable move
            .Where(b=>a!=b&B[a]==p&B[b]=="0"&(a==4|b==4|a-b==3|b-a==3|((a-b==1|b-a==1)&a/3==b/3))) // where it's legal
            .Select(b=>{var N=(string[])B.Clone();N[b]=p;N[a]="0";return N;}) // select the resulting board
        ).DefaultIfEmpty(B) // allow not-moving
        .ToArray();

        int h, // h stores the number of responses the opponent has to each move
        G; // G stores the number of responses by the opponent we can beat

        Console.WriteLine(":"+"(|))"[ // we index into this to decide which smiley
            V(A,"1").Max(z=>
                    ((h=0)<(G=V(z,"2").Sum(j=>V(j,"1").Max(q=>W(q,"1")-W(q,"2"))+h++*0))?1:0) // if there is atleast 1 reponse by the opponent we can beat, we can possibly win
                    +(h>G?W(z,"1")*2:2) // if there are moves which we can't win, then if we have already won (one-move), else, we can definitely win
                   ) // sum is therefore 0 if impossible, 1 if possible, >2 (no more than 3) if definite 
            ]);

    }
}

นี่คือสคริปต์ทดสอบของฉัน:

ThreeMill 2 1 0 2 1 2 0 0 1
ThreeMill 2 1 0 0 1 0 2 2 1
ThreeMill 1 0 1 1 0 2 0 2 2
ThreeMill 1 2 2 2 1 0 0 0 1

ThreeMill 1 0 1 1 2 2 2 0 0
ThreeMill 1 0 1 1 2 0 2 0 2
ThreeMill 1 2 2 0 0 1 2 1 0

ThreeMill 1 0 0 1 2 2 2 0 1
ThreeMill 1 2 1 1 2 0 0 0 2
ThreeMill 1 0 1 2 0 2 1 0 2

ซึ่งเอาท์พุท

:)
:)
:)
:)
:|
:|
:|
:(
:|
:)

ดี ขอบคุณที่เป็นคนแรก :) ถ้าไม่เป็นไรฉันจะมอบรางวัลให้หลังจากวันหยุดสุดสัปดาห์เพื่อเก็บไว้อีกสองสามวันในแท็บวิดีโอเด่น
นี่

@insertusername ที่นี่ก็ดีสำหรับฉันถ้าฉันไม่สามารถใส่ใจที่จะทำงานจริง ๆ ได้ฉันอาจจะทำงานต่อไปในวันพรุ่งนี้
VisualMelon

1
สิ่งนี้ทำให้ฉันนึกถึงความคิดเห็นนี้: " ฉันไม่สามารถตอบคำถามสำหรับสี่สิบนาทีนี่เป็นสิ่งสำคัญ! เพียงส่งรายละเอียดฐานข้อมูลและฉันจะแทรก SQL คำตอบของฉันฉันมีงานมากมายที่จะหลีกเลี่ยงและไม่มีเหตุผล การหลีกเลี่ยง !! "บนทำไม Stack Overflow ไม่ทำงาน? . :)
insertusername ที่นี่

1

PowerShell 576 550 ไบต์

ฉันจะไม่ถูกขัดขวางอย่างง่ายดาย - ถ้าฉันไม่สามารถรับ C # ที่ต่ำกว่า 631 ไบต์ฉันจะต้องใช้ภาษาอื่นแทน! ฉันหวังว่า Leif Willerts จะล้มคำตอบของเขา 5 ไบต์เพราะฉันตัดสินใจว่าฉันไม่ชอบ PowerShell มากเกินไปบางทีฉันแค่ต้องดูอย่างเป็นกลางในแง่ของจำนวนไบต์ ...

. .\mill.ps1 "201102021"นี้เป็นสคริปต์ที่คุณเรียกมันด้วย มันเป็นสำเนาของคำตอบ C # ของฉันค่อนข้างดีมีเพียงภาษาที่ฉันมีประสบการณ์เล็กน้อย ฉันไม่ได้พยายามมากนักในการตีกอล์ฟนี้เพราะมันใช้เวลานานมากในการทำงานในครั้งแรกและค่อนข้างกะทัดรัดอยู่แล้ว

แก้ไข: ไม่สามารถฝาก[Math]::Floorสายเหล่านั้นได้

param($U);$I=0,3,6,1,4,7,2,5,8;function J($S){($S[0..2]+" "+$S[3..5]+" "+$S[6..8]-join"").Contains($p*3)}function W($D,$p){(J $D)-or(J $D[$I])}function V($Q,$C){$I|%{$a=$_;$I|?{$a-ne$_-and$Q[$a]-eq$c-and$Q[$_]-eq"0"-and($a-eq4-or$_-eq4-or$a-$_-eq3-or$_-$a-eq3-or(($a-$_-eq1-or$_-$a-eq1)-and$a/3-$a%3/3-eq$_/3-$_%3/3))}|%{$b=$Q[0..8];$b[$_]=$c;$b[$a]=0;$b-join''}}|%{$n=1}{$n=0;$_}{if($n){$Q}}}$e=$f=0;V $U "1"|%{$h=0;$x=$_;V $x "2"|%{$k=0;(V $_ "1"|%{if((W $_ "1")-and!(W $_ "2")){$k=$e=1}});$h+=1-$k};if($h-eq0-or(W $x "1")){$f=2}};":"+"(|))"[$e+$f]

หากคุณมีคำอธิบายว่ามันทำงานอย่างไรคำตอบ C # นั้นเหมาะสำหรับคุณ แต่หวังว่าความคิดเห็นจะชัดเจนพอสมควร อัฒภาคอาจไม่ตรงกันอย่างสมบูรณ์กับคำสั่งบรรทัดเดียวฉันไม่แน่ใจว่าพวกเขาต้องการหรือไม่และไม่ได้คัดลอกกลับมาเมื่อฉันใส่ทุกอย่างไว้ในบรรทัดเดียว

param($U); # take input as argument

$I=0,3,6,1,4,7,2,5,8; # cols

function J($S){ # checks if this is a winning string
($S[0..2]+" "+$S[3..5]+" "+$S[6..8]-join"").Contains($p*3)}

function W($D,$p){ # checks if this is a winning board
(J $D)-or(J $D[$I])} # $D[$I] reorganises into columns

function V($Q,$C){ # yields all valid moves from position $Q for player $C
$I|%{$a=$_;$I| # for each possible move
?{$a-ne$_-and$Q[$a]-eq$c-and$Q[$_]-eq"0"-and($a-eq4-or$_-eq4-or$a-$_-eq3-or$_-$a-eq3-or(($a-$_-eq1-or$_-$a-eq1)-and$a/3-$a%3/3-eq$_/3-$_%3/3))}| # where legal
%{$b=$Q[0..8];$b[$_]=$c;$b[$a]=0;$b-join''}}| # make the move (copy $Q to an array, modify, join into a string)
%{$n=1}{$n=0;$_}{if($n){$Q}}} # if empty, return $Q - I am confident this can be achieved with commas, and [0], and maybe a +, but I don't want to think about it

$e=$f=0; # possible, definite

V $U "1"|%{ # for all our possible moves
$h=0;$x=$_; # $k is whether we win all of these
  V $x "2"| # for all opponent's responses
  %{$k=0;(V $_ "1"| # for all our responses
  %{if((W $_ "1")-and!(W $_ "2")){$k=$e=1}});$h+=1-$k}; # if we can win and he can't, then things are looking good, set $e to 1 (possible win)

  if($h-eq0-or(W $x "1")){$f=2} # if we win every move, or we have already won, it's a definite
};

":"+"(|))"[$e+$f] # smile, it's all over

สคริปต์ทดสอบ (PowerShell):

. .\mill.ps1 "210212001"
. .\mill.ps1 "210010221"
. .\mill.ps1 "101102022"
. .\mill.ps1 "122210001"

. .\mill.ps1 "101122200"
. .\mill.ps1 "101120202"
. .\mill.ps1 "122001210"

. .\mill.ps1 "100122201"
. .\mill.ps1 "121120002"
. .\mill.ps1 "101202102"

. .\mill.ps1 "100122201"
. .\mill.ps1 "120210120"

เอาท์พุทของมัน:

:)
:)
:)
:)
:|
:|
:|
:(
:|
:)
:(
:(

1

Python 3, 566 557 ไบต์

ฉันจะต้องดูว่าฉันสามารถตีมันลงไปอีกหรือจะได้โบนัส 30% แต่หลังจากผัดวันประกันพรุ่งมากมายนี่คือคำตอบของฉัน

def t(g,x=1,r=0,z=0):
 m=[[1,3,4],[0,2,4],[2,4,5],[0,4,6],[0,1,2,3,5,6,7,8],[2,4,8],[3,4,7],[4,6,8],[4,5,7]];a=[[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]];z=z or[[],[],[],[]];s=0
 if r>3:return z
 for i in a:
  if g[i[0]]==g[i[1]]==g[i[2]]>0:s=g[i[0]];break
 z[r]+=s,
 for q in range(9):
  i=g[q]
  if i==x:
   for p in m[q]:
    if g[p]<1:n=g[:];n[q],n[p]=n[p],n[q];z=t(n,3-x,r+1,z)
 if r:return z
 else:
  w=l=0
  for j in range(4):w=w or 1in z[j];l=l or 2in z[j]
  if l<1and w:return":)"
  elif w<1and l:return":("
  else:return":|"

Ungolfed:

def three_mens_morris(grid, player=1, rec=0, w_l=0, p=0):
    moves = [[1,3,4],[0,2,4],[2,4,5],[0,4,6],[0,1,2,3,5,6,7,8],[2,4,8],[3,4,7],[4,6,8],[4,5,7]]
    w_l = w_l or [[],[],[],[]]
    if rec == 4: return w_l
    result = check_grid(grid)
    w_l[rec].append(result)
    for sq_1 in range(len(grid)):
        piece = grid[sq_1]
        if piece == player:
            for sq_2 in moves[sq_1]:
                if grid[sq_2] == 0:
                    new_grid = grid.copy()
                    new_grid[sq_1],new_grid[sq_2]=new_grid[sq_2],new_grid[sq_1]
                    w_l = three_mens_morris(new_grid,3-player,rec+1,w_l)
    if p: print(w_l)
    if rec:
        return w_l
    else:
        win = loss = 0
        for i in range(4):
            if 1 in w_l[i]:
                win = 1
            elif 2 in w_l[i]:
                loss = 1
        if p:print(win,loss)
        if loss==0 and win:
            return ":)"
        elif loss and win==0:
            return ":("
        else:
            return ":|"

def check_grid(grid):
    rows = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]]
    for i in rows:
        if grid[i[0]]==grid[i[1]]==grid[i[2]] and grid[i[0]]:
            return grid[i[0]]
    return 0
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.