เขียนเกมที่สั้นที่สุดของ Alak


10

Alak ถูกคิดค้นโดยนักคณิตศาสตร์ AK Dewdney และอธิบายไว้ในหนังสือ 1984 Planiverse ของเขา กฎของ Alak นั้นเรียบง่าย:

Alak เป็นเกมที่ผู้เล่นสองคนเล่นบนกระดานหนึ่งมิติพร้อมช่องสิบเอ็ดช่อง แต่ละสล็อตสามารถถือได้ทีละชิ้นมากที่สุด มีสองชนิดคือ "x" และ "o" x เป็นของผู้เล่นหนึ่งคน การกำหนดค่าเริ่มต้นของบอร์ดคือ:

      xxxx___oooo

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

หากการเคลื่อนไหวสร้างรูปแบบที่ชิ้นส่วนของฝ่ายตรงข้ามล้อมรอบทั้งสองด้านโดยสีของผู้เสนอญัตติสองชิ้น (โดยไม่มีช่องว่างว่างที่ไม่ว่าง) จากนั้นชิ้นส่วนที่ล้อมรอบจะถูกลบออกจากกระดาน

เป้าหมายของเกมคือการลบชิ้นส่วนของฝ่ายตรงข้ามทั้งหมดที่จุดสิ้นสุดเกม การเอาออกทั้งหมด - แต่ - หนึ่งจบเกมเช่นกันเนื่องจากคู่ต่อสู้ไม่สามารถล้อมคุณด้วยชิ้นเดียวและจะสูญเสียภายในไม่กี่เคลื่อนไหวเสมอ

ฉันพบเกมนี้ออนไลน์และสงสัยว่า: มันสามารถเล่นกอล์ฟได้หรือไม่?

กติกาการเล่นกอล์ฟ

  • รหัสของคุณจะต้องเป็นไปตามกฎทั้งหมดในเกมการจับการเคลื่อนไหวที่เหมาะสมเป็นต้น (ยกเว้นเพียงคุณไม่ต้องเพิ่มบอท แต่คุณต้องมีผู้เล่นทั้งสองที่ควบคุมอย่างใดและผู้เล่นคนหนึ่งต้องเป็นมนุษย์)
  • ข้อมูลจะต้องย้ายชิ้นส่วนที่ tile X ถึง tile Y หรือออก ตัวอย่างเช่นคุณสามารถใช้1 4เพื่อพูดว่า 'ย้ายชิ้นส่วนนี้ที่แผ่น 1 ถึงแผ่นต่อ 4' quitจะจบโปรแกรมแม้ว่าการใช้Control- Cจะเป็นที่ยอมรับ คุณต้องตรวจสอบด้วยว่าการเคลื่อนไหวนั้นไม่ถูกต้องหรือไม่ (โดยการออกไปข้างนอกบอร์ดหรือเคลื่อนที่ไปที่ไหนสักแห่งที่คุณจะต้องข้ามช่องว่างที่ว่างเพื่อไปยังหรือส่งข้อความที่ไม่ใช่แผ่นกระเบื้องหรือคู่quit)
  • ขาออกสำหรับผู้เล่นที่ชนะและไม่ถูกต้องจะต้องP1 WINS, P2 WINSและINVALIDตามลำดับ (ทั้งหมดนี้คือ 7 ตัวอักษร)
  • เอาท์พุทจะต้องแสดงบอร์ด นั่นคือทั้งหมดที่จำเป็น
  • ไม่สำคัญว่าคุณจะใช้เครื่องช่วยเช่นกระเบื้องที่มีหมายเลขหรือชิ้นส่วนอื่น ๆ
  • ความท้าทายจะสิ้นสุดลงถ้า:

    • หนึ่งคำตอบจะได้รับ 50 คะแนน
    • หนึ่งคำตอบยังคงได้คะแนนสูงสุดเป็นเวลา 3 สัปดาห์และไม่มีคำตอบอื่นใดโพสต์ในเวลานั้น

และความท้าทายมีอย่างน้อย 3 คำตอบ (ดังนั้นจึงมีการแข่งขันจริง)

