Napisz najkrótszą grę alak

10

Alak został wynaleziony przez matematyka AK Dewdneya i opisany w jego książce Planiverse z 1984 roku. Zasady Alaka są proste:

Alak to gra dla dwóch graczy, rozgrywana na jednowymiarowej planszy z jedenastoma slotami. Każde miejsce może pomieścić najwyżej jeden element na raz. Istnieją dwa rodzaje elementów: „x” i „o”. x należy do jednego gracza, o do drugiego. Początkowa konfiguracja płyty to:

      xxxx___oooo

Gracze na zmianę się poruszają. W każdej turze każdy gracz może przesunąć tylko jeden element, raz. Gracz nie może spasować w swojej turze. Gracz może przenieść dowolny ze swoich pionków do następnego niezajętego miejsca na prawo lub lewo, co może obejmować przeskakiwanie zajętych miejsc. Gracz nie może przesunąć pionka z boku planszy.

Jeśli ruch tworzy wzór, w którym pionki przeciwnika są otoczone po obu stronach dwoma kawałkami koloru poruszającego się (bez żadnych pustych pustych miejsc), wówczas te otoczone fragmenty są usuwane z planszy.

Celem gry jest usunięcie wszystkich elementów przeciwnika, w którym to momencie gra się kończy. Usunięcie „wszystko oprócz jednego” również kończy grę, ponieważ przeciwnik nie może cię otoczyć jednym kawałkiem, dlatego i tak zawsze przegra w ciągu kilku ruchów.

Znalazłem tę grę online i zastanawiałem się: czy można w nią grać w golfa?

Zasady gry w golfa

  • Twój kod musi przestrzegać wszystkich zasad gry, obsługi przechwytywania, właściwego poruszania się itp. (Jedynym wyjątkiem jest to, że nie musisz dodawać bota, ale musisz jakoś kontrolować obu graczy, a jeden gracz musi być człowiekiem).
  • Wejście musi być przeniesione na kafelku X do kafelka Y lub wyjść. Na przykład możesz użyć 1 4słowa „przenieś ten kawałek z pola 1 na pole 4”. quitzakończy program, chociaż użycie Control- Cbyłoby dopuszczalne. Musisz także sprawdzić, czy ruch jest nieważny (wychodząc poza planszę lub poruszając się w miejscu, w którym musisz przejść przez niezajęte miejsca, aby dostać się do lub wysłać wiadomość, która nie jest parą płytek lub quit).
  • Wyjścia dla graczy wygrywających i nieważne musi być P1 WINS, P2 WINSi INVALID, odpowiednio. (Wszystkie mają 7 znaków).
  • Wyjście musi pokazywać tablicę. To wszystko, co jest wymagane.
  • Nie ma znaczenia, czy użyjesz pomocy, takiej jak ponumerowane kafelki lub inne elementy.
  • Wyzwanie kończy się, jeśli:

    • Jedna odpowiedź dostaje 50 głosów
    • Jedna odpowiedź pozostaje najwyżej głosowana przez 3 tygodnie, a w tym czasie nie opublikowano żadnych innych odpowiedzi

a wyzwanie ma co najmniej 3 odpowiedzi (więc istnieje prawdziwa konkurencja).

Zasady gry

  • Gracz po lewej musi zacząć pierwszy.
  • Tylko jeden element zajmuje kwadrat na raz. Poruszasz pionkiem w lewo lub w prawo, aż trafi on na niezajęte miejsce. Plansza się nie zawija i nie można poruszać się przez niezajęte obszary. Na przykład:
    • xoo__o. W tym przypadku xruch w prawo zmieni tablicę na _oox_o.
    • xxooo_. Tutaj najdalej-lewa strona xmogła się przesunąć, by ustąpić _xooox, który przechwytuje os, pozostawiając _x___x.
    • x__oox. Tutaj os nie są rejestrowane (nadal istnieje luka). Przechwytywanie nie jest możliwe, ponieważ nie można poruszać się przez niezajęte miejsca. Po xlewej stronie można przesunąć tylko jedno pole, ponieważ pomiędzy nimi nie ma innych elementów (pozostawiając _x_oox).
  • Wiele sąsiadujących elementów może zostać schwytanych na raz, jeśli grupa jest otoczona kawałkami przeciwnika. Np. Od x_ooxdo _xooxprzechwyci zarówno os, jak i spowoduje _x__x.
  • Jeśli po ruchu najpierw złapiesz pionki przeciwnika , zanim sprawdzisz, czy należy usunąć własny kawałek. Weź dwa przykłady:
    • o_oxxdo oxox_. Po pierwsze, drugi ozostaje schwytany ox_x_, więc pierwszy xpozostaje na planszy.
    • o_ooxdo oxoo_. Tym razem żaden z nich nie ojest przechwytywany, więc xzamiast tego jest przechwytywany.
    • Jeśli masz tylko jeden element, gra się kończy, ponieważ nie możesz przechwycić za pomocą tylko jednego elementu.

Niech rozpocznie się gra! Nie mogę się doczekać, aby zobaczyć, co wymyślisz.

ASCIIThenANSI
źródło
Komentarze zostały usunięte, ponieważ były przestarzałe. Powiadom mnie o wszelkich komentarzach, które powinny zostać usunięte.
Klamka

Odpowiedzi:

9

C, 617 592 bajtów

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

Rozpruty:

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

Naprawdę chciałem uzyskać ten w ~ 400 bajtach, ale jest tu wiele małych reguł, a przetwarzanie danych wejściowych zakończyło się dość nieznośnie. Zdecydowanie się z tym nie skończyłem. Oto zestaw przykładowych przebiegów obejmujący prawie wszystko:

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

Jeśli coś źle zinterpretowałem, daj mi znać!

BrainSteel
źródło
Przetestowałem to, działa dobrze i nic nie zostało pominięte. Dobra robota!
ASCIIThenANSI,
Możesz zaoszczędzić kilka bajtów, zastępując printf("INVALID");je puts("INVALID");, o<2||x<2z o<2|x<2i printf(b);while(!q){zfor(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);}}

Powiadomienia należy ukryć, przekierowując STDERRna adres /dev/null.

Z rozsądnym białym znakiem:

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

W przypadkach testowych 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
źródło
Co rozumiesz przez „powiadomienia / ostrzeżenia”?
ASCIIThenANSI
@ASCIIThenANSI Ostrzeżenia z powodu niecytowanych literałów znakowych: PHP Uwaga: Użycie niezdefiniowanej stałej o - przyjęto „o” w /tmp/pcg-48388.php w linii 2. Można przekierować je do / dev / null.
TimWolla
Czy to łamie program?
ASCIIThenANSI
@ASCIIThenANSI Nie, działa dobrze, jeśli zostaną przekierowani /dev/null.
TimWolla
Jeśli tak, program będzie działał poprawnie i będą przekierowywani do /dev/null.
ASCIIThenANSI
1

Python 2, 536 509 448 441 bajtów

Zadzwoń przez a(); ruchy należy wprowadzić w formularzu piece,destination(tj. 1,4); wyjdź z Ctrl-C. Jeśli ktoś widzi więcej możliwości gry w golfa, jestem cały w uszach.

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
źródło
1

SpecBAS - 718 bajtów

SpecBAS to zaktualizowana wersja Sinclair / ZX BASIC, która może działać poza emulatorem. (Wciąż interpretowane).

Użyłem niektórych nowych funkcji, aby zmniejszyć rozmiar tak bardzo, jak tylko mogłem.

Wiersz 12 ustawia wyrażenie regularne, aby wyszukiwać fragmenty „wciśnięte” za pomocą wbudowanego IF, a wiersz 18 używa charakteru INC (zamiast mówić 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

Wyjście (nie można skopiować z wdowy po wyjściu, więc zrzut ekranu) wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

Brian
źródło
0

C #, 730 bajtów

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

Wyobrażam sobie, że możliwe są dalsze ulepszenia. Z drugiej strony zinterpretowałem dane INVALIDwyjściowe jako zakończenie wykonania, więc może być konieczne naprawienie tego problemu, aby zachować zgodność z innymi odpowiedziami.

Andrzej
źródło