กลายเป็นแชมป์


11

Tic-Tac ละติน!

นี่เป็นเรื่องจริงดังนั้นชื่อจึงเปลี่ยนไป

อาจารย์ละตินของฉันนายลาตินสร้างกรรมสิทธิ์ในตัวเอง (ไม่ตลก) ลองเรียกมันว่า tic-tac-latin เกมดังกล่าวเป็นเกมที่เล่นง่ายมันเป็นเกมที่เล่นบนโต๊ะสี่ถึงสี่นิ้ว

การประกาศกฎอย่างเป็นทางการ

บรรทัดเป็นทั้งแถวคอลัมน์หรือแนวทแยงมุม มีสัญลักษณ์สองตัวคือ 'X' และ 'O' แต่อาจมีหนึ่งหรือทั้งสองอย่างใช้แทนสัญลักษณ์อื่นได้
คุณได้คะแนนหนึ่งคะแนนเมื่อคุณมีสามสัญลักษณ์และหนึ่งในตัวละครอื่น ๆ

คะแนนการเตรียมการเหล่านี้:

--- O
-O--
XXXO
XOOX

O -XX
- O -
- X -
--- โอ

สิ่งเหล่านี้ไม่ได้คะแนน:

----
XXXX
----
OOOO

----
xxx-
----
OOO-

เกมนี้ชนะเมื่อผู้เล่นคนหนึ่งมีคะแนนมากกว่ากัน เกมดังกล่าวเป็นเพียงการดึงกระดานออกมาเท่านั้น

ท้าทาย

แก้เกมนี้ งานของคุณคือการให้วิธีการรับประกันการชนะหรือเสมอผลงานที่ดีที่สุด

โซลูชันของคุณอาจเลือกที่จะเริ่มครั้งแรกหรือครั้งที่สอง (และอาจเลือกเป็นสัญลักษณ์) ไม่จำเป็นต้องใช้เกมแบบโต้ตอบที่ผู้ใช้ย้ายเข้าและการเปลี่ยนแปลงการแสดงที่สอดคล้องกัน นอกจากนี้ยังอาจจะมีฟังก์ชั่นหรือโปรแกรมที่จะเข้าเป็นรัฐเกมและผลคณะกรรมการใหม่หรือคำอธิบายของการย้ายของพวกเขา ตัวเลือกทั้งสองจะต้องทำงานภายในเวลาประมาณสิบวินาทีต่อการย้าย


การเล่นเครื่องเล่นของคุณกับการเคลื่อนไหวตามลำดับใด ๆ จะต้องให้ผลลัพธ์ที่ดีที่สุด ซึ่งหมายความว่าคุณอาจสมมติว่าตำแหน่งอินพุตเป็นตำแหน่งที่สามารถเข้าถึงได้จากการเล่นกับเครื่องเล่นของคุณ การส่งจะต้องถูกกำหนดไว้และไม่จำเป็นต้องแสดงหลักฐานการมองโลกในแง่ดี แต่หากพวกเขาได้รับการแตกร้าว (โดยแพ้) การส่งของคุณจะถือว่าไม่ถูกต้อง (คุณอาจทิ้งไว้ แต่เพิ่ม (แตก) ในบรรทัดแรก)
นี่เป็นภารกิจที่ไม่สำคัญดังนั้นการส่งใด ๆ ที่ถูกต้องน่าประทับใจและมีค่าควรแก่การติ๊กที่ยอมรับได้ แต่ฉันจะทำให้รหัสกอล์ฟเป็นเกณฑ์การชนะขั้นแรก

ผู้ชนะจะถูกเลือกโดยการลงรายการนี้จนกว่าจะมีการเลือกผู้ชนะหนึ่งคน

  • การดำเนินการแก้ไขที่สั้นที่สุดซึ่งชนะเสมอ
  • การใช้งานที่สั้นที่สุด

1
"ก่อนอื่นต้องพิจารณาคุณภาพของการเล่น" คุณไม่คิดว่ามันเป็นอัตนัยหรือ
user48538

งานของการให้อินเทอร์เฟซสำหรับเล่นดูเหมือนจะเป็นอุปกรณ์ต่อพ่วงในการเขียนเครื่องเล่นที่สมบูรณ์แบบ ฉันขอแนะนำให้เพียงแค่ผ่านสถานะของเกมปัจจุบันเป็นอินพุตและต้องการให้โค้ดส่งออกการย้ายที่ชนะหรือเพียงแค่การประเมินภายใต้การเล่นที่สมบูรณ์แบบ (win, draw, loss)
xnor

1
วิธีการแก้ปัญหาสามารถเล่นกอล์ฟได้โดยการค้นหาแรงเดรัจฉานที่ไม่มีประสิทธิภาพ คุณตกลงไหมถ้ารหัสทำงานช้ามาก?
xnor

1
" คุณชนะเกมนี้หากคุณให้คะแนนและในกระบวนการไม่ได้คะแนนสำหรับคู่ต่อสู้ของคุณ " นี่หมายความว่าฉันสามารถชนะเมื่อฉันวางชิ้นเดียวเท่านั้นไม่ใช่เมื่อฝ่ายตรงข้ามทำเช่นนั้น? จะเกิดอะไรขึ้นถ้าการเคลื่อนไหวสร้างเส้นชนะสำหรับผู้เล่นทั้งสอง: เกมที่เล่นหรือเล่นต่อ?
Peter Taylor

1
@RohanJhunjhunwala คุณควรชี้แจงการอนุญาตให้ป้อนข้อมูลสถานะเกมมิฉะนั้นเป็นไปได้ที่ผู้คนอาจใช้ประโยชน์จากรูปแบบการป้อนข้อมูลที่ไม่ได้กำหนดในปัจจุบันและเลือกรูปแบบที่ช่วยแก้ปัญหาได้มาก
ASCII เท่านั้น

คำตอบ:


6

Perl, 147 ไบต์ (ไม่ใช่การแข่งขันใช้เวลามากกว่า 10 วินาทีต่อการเคลื่อนไหว)

รวมถึง +4 สำหรับ -0p

Xละครโปรแกรม มันจะเล่นเกมที่สมบูรณ์แบบ

ใส่บอร์ดบน STDIN เช่น:

tictaclatin.pl
-X-O
-X--
X-X-
O--O
^D

ouptut จะเป็นบอร์ดเดียวกันโดยXแทนที่ด้วยOและในทางกลับกัน จุดที่ว่างเปล่าจะเต็มไปด้วยตัวเลขที่ระบุผลลัพธ์ถ้า X เล่นที่นั่นพร้อมกับ1ความหมายผลลัพธ์จะชนะ2การเสมอและ3การสูญเสีย เกมที่เล่นเสร็จแล้วจะกลับมาอยู่ในตำแหน่งเดิมโดยที่สีกลับด้าน

ในตัวอย่างนี้ผลลัพธ์จะเป็น:

1O1X
1O33
O3O3
X33X

ดังนั้นตำแหน่งคือการชนะXถ้าเขาเล่นใน 3 จุดตามด้านบนและด้านซ้าย การเคลื่อนไหวอื่น ๆ ทั้งหมดจะแพ้

ผลลัพธ์ที่สับสนนี้สะดวกจริง ๆ ถ้าคุณต้องการทราบว่าเกมดำเนินต่อไปอย่างไรหลังจากย้าย เนื่องจากโปรแกรมมักจะเล่นXคุณต้องสลับXและจะเห็นการเคลื่อนไหวสำหรับO Oตัวอย่างเช่นที่นี่ค่อนข้างชัดเจนว่าXชนะโดยการเล่นที่มุมบนซ้าย แต่ถ้าXเล่นในตำแหน่งที่สามตามด้านบนล่ะ เพียงแค่คัดลอกเอาท์พุทOแทนที่การเคลื่อนไหวที่คุณเลือกและแทนที่หมายเลขอื่นทั้งหมด-อีกครั้งดังนั้นที่นี่:

-OOX
-O--
O-O-
X--X

ที่เกิดขึ้นใน:

3XXO
3X33
X3X3
O33O

เห็นได้ชัดว่าทุกการเคลื่อนไหวโดยOควรสูญเสียดังนั้นเขาจะสูญเสียถ้าเขาเล่นในมุมบนซ้ายได้อย่างไร ทำสิ่งนี้อีกครั้งโดยใส่Oที่ด้านบนซ้ายและแทนที่ตัวเลขด้วย-:

OXXO
-X--
X-X-
O--O

ให้:

XOOX
1O33
O3O3
X33X

ดังนั้น X มีทางเดียวเท่านั้นที่จะชนะเขาได้:

XOOX
OO--
O-O-
X--X

ให้

OXXO
XX33
X3X3
O33O

สถานการณ์Oยังคงสิ้นหวัง ตอนนี้มันเป็นเรื่องง่ายที่จะเห็นว่าทุกการเคลื่อนไหวอนุญาตให้Xชนะได้ทันที อย่างน้อยก็ลองทำ 3 โอต่อเนื่องกัน:

OXXO
XX--
X-X-
O-OO

ให้:

XOOX
OO13
O3O3
X3XX

Xเล่นการย้ายที่ชนะเท่านั้น (โปรดสังเกตว่าสิ่งนี้ทำXXXOตามคอลัมน์ที่สาม:

XOOX
OOO-
O-O-
X-XX

นี่คือผลลัพธ์:

OXXO
XXX-
X-X-
O-OO

เพราะเกมเสร็จแล้ว คุณสามารถเห็นชัยชนะในคอลัมน์ที่สาม

โปรแกรมจริงtictaclatin.pl:

#!/usr/bin/perl -0p
y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/sx;$@<=>0||s%-%$_="$`O$'";$$_||=2+do$0%eg&&(/1/||/2/-1)

นำไปใช้กับบอร์ดว่างนี้ประเมินตำแหน่ง 9506699 ซึ่งใช้เวลา 30Gb และ 41 นาทีบนคอมพิวเตอร์ของฉัน ผลลัพธ์คือ:

2222
2222
2222
2222

ดังนั้นการเริ่มต้นทุกครั้งจึงเกิดขึ้น ดังนั้นเกมคือการจับฉลาก

do$0ใช้หน่วยความจำมากส่วนใหญ่จะเกิดจากการเรียกซ้ำโดยใช้ การใช้ 154 ไบต์รุ่นนี้โดยใช้ฟังก์ชั่นธรรมดาต้องใช้ 3G และ 11 นาที:

#!/usr/bin/perl -0p
sub f{y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/sx;$@<=>0||s%-%$_="$`O$'";$$_||=2+&f%eeg&&(/1/||/2/-1)}f

ซึ่งสามารถรับได้มากขึ้น (แต่ก็ยังมากเกินไป

การรวมจำนวนการเร่งความเร็วจำนวนมากจะนำไปสู่เวอร์ชัน 160 ไบต์ (5028168 ตำแหน่ง, 4 นาทีและ 800M สำหรับบอร์ดว่างเปล่า):

#!/usr/bin/perl -0p
sub f{y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/osx;$@<=>0||s%-%$_="$`O$'";$a{$_}//=&f+1or return 1%eeg&&/1/-1}f

อันสุดท้ายใช้0สำหรับการชนะ (อย่าสับสนO) 1สำหรับการเสมอและ2การแพ้ การส่งออกของอันนี้ก็สับสนมากขึ้น มันเติมในการย้ายที่ชนะสำหรับ X ในกรณีที่ชนะโดยไม่มีการสลับสี แต่ถ้าเกมอินพุตได้รับรางวัลแล้วก็ยังคงเป็นการสลับสีและไม่เติมเต็มในการเคลื่อนไหวใด ๆ

ทุกรุ่นได้เร็วขึ้นและใช้หน่วยความจำน้อยลงเมื่อบอร์ดเต็ม เวอร์ชันที่เร็วขึ้นควรสร้างการเคลื่อนไหวภายใน 10 วินาทีทันทีที่มีการเคลื่อนไหว 2 หรือ 3 ครั้ง

โดยหลักการแล้ว 146 byte version ควรใช้งานได้:

#!/usr/bin/perl -0p
y/XO/OX/,$@=-$@while/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^/sx,--$|;$@<=>0||s%-%$_="$`O$'";$$_||=2+do$0%eg&&(/1/||/2/-1)

แต่ในเครื่องของฉันมันทำให้เกิดข้อผิดพลาดของ Perl และทิ้งแกน

โดยหลักการแล้วเวอร์ชันทั้งหมดจะยังคงทำงานหากการแคชตำแหน่ง 6 ไบต์ที่ทำโดย$$_||=ถูกลบออกไป แต่ใช้เวลาและหน่วยความจำมากจนใช้ได้กับแผงวงจรเกือบเต็ม แต่ในทางทฤษฎีอย่างน้อยฉันก็มีวิธีแก้ปัญหา 140 ไบต์

หากคุณใส่$\=(ราคา: 3 ไบต์) ก่อนหน้า$@<=>0บอร์ดผลลัพธ์แต่ละบอร์ดจะตามด้วยสถานะของบอร์ดทั้งหมด: 1สำหรับXผู้ชนะ, 0เสมอและ-1เสมอ

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

#!/usr/bin/perl
sub f{
    if ($p++ % 100000 == 0) {
        local $| = 1;
        print ".";
    }
y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/osx;$@<=>0||s%-%$_="$`O$'";$a{$_}//=&f+1or return 1%eeg&&/1/-1}

# Driver
my $tomove = "X";
my $move = 0;
@board = ("----\n") x 4;
while (1) {
    print "Current board after move $move ($tomove to move):\n  ABCD\n";
    for my $i (1..4) {
        print "$i $board[$i-1]";
    }
    print "Enter a move like B4, PASS (not a valid move, just for setup) or just press enter to let the program make suggestions\n";
    my $input = <> // exit;
    if ($input eq "\n") {
        $_ = join "", @board;
        tr/OX/XO/ if $tomove eq "O";
        $p = 0;
        $@="";
        %a = ();
        my $start = time();
        my $result = f;
        if ($result == 1) {
            tr/OX/XO/ if $tomove eq "O";
            tr/012/-/;
        } else {
            tr/OX/XO/ if $tomove eq "X";
            tr/012/123/;
        }
        $result = -$result if $tomove eq "O";
        my $period = time() - $start;
        print "\nSuggested moves (evaluated $p positions in $period seconds, predicted result for X: $result):\n$_";
        redo;
    } elsif ($input =~ /^pass$/i) {
        # Do nothing
    } elsif (my ($x, $y) = $input =~ /^([A-D])([1-4])$/) {
        $x = ord($x) - ord("A");
        --$y;
        my $ch = substr($board[$y],$x, 1);
        if ($ch ne "-") {
            print "Position already has $ch. Try again\n";
            redo;
        }
        substr($board[$y],$x, 1) = $tomove;
    } else {
        print "Cannot parse move. Try again\n";
        redo;
    }
    $tomove =~ tr/OX/XO/;
    ++$move;
}

คำตอบที่ดี คุณช่วยหาวิธีง่ายๆให้ฉันทดสอบได้ไหม? เป็นการดีที่จะรักที่จะเห็นรุ่นแบบโต้ตอบ ... (นี่คือ jut สำหรับความอยากรู้ของฉันเอง)
Rohan Jhunjhunwala

@RohanJhunjhunwala Ok เพิ่มไดรเวอร์อินเทอร์แอคทีฟที่ใช้งานง่าย
Ton Hospel

ตัวแปร '$ move' ไม่ถูกประกาศที่ prog.pl:2
Rohan Jhunjhunwala

มนุษย์มีวิธีแก้ปัญหาด้วยวิธีแก้ปัญหาได้หรือไม่?
Rohan Jhunjhunwala

@RohanJhunjhunwala เพียงตรวจสอบโปรแกรมไดรเวอร์อีกครั้ง วิ่งได้ดี$moveมีการประกาศในบรรทัดที่ 11 ฉันไม่รู้ว่ามีฮิวริสติกของมนุษย์หรือไม่ โปรแกรมนี้ก็ไม่ Minimax บนต้นไม้เกมก็ไม่ได้มีการใด ๆความรู้เชิงกลยุทธ์
Ton Hospel

2

JavaScript (ES6) 392 ไบต์

a=>b=>(c="0ed3b56879a4c21f",r=[],k=f=>r.push([a.filter(f),b.filter(f)]),[0,1,2,3].map(i=>k(n=>n%4==i)+k(n=>(n/4|0)==i)),k(n=>n%5==0),k(n=>n&&n-15&&!(n%3)),g=r.find(o=>(o[0].length==1&&o[1].length==2)||(o[0].length==2&&o[1].length==1)),g?parseInt(c[30-[...g[0],...g[1]].map(i=>parseInt(c[i],16)).reduce((p,c)=>p+c)],16):[...a,...b].indexOf(15-a[0])+1?15-a.find(i=>b.indexOf(15-i)==-1):15-a[0])

การใช้

"บอท" จะเล่นที่สอง

วาดตาราง 4x4 ที่มีหมายเลขดังนี้:

+----+----+----+----+
|  0 |  1 |  2 |  3 |
+----+----+----+----+
|  4 |  5 |  6 |  7 |
+----+----+----+----+
|  8 |  9 | 10 | 11 |
+----+----+----+----+
| 12 | 13 | 14 | 15 |
+----+----+----+----+

มารันสิ่งนี้ในคอนโซลของเบราว์เซอร์: ใส่f=รหัสไว้ก่อน

ดังนั้นถ้าผมอยากจะเริ่มต้นที่1ผมจะทำงานและมันจะให้ฉันf([1])([])14

ย้ายที่ดี ... ถ้าฉันเล่น2หลังจากนั้น f([2,1])([14]). 13มันจะกลับมา

เล็มม์ลองยอมแพ้ 3เล่น f([3,2,1])([14,13]). โอ้0! คุณมีฉัน!

เล่น0เหรอ f([0,2,1])([14,13]). 15ตกลงเล่นต่อไป ...

บันทึก

  1. เล่นแบบโต้ตอบ f([your-step])([])เริ่มต้นด้วย

  2. เตรียมขั้นตอนต่อไปของคุณ (ดูตัวอย่างด้านบน)

  3. ช่วยอินพุต "bot" ตามขั้นตอน มันจะไม่ให้ผลลัพธ์ที่ดีถ้าคุณตั้งค่าแบบสุ่ม (ชอบf([1,2,4])([14,12])จะให้14- เฮ้บอต้องการที่จะเล่น13ในการย้ายที่สองของมัน!

สรุปโดยย่อ

ตราบใดที่คุณยังไม่ยอมแพ้บอทจะเล่นกระจกเงา

ขอบคุณ @EHTproductions ที่บอกฉันว่าฉันทำผิดกฎของเกมและเคล็ดลับการเล่นกอล์ฟ: P

ตอนนี้มันจะตรวจพบว่ามันได้รุกฆาต ถ้าใช่ปิดกั้น!

ลำดับความสำคัญของมัน: บล็อก> กระจก> (ทางเลือก) มองหาวิธีสร้างกระจก


ฉันชอบแทคติก "mirror move" :) ฉันอาจเข้าใจผิด แต่ไม่ใช่3,2,1สำหรับคุณและ0เพื่อบอทจะชนะสำหรับคุณ
ETHproductions

โอ๊ะฉันเข้าใจผิดว่า "ผู้จับรูปแบบ 3 แบบและอีก 1 แบบ" Lemme ปรับแต่งการแก้ปัญหาเล็กน้อย .. ขอบคุณ @ ETHproductions
Sunny Pun

คู่ของเคล็ดลับการเล่นกอล์ฟ: สามารถที่จะแข็งแรงเล่นกอล์ฟ[0,1,2,3].map(i=>{k(n=>n%4==i);k(n=>Math.floor(n/4)==i);}) [0,1,2,3].map(i=>k(n=>n%4==i)+k(n=>(n/4|0)==i))
ETHproductions

ฉันไม่คิดว่านี่จะเป็นชัยชนะที่พิสูจน์ได้
Rohan Jhunjhunwala

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