กฎของเกม

  • ผู้เล่นทางด้านซ้ายจะต้องเริ่มต้นก่อน
  • มีเพียงชิ้นเดียวเท่านั้นที่ใช้เวลาหนึ่งตาราง คุณเลื่อนชิ้นส่วนไปทางซ้ายหรือขวาจนกว่าจะถึงพื้นที่ว่าง กระดานไม่พันและคุณไม่สามารถเคลื่อนที่ผ่านบริเวณที่ว่าง ตัวอย่างเช่น:
    • xoo__o. นี่ขวาย้ายจะเปลี่ยนคณะกรรมการเพื่อx_oox_o
    • xxooo_. ที่นี่ทางซ้ายสุดxสามารถเคลื่อนย้ายเพื่อให้_xoooxได้ซึ่งจับภาพการoจาก_x___xไป
    • x__oox. ที่นี่oไม่ถูกบันทึก (ยังมีช่องว่าง) จับภาพเป็นไปไม่ได้เพราะคุณไม่สามารถเคลื่อนที่ผ่านช่องว่างที่ว่าง xด้านซ้ายเท่านั้นที่สามารถย้ายพื้นที่หนึ่งเพราะไม่มีชิ้นอื่น ๆ ในระหว่าง (ออก_x_oox)
  • สามารถจับชิ้นส่วนที่อยู่ติดกันหลายชิ้นได้ในครั้งเดียวหากกลุ่มถูกล้อมรอบด้วยชิ้นส่วนของคู่ต่อสู้ เช่นจากx_ooxการ_xooxจะจับภาพทั้งos _x__xและผลในการ
  • ถ้าหลังจากย้ายคุณจับชิ้นส่วนของฝ่ายตรงข้ามก่อนตรวจสอบว่าควรลบชิ้นส่วนของคุณเองหรือไม่ ใช้สองตัวอย่าง:
    • o_oxxoxox_ไปยัง ครั้งแรกที่สองoถูกจับox_x_ดังนั้นคนแรกที่xยังคงอยู่บนกระดาน
    • o_ooxoxoo_ไปยัง เวลานี้จะไม่มีการoจับ s ดังนั้นจึงxถูกจับแทน
    • หากคุณมีเพียงชิ้นเดียวเกมจะจบลงเพราะคุณไม่สามารถจับภาพได้ด้วยชิ้นเดียว

ให้เกมเริ่มต้นขึ้น! ฉันหวังว่าจะเห็นสิ่งที่คุณเกิดขึ้น


ความคิดเห็นถูกลบล้างเนื่องจากล้าสมัย โปรดแจ้งความคิดเห็นใด ๆ ที่ควรถูกลบทิ้ง
Doorknob

คำตอบ:


9

C, 617 592 ไบต์

#define O(x)(x-'x'?'x':'o')
q,f,t,k,i,x=4,o=4,*d;main(){char*A,Q[9],c='x',b[]="xxxx___oooo";printf(b);while(!q){scanf(" %8[^\n]%*[^\n]",Q);if(!strcmp(Q,"quit"))break;f=*Q>47&&*Q<58?atoi(Q):-1;A=f>9?Q+2:Q+1;t=*A==32&&A[1]>47&&A[1]<58?atoi(A+1):-1;i=t==f&&t<0&&f<0?1:0;for(k=f;k!=t;k+=(t-f)/abs(t-f))if(b[k]==95||b[t]-95||b[f]-c)i=1;if(i){printf("INVALID");continue;}b[t]=c;b[f]=95;for(t=0;t<2;t++){d=c-'x'?&o:&x;for(k=1;k<11;k++)if(b[k]==O(c)){for(i=k+1;b[i]==O(c)&&b[i];i++);if(b[i]==c&&b[k-1]==c)while(k<i)b[k++]=95,(*d)--;}c=t?c:O(c);}printf(b);if(o<2||x<2)printf("P%d WINS",(x>1)+1),q=1;}}

หลุด:

#define O(x)(x-'x'?'x':'o')
q,f,t,k,i,x=4,o=4,*d;
main(){
    char*A,Q[9],c='x',b[]="xxxx___oooo";
    printf(b);
    while(!q){
        scanf(" %8[^\n]%*[^\n]",Q);
        if(!strcmp(Q,"quit"))break;
        f=*Q>47&&*Q<58?atoi(Q):-1;
        A=f>9?Q+2:Q+1;
        t=*A==32&&A[1]>47&&A[1]<58?atoi(A+1):-1;
        i=t==f&&t<0&&f<0?1:0;
        for(k=f;k!=t;k+=(t-f)/abs(t-f))
            if(b[k]==95||b[t]-95||b[f]-c)
                i=1;
        if(i){
            printf("INVALID");
            continue;
        }
        b[t]=c;
        b[f]=95;
        for(t=0;t<2;t++){
            d=c-'x'?&o:&x;
            for(k=1;k<11;k++)
                if(b[k]==O(c)){
                    for(i=k+1;b[i]==O(c)&&b[i];i++);
                    if(b[i]==c&&b[k-1]==c)
                        while(k<i)b[k++]=95,(*d)--;
                }
            c=t?c:O(c);
        }
        printf(b);
        if(o<2||x<2)printf("P%d WINS",(x>1)+1),q=1;
    }
}

ฉันอยากได้อันนี้ในขนาด ~ 400 ไบต์ แต่มีกฎเล็ก ๆ น้อย ๆ มากมายที่นี่และการประมวลผลอินพุตก็ค่อนข้างน่ารังเกียจ ฉันไม่ได้ทำอย่างนี้แน่นอน ต่อไปนี้เป็นชุดตัวอย่างการทำงานที่ครอบคลุมทุกอย่าง

xxxx___oooo0 4
_xxxx__oooo7 6
_xxxx_o_ooo4 5
_xxx_xo_ooo8 6
INVALID8 7
_xxx_xoo_oo3 4
_xx_xxoo_oo7 3
_xxo__o__oo1 4
__x_x_o__oo10 9
INVALID10 8
__x_x_o_oo_2 3
___xx_o_oo_6 5
___xxo__oo_6 6
INVALID5 5
INVALID3 6
____x_x_oo_8 7
____x_xo_o_6 8
____x__o_o_P2 WINS

xxxx___oooo0 4
_xxxx__oooo10 6
_xxxx_oooo_1 5
__xxxxoooo_9 1
_o____ooo__P2 WINS

xxxx___oooo0 4
_xxxx__oooo7 6
_xxxx_o_ooo1 5
__xxxxo_ooo10 7
__xxxxoooo_2 10
___xxx____xP1 WINS

xxxx___oooo3 4
xxx_x__ooooquits
INVALIDtestme
INVALID3*4
INVALID3 four
INVALIDthree four
INVALIDthisstringislongerthanmybuffer
INVALID10 0
INVALID4 5
INVALID7 6
xxx_x_o_oooquit

หากฉันตีความบางอย่างผิดโปรดแจ้งให้เราทราบ!


ฉันทดสอบมันใช้งานได้ดีและไม่มีอะไรเหลือ เยี่ยมมาก!
ASCIIThenANSI

คุณสามารถบันทึกไม่กี่ไบต์โดยการแทนที่printf("INVALID");ด้วยputs("INVALID");, o<2||x<2มีo<2|x<2และprintf(b);while(!q){มีfor(printf(b);!q;){
es1024

3

PHP - 505

<?php
$s="xxxx___ooo".$y=o;$x=x;$c=function($m)use(&$x){return$x.str_repeat('_',strlen($m[1])).$x;};$e='$s=preg_replace_callback("~$x($y+)$x~",$c,$s);';$_=substr_count;while(true){echo$s;if($_($s,x)<2)die("P2 WINS");if($_($s,o)<2)die("P1 WINS");$i=trim(fgets(STDIN));if($i=='quit')die;if(!preg_match('!^(\d+) (\d+)$!',$i,$m)||$s[$f=$m[1]]!=$x||$s[$t=$m[2]]!="_"||(0&($a=min($f,$t))&$b=max($f,$t))||$_($s,"_",$a,($b-$a)+1)>1)echo"INVALID\n";else{$s[$f]='_';$s[$t]=$x;eval($e);$z=$x;$x=$y;$y=$z;eval($e);}}

การบอกกล่าวที่ต้องถูกระงับโดยการเปลี่ยนเส้นทางไปยังSTDERR/dev/null

ด้วยช่องว่างที่มีสติ:

<?php
@$s = "xxxx___ooo".($y = o);
@$x = x;
$c = function($m)usea(&$x){
    return$x.str_repeat('_',strlen($m[1])).$x;
};
$e = '$s=preg_replace_callback("~$x($y+)$x~",$c,$s);';
@$_ = substr_count;
while (true){
    echo $s;

    if (@$_($s,x) < 2) die("P2 WINS");
    if (@$_($s,o) < 2) die("P1 WINS");

    $i = trim(fgets(STDIN));
    if($i == 'quit') die;

    if( !preg_match('!^(\d+) (\d+)$!',$i,$m)
    ||   $s[$f = $m[1]] != $x
    ||  @$s[$t = $m[2]] != "_"
    ||  (0 & ($a = min($f, $t)) & $b = max($f, $t))
    ||  $_($s, "_", $a, ($b - $a) + 1) > 1
    ) echo "INVALID\n";
    else {
        $s[$f] = '_';
        $s[$t] = $x;
        eval($e);
        $z = $x;
        $x = $y;
        $y = $z;
        eval($e);
    }
}

ด้วยกรณีทดสอบของ BrainSteel:

xxxx___oooo0 4
_xxxx__oooo7 6
_xxxx_o_ooo4 5
_xxx_xo_ooo8 6
INVALID
_xxx_xo_ooo8 7
_xxx_xoo_oo3 4
_xx_xxoo_oo7 3
_xxo__o__oo1 4
__x_x_o__oo10 9
INVALID
__x_x_o__oo10 8
__x_x_o_oo_2 3
___xx_o_oo_6 5
___xxo__oo_6 6
INVALID
___xxo__oo_5 5
INVALID
___xxo__oo_3 6
____x_x_oo_8 7
____x_xo_o_6 8
____x__o_o_P2 WINS

xxxx___oooo0 4
_xxxx__oooo10 6
_xxxx_oooo_1 5
__xxxxoooo_9 1
_o____ooo__P2 WINS

xxxx___oooo0 4
_xxxx__oooo7 6
_xxxx_o_ooo1 5
__xxxxo_ooo10 7
__xxxxoooo_2 10
___xxx____xP1 WINS

xxxx___oooo3 4
xxx_x__ooooquits
INVALID
xxx_x__ooootestme
INVALID
xxx_x__oooo3*4
INVALID
xxx_x__oooo3 four
INVALID
xxx_x__oooothree four
INVALID
xxx_x__oooothisstringislongerthanmybuffer
INVALID
xxx_x__oooo10 0
INVALID
xxx_x__oooo4 5
INVALID
xxx_x__oooo7 6
xxx_x_o_oooquit

คุณหมายถึง 'ประกาศ / คำเตือน' หมายถึงอะไร
ASCIIThenANSI

@ASCIIThenANSI คำเตือนเนื่องจากตัวอักษร unquoted ตัวอักษร: ประกาศ PHP: การใช้ค่าคงที่ไม่ได้กำหนด o - สันนิษฐานว่า 'o' ใน /tmp/pcg-48388.php ในบรรทัด 2 หนึ่งสามารถเปลี่ยนเส้นทางไปยัง / dev / null
TimWolla

โปรแกรมนี้หยุดพักหรือไม่?
ASCIIThenANSI

@ASCIIThenANSI /dev/nullไม่มีก็จะปรับการทำงานคือพวกเขาจะเปลี่ยนเส้นทางไปยัง
TimWolla

/dev/nullแล้วก็ตกลงที่จะมีมันตราบเท่าที่โปรแกรมยังคงทำงานอย่างถูกต้องและพวกเขาจะเปลี่ยนเส้นทางไปยัง
ASCIIThenANSI

1

Python 2, 536 509 448 441 ไบต์

โทรผ่านa(); การเคลื่อนไหวจะต้องป้อนในแบบฟอร์มpiece,destination(เช่น, 1,4); ออกด้วย Ctrl-C ถ้าใครสามารถเห็นศักยภาพในการเล่นกอล์ฟมากขึ้น

b,r,x='_',lambda p:''.join([p[i]for i in x]),range(11)
def a(m='xo'):
 t=w=0;p=dict(zip(x,'xxxx___oooo'))
 while w<1:
    print r(p);y=m[t%2]
    try:
     s,v=input();1/all([y==p[s],{v}<{r(p).rfind(b,0,s),r(p).find(b,s)},v-s]);p[s],p[v],h,c=b,y,0,{}  
     for _ in y,m[-~t%2]:
        for i in p:exec{_:"h=1;p.update(c)",b:"h,c=0,{}"}.get(p[i],h*"c[i]=b")
     w=min(map(r(p).count,m))<2;t+=1
    except:print"INVALID"
 print"P%d WINS"%-~(r(p).count('o')<2)

1

SpecBAS - 718 ไบต์

SpecBASเป็น Sinclair / ZX BASIC รุ่นปรับปรุงที่สามารถทำงานนอกตัวจำลอง (ตีความยัง)

ได้ใช้คุณสมบัติใหม่บางอย่างเพื่อลดขนาดให้มากที่สุดเท่าที่จะทำได้

บรรทัดที่ 12 ตั้งค่า regex เพื่อค้นหาชิ้นส่วน "แซนวิช" โดยใช้อินไลน์ IF และบรรทัดที่ 18 ใช้การล้อมรอบธรรมชาติของ INC (แทนที่จะพูดINC p: IF p=3 THEN LET p=1)

1 LET b$="xxxx---oooo": LET p=1: LET c$="xo": DIM s=4,4
2 LET v=0: PRINT b$'"[";p;"] ";
3 INPUT m$: IF m$(1)="Q" THEN PRINT "QUIT": STOP 
4 LET f=VAL(ITEM$(m$,1," ")): LET t=VAL(ITEM$(m$,2," ")): PRINT f;" ";t
5 IF (f<1 OR f>11) OR (t<1 OR t>11) THEN LET v=1: GO TO 10
6 IF (b$(f)<>c$(p)) OR b$(t)<>"-" THEN LET v=1: GO TO 10
7 FOR i=f TO t STEP SGN(t-f)
8 IF b$(i)="-" THEN IF i<>t THEN LET v=1
9 NEXT i
10 IF v=1 THEN PRINT "INVALID": GO TO 2
11 LET b$(t)=b$(f): LET b$(f)="-"
12 LET r$=IIF$(p=1,"xo+x","ox+o")
13 LET m=MATCH(r$,b$): IF m=0 THEN GO TO 18
14 FOR i=m+1 TO POS(c$(p),b$,m+2)
15 IF b$(i)=c$(3-p) THEN LET b$(i)="-": DEC s(3-p): END IF
16 NEXT i
17 IF s(3-p)<2 THEN PRINT b$'"P";p;" WINS": STOP 
18 INC p,1 TO 2
19 GO TO 2

เอาท์พุท (ไม่สามารถคัดลอกจากม่ายออกดังนั้นภาพหน้าจอ) ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่


0

C #, 730 ไบต์

using System;using System.Linq;class P{static void Main(string[]z){int p=1,d,e,g,x,y;var b=new[]{3,1,1,1,1,0,0,0,2,2,2,2};var o=new[]{"_","x","o"};Action<string>h=s=>{Console.Write(s,p);Environment.Exit(0);};Action i=()=>h("INVALID");Func<int,int,bool>j=(q,r)=>b.Select((v,w)=>w<=q||w>=r||v>0?0:w).Any(w=>w>0);Action<int>k=m=>{e=0;for(d=1;d<12;d++){if(b[d]==m){if(e>0&&!j(e,d))for(g=e+1;g<d;g++)b[g]=0;e=d;}}if(b.Count(w=>w>0&&w!=m)<3)h("P{0} WINS");};try{for(;;){for(g=1;g<12;g++)Console.Write(o[b[g]]);var n=Console.ReadLine();if(n=="quit")h("");var c=n.Split(' ');x=int.Parse(c[0]);y=int.Parse(c[1]);if(c.Length>2||b[x]!=p||b[y]!=0||(p>1?y:x)>=(p>1?x:y)||j(x<y?x:y,x<y?y:x))i();b[x]=0;b[y]=p;k(p);p=p>1?1:2;k(p);}}catch{i();}}}

ฉันคิดว่าการปรับปรุงเพิ่มเติมเป็นไปได้ ในทางกลับกันฉันตีความINVALIDเอาท์พุทเป็นการสิ้นสุดการประมวลผลดังนั้นฉันอาจต้องแก้ไขปัญหานั้นให้เท่าเทียมกับคำตอบอื่น ๆ

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