Tulis game alak terpendek

10

Alak ditemukan oleh ahli matematika AK Dewdney, dan dijelaskan dalam bukunya Planiverse 1984. Aturan Alak sederhana:

Alak adalah gim dua pemain yang dimainkan di papan satu dimensi dengan sebelas slot di atasnya. Setiap slot dapat menampung paling banyak satu bagian sekaligus. Ada dua macam kepingan, "x" dan "o". x milik satu pemain, o milik yang lain. Konfigurasi awal papan adalah:

      xxxx___oooo

Para pemain bergiliran bergerak. Di setiap belokan, setiap pemain hanya bisa bergerak satu bagian, satu kali. Seorang pemain tidak bisa melewatkan gilirannya. Seorang pemain dapat memindahkan salah satu bagiannya ke slot kosong berikutnya ke kanan atau kiri, yang mungkin melibatkan melompati slot yang ditempati. Seorang pemain tidak dapat memindahkan bagian dari sisi papan.

Jika suatu gerakan menciptakan pola di mana potongan-potongan lawan dikelilingi, di kedua sisi, oleh dua potong warna penggerak (tanpa ada slot kosong yang tidak diduduki), maka potongan-potongan yang dikelilingi itu dikeluarkan dari papan.

Tujuan dari permainan ini adalah untuk menghapus semua bagian lawan Anda, di mana titik permainan berakhir. Menghapus semua-tetapi-satu juga mengakhiri permainan, karena lawan tidak dapat mengelilingi Anda dengan satu bagian, dan karenanya akan selalu kalah dalam beberapa gerakan saja.

Saya menemukan game ini online dan bertanya-tanya: apakah bisa golf?

Peraturan golf

  • Kode Anda harus mengikuti semua aturan dalam permainan, menangani tangkapan, pergerakan yang tepat, dll. (Satu-satunya pengecualian adalah Anda tidak harus menambahkan bot, tetapi Anda harus memiliki entah bagaimana kedua pemain dikendalikan, dan satu pemain harus manusiawi).
  • Input harus dipindahkan petak pada ubin X ke ubin Y, atau keluar. Misalnya, Anda dapat menggunakan 1 4untuk mengatakan 'pindahkan bagian ini di ubin 1 ke ubin 4'. quitakan mengakhiri program, meskipun menggunakan Control- Cakan diterima. Anda juga harus memeriksa apakah perpindahan tidak valid (dengan pergi ke luar papan atau pindah ke suatu tempat yang Anda harus melewati ruang kosong untuk mendapatkan atau mengirim pesan yang bukan pasangan ubin atau quit).
  • Output untuk pemain menang dan tidak valid harus P1 WINS, P2 WINSdan INVALIDmasing-masing. (Semua ini adalah 7 karakter.)
  • Output harus menunjukkan papan. Itu saja yang diperlukan.
  • Tidak masalah jika Anda menggunakan alat bantu seperti ubin bernomor atau potongan lainnya.
  • Tantangan berakhir jika:

    • Satu jawaban mendapat 50 suara
    • Satu jawaban tetap terpilih sebagai teratas selama 3 minggu, dan tidak ada jawaban lain yang diposting pada waktu itu

dan tantangannya memiliki setidaknya 3 jawaban (jadi ada beberapa kompetisi nyata).

Aturan mainnya

  • Pemain di sebelah kiri harus mulai duluan.
  • Hanya satu bagian menempati persegi pada satu waktu. Anda memindahkan potongan ke kiri atau ke kanan hingga menyentuh ruang kosong. Papan tidak terbungkus, dan Anda tidak dapat bergerak melewati area yang tidak dihuni. Sebagai contoh:
    • xoo__o. Di sini, xbergerak ke kanan akan mengubah papan _oox_o.
    • xxooo_. Di sini, yang paling kiri-kiri xbisa bergerak untuk menghasilkan _xooox, yang menangkap o, meninggalkan _x___x.
    • x__oox. Di sini, os tidak ditangkap (masih ada celah). Pengambilan foto tidak dimungkinkan karena Anda tidak dapat bergerak melintasi ruang kosong. Di xsebelah kiri hanya bisa bergerak satu ruang, karena tidak ada bagian lain di antara (meninggalkan _x_oox).
  • Beberapa potongan yang berdekatan dapat ditangkap sekaligus jika kelompok dikelilingi oleh potongan lawan. Misalnya dari x_ooxke _xooxakan menangkap keduanya odan menghasilkan _x__x.
  • Jika setelah bergerak, Anda pertama-tama menangkap kepingan lawan , sebelum memeriksa apakah kepingan Anda sendiri harus dihapus. Ambil dua contoh:
    • o_oxxuntuk oxox_. Pertama, yang kedua oditangkap ox_x_,, jadi yang pertama xtetap di papan tulis.
    • o_ooxuntuk oxoo_. Kali ini, tidak ada oyang ditangkap, jadi yang xditangkap sebagai gantinya.
    • Jika Anda hanya memiliki satu bagian, permainan berakhir, karena Anda tidak dapat menangkap hanya dengan satu bagian.

Biarkan game dimulai! Saya berharap dapat melihat apa yang Anda hasilkan.

ASCIIThenANSI
sumber
Komentar dibersihkan, karena sudah usang. Tolong beri tahu saya jika ada komentar yang harus dihapus.
Gagang Pintu

Jawaban:

9

C, 617 592 byte

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

Terurai:

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

Saya benar-benar ingin mendapatkan yang ini dalam ~ 400 byte, tetapi ada banyak aturan kecil di sini dan pemrosesan input berakhir sangat menjengkelkan. Saya jelas tidak selesai dengan ini. Berikut adalah serangkaian contoh proses yang mencakup hampir semua hal:

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

Jika saya salah mengartikan sesuatu, beri tahu saya!

BrainSteel
sumber
Saya mengujinya, itu bekerja dengan baik, dan tidak ada yang tertinggal. Kerja bagus!
ASCIIThenANSI
Anda dapat menyimpan beberapa byte dengan mengganti printf("INVALID");dengan puts("INVALID");, o<2||x<2dengan o<2|x<2dan printf(b);while(!q){denganfor(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);}}

Pemberitahuan harus ditekan dengan mengalihkan STDERRke /dev/null.

Dengan ruang kosong waras:

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

Dengan kasus uji 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
TimWolla
sumber
Apa yang Anda maksud dengan 'pemberitahuan / peringatan'?
ASCIIThenANSI
@ASCIIThenANSI Peringatan karena literal karakter yang tidak dikutip: Pemberitahuan PHP: Penggunaan konstanta yang tidak terdefinisi o - diasumsikan 'o' di /tmp/pcg-48388.php pada baris 2. Seseorang dapat mengarahkan mereka ke / dev / null.
TimWolla
Apakah itu merusak program?
ASCIIThenANSI
@ ASCIIThenANSI Tidak, itu berfungsi dengan baik adalah mereka diarahkan /dev/null.
TimWolla
Maka tidak apa-apa untuk memilikinya selama program terus berfungsi dengan baik, dan mereka dialihkan ke /dev/null.
ASCIIThenANSI
1

Python 2, 536 509 448 441 byte

Hubungi via a(); bergerak harus dimasukkan dalam bentuk piece,destination(yaitu, 1,4); keluar dengan Ctrl-C. Kalau ada yang bisa melihat lebih banyak potensi golf, saya semua telinga.

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)
Sirpercival
sumber
1

SpecBAS - 718 byte

SpecBAS adalah versi terbaru dari Sinclair / ZX BASIC yang dapat berjalan di luar emulator. (Masih ditafsirkan).

Telah menggunakan beberapa fitur baru untuk menurunkan ukuran sebanyak yang saya bisa.

Baris 12 membuat regex untuk mencari potongan "yang di-sandwich" menggunakan inline IF dan baris 18 menggunakan pembungkus di sekitar sifat INC (daripada mengatakan 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

Keluaran (tidak dapat menyalin dari janda keluaran, jadi tangkapan layar) masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

Brian
sumber
0

C #, 730 byte

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

Saya membayangkan bahwa perbaikan lebih lanjut dimungkinkan. Di sisi lain, saya menafsirkan INVALIDoutput sebagai mengakhiri eksekusi, jadi saya mungkin perlu memperbaiki masalah itu agar setara dengan jawaban lain.

Andrew
sumber