Escribe el juego más corto de alak

10

Alak fue inventado por el matemático AK Dewdney y descrito en su libro de 1984 Planiverse. Las reglas de Alak son simples:

Alak es un juego de dos jugadores que se juega en un tablero unidimensional con once máquinas tragamonedas. Cada ranura puede contener como máximo una pieza a la vez. Hay dos tipos de piezas, "x" y "o". Las x pertenecen a un jugador, las o al otro. La configuración inicial de la placa es:

      xxxx___oooo

Los jugadores se turnan para moverse. En cada turno, cada jugador puede mover solo una pieza, una vez. Un jugador no puede dejar pasar su turno. Un jugador puede mover cualquiera de sus piezas a la siguiente ranura desocupada a su derecha o izquierda, lo que puede implicar saltar sobre las ranuras ocupadas. Un jugador no puede mover una pieza del costado del tablero.

Si un movimiento crea un patrón en el que las piezas del oponente están rodeadas, en ambos lados, por dos piezas del color del motor (sin ninguna ranura vacía desocupada que interviene), entonces esas piezas rodeadas se eliminan del tablero.

El objetivo del juego es eliminar todas las piezas de tu oponente, momento en el cual el juego termina. Quitar todo menos uno también finaliza el juego, ya que el oponente no puede rodearte con una sola pieza, por lo que siempre perderá en unos pocos movimientos de todos modos.

Encontré este juego en línea y me preguntaba: ¿se puede jugar al golf?

Reglas del golf

  • Su código debe seguir todas las reglas del juego, manejar capturas, movimientos adecuados, etc. (la única excepción es que no tiene que agregar un bot, pero debe tener a ambos jugadores controlados de alguna manera, y un jugador debe ser humano).
  • La entrada debe ser mover la pieza en el mosaico X al mosaico Y, o salir. Por ejemplo, puede usar 1 4para decir 'mover esta pieza en la casilla 1 a la casilla 4'. quitterminaría el programa, aunque usar Control- Csería aceptable. También debe verificar si un movimiento no es válido (saliendo del tablero o moviéndose a un lugar en el que tendría que cruzar los espacios desocupados para llegar o enviar un mensaje que no sea un par de fichas o quit).
  • Salidas para los jugadores ganadores y no válidos deben ser P1 WINS, P2 WINSy INVALID, respectivamente. (Todos estos son 7 caracteres).
  • La salida debe mostrar el tablero. Eso es todo lo que se requiere.
  • No importa si usa ayudas como fichas numeradas u otras piezas.
  • El desafío termina si:

    • Una respuesta obtiene 50 votos
    • Una respuesta sigue siendo la mejor votada durante 3 semanas, y no se publicaron otras respuestas en ese momento

y el desafío tiene al menos 3 respuestas (por lo que hay una competencia real).

Reglas del juego

  • El jugador de la izquierda debe comenzar primero.
  • Solo una pieza ocupa un cuadrado a la vez. Mueves la pieza hacia la izquierda o hacia la derecha hasta que golpea un espacio desocupado. El tablero no se ajusta y no puedes moverte por las áreas desocupadas. Por ejemplo:
    • xoo__o. Aquí, el xmovimiento hacia la derecha cambiaría el tablero a _oox_o.
    • xxooo_. Aquí, el extremo izquierdo xpodría moverse para ceder _xooox, lo que captura el os, yéndose _x___x.
    • x__oox. Aquí, los os no se capturan (todavía hay una brecha). La captura no es posible porque no puede moverse a través de espacios desocupados. El xde la izquierda solo podía moverse un espacio, porque no hay otras piezas en el medio (al salir _x_oox).
  • Se pueden capturar varias piezas adyacentes a la vez si el grupo está rodeado por las piezas del oponente. Por ejemplo, desde x_ooxa _xooxcapturará ambos oy dará como resultado _x__x.
  • Si después de un movimiento, primero capturas las piezas del oponente , antes de verificar si tu propia pieza debe eliminarse. Toma dos ejemplos:
    • o_oxxa oxox_. Primero, el segundo oes capturado ox_x_, por lo que el primero xpermanece en el tablero.
    • o_ooxa oxoo_. Esta vez, ninguno de los os se captura, por lo que xse captura en su lugar.
    • Si solo tienes una pieza, el juego termina, porque no puedes capturar con solo una pieza.

¡Que empiecen los juegos! Espero ver lo que se te ocurre.

ASCIIThenANSI
fuente
Comentarios purgados, ya que eran obsoletos. Por favor notifíqueme de cualquier comentario que deba ser recuperado.
Pomo de la puerta

Respuestas:

9

C, 617 592 bytes

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

Desenredado:

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

Realmente quería obtener este en ~ 400 bytes, pero hay muchas pequeñas reglas aquí y el procesamiento de entrada terminó siendo bastante desagradable. Definitivamente no he terminado con esto. Aquí hay un conjunto de ejecuciones de muestra que cubre casi todo:

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

Si he malinterpretado algo, ¡hágamelo saber!

BrainSteel
fuente
Lo probé, funciona bien y no quedó nada. ¡Buen trabajo!
ASCIIThenANSI
Puede guardar algunos bytes reemplazando printf("INVALID");con puts("INVALID");, o<2||x<2con o<2|x<2y printf(b);while(!q){confor(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);}}

Los avisos deben suprimirse redirigiendo STDERRa /dev/null.

Con espacio en blanco sano:

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

Con los casos de prueba de 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
fuente
¿Qué quiere decir con "avisos / advertencias"?
ASCIIThenANSI
@ASCIIThenANSI Advertencias debido a literales de caracteres sin comillas: Aviso PHP: Uso de constante indefinida o - supuesta 'o' en /tmp/pcg-48388.php en la línea 2. Se pueden redirigir a / dev / null.
TimWolla
¿Eso rompe el programa?
ASCIIThenANSI
@ASCIIThenANSI No, funciona bien si se les redirige /dev/null.
TimWolla
Entonces está bien tenerlo siempre y cuando el programa continúe funcionando correctamente y se les redirija /dev/null.
ASCIIThenANSI
1

Python 2, 536 509 448 441 bytes

Llamar a través de a(); los movimientos deben ingresarse en la forma piece,destination(es decir, 1,4); Salga con Ctrl-C. Si alguien puede ver más potencial de golf, soy todo oídos.

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
fuente
1

SpecBAS - 718 bytes

SpecBAS es una versión actualizada de Sinclair / ZX BASIC que puede ejecutarse fuera de un emulador. (Aún interpretado).

He utilizado algunas de las nuevas funciones para reducir el tamaño tanto como pude.

La línea 12 establece una expresión regular para buscar piezas "intercaladas" usando IF en línea y la línea 18 usa la naturaleza envolvente de INC (en lugar de decir 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

Salida (no se puede copiar desde la ventana de salida, así que captura de pantalla) ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Brian
fuente
0

C #, 730 bytes

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

Me imagino que son posibles nuevas mejoras. Por otro lado, interpreté el INVALIDresultado como finalizando la ejecución, por lo que es posible que deba solucionar ese problema para estar a la par con otras respuestas.

Andrés
fuente