Écrivez le jeu le plus court d'Alak

10

Alak a été inventé par le mathématicien AK Dewdney et décrit dans son livre Planiverse de 1984. Les règles d'Alak sont simples:

Alak est un jeu à deux joueurs joué sur un plateau unidimensionnel avec onze emplacements. Chaque emplacement peut contenir au plus une pièce à la fois. Il existe deux types de pièces, "x" et "o". les x appartiennent à un joueur, les o à l'autre. La configuration initiale de la carte est:

      xxxx___oooo

Les joueurs se déplacent à tour de rôle. A chaque tour, chaque joueur ne peut déplacer qu'une seule pièce, une fois. Un joueur ne peut pas laisser passer son tour. Un joueur peut déplacer n'importe laquelle de ses pièces vers le prochain emplacement libre à sa droite ou sa gauche, ce qui peut impliquer de sauter par-dessus les emplacements occupés. Un joueur ne peut pas déplacer une pièce du côté du plateau.

Si un coup crée un motif où les pièces de l'adversaire sont entourées, des deux côtés, par deux pièces de la couleur du déménageur (sans emplacement vide inoccupé), alors ces pièces entourées sont retirées du plateau.

Le but du jeu est de retirer toutes les pièces de votre adversaire, point auquel le jeu se termine. La suppression de tout sauf un met également fin au jeu, car l'adversaire ne peut pas vous entourer d'une seule pièce, et perdra donc toujours en quelques mouvements de toute façon.

J'ai trouvé ce jeu en ligne et je me demandais: peut-il être joué au golf?

Règles du golf

  • Votre code doit suivre toutes les règles du jeu, gérer les captures, se déplacer correctement, etc. (la seule exception est que vous n'avez pas besoin d'ajouter un bot, mais vous devez avoir les deux joueurs contrôlés d'une manière ou d'une autre et un joueur doit être humain).
  • L'entrée doit être déplacer la pièce de la tuile X vers la tuile Y ou quitter. Par exemple, vous pouvez utiliser 1 4pour dire «déplacer cette pièce de la tuile 1 à la tuile 4». quitmettrait fin au programme, bien que l'utilisation de Control- Csoit acceptable. Vous devez également vérifier si un mouvement n'est pas valide (en sortant du plateau ou en vous déplaçant quelque part où vous devrez traverser des espaces inoccupés pour vous rendre ou envoyer un message qui n'est pas une paire de tuiles ou quit).
  • Sorties pour les joueurs gagnants et invalides doivent être P1 WINS, P2 WINSet INVALID, respectivement. (Ce sont tous 7 caractères.)
  • La sortie doit montrer la carte. C'est tout ce qu'il faut.
  • Peu importe si vous utilisez des aides comme des tuiles numérotées ou d'autres pièces.
  • Le défi prend fin si:

    • Une réponse obtient 50 votes
    • Une réponse reste le plus voté pendant 3 semaines, et aucune autre réponse n'a été publiée pendant cette période

et le défi a au moins 3 réponses (donc il y a une vraie compétition).

Règles du jeu

  • Le joueur de gauche doit commencer en premier.
  • Une seule pièce occupe un carré à la fois. Vous déplacez la pièce vers la gauche ou la droite jusqu'à ce qu'elle touche un espace inoccupé. Le plateau ne s'enroule pas et vous ne pouvez pas vous déplacer dans les zones inoccupées. Par exemple:
    • xoo__o. Ici, le xdéplacement vers la droite changerait le conseil d'administration en _oox_o.
    • xxooo_. Ici, la plus à gauche xpourrait se déplacer pour céder _xooox, ce qui capture les os, en partant _x___x.
    • x__oox. Ici, les os ne sont pas capturés (il y a encore un écart). La capture n'est pas possible car vous ne pouvez pas vous déplacer dans les espaces inoccupés. La xgauche ne peut déplacer qu'un espace, car il n'y a pas d'autres pièces entre les deux (en partant _x_oox).
  • Plusieurs pièces adjacentes peuvent être capturées à la fois si le groupe est entouré par les pièces de l'adversaire. Par exemple, de x_ooxà _xooxcapturera à la fois os et entraînera _x__x.
  • Si après un coup, vous capturez d'abord les pièces de l' adversaire , avant de vérifier si votre propre pièce doit être retirée. Prenons deux exemples:
    • o_oxxà oxox_. Tout d'abord, le second oest capturé, ox_x_donc le premier xreste sur le plateau.
    • o_ooxà oxoo_. Cette fois, aucun des os n'est capturé, donc le xest capturé à la place.
    • Si vous n'avez qu'une seule pièce, le jeu se termine, car vous ne pouvez pas capturer avec une seule pièce.

Que les jeux commencent! J'ai hâte de voir ce que vous proposez.

ASCIIThenANSI
la source
Les commentaires ont été supprimés, car ils étaient obsolètes. Veuillez m'informer de tout commentaire qui ne devrait pas être supprimé.
Poignée de porte

Réponses:

9

C, 617 592 octets

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

Démêlé:

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

Je voulais vraiment obtenir celui-ci en ~ 400 octets, mais il y a beaucoup de petites règles ici et le traitement d'entrée s'est avéré assez désagréable. Je n'en ai définitivement pas fini avec ça. Voici un ensemble d'exécutions qui couvre à peu près tout:

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 j'ai mal interprété quelque chose, faites-le moi savoir!

BrainSteel
la source
Je l'ai testé, cela fonctionne bien et rien n'a été oublié. Bon travail!
ASCIIThenANSI
Vous pouvez économiser quelques octets en remplaçant printf("INVALID");par puts("INVALID");, o<2||x<2avec o<2|x<2et printf(b);while(!q){avecfor(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);}}

Les avis doivent être supprimés en redirigeant STDERRvers /dev/null.

Avec un espace sain:

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

Avec les cas de test 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
la source
Qu'entendez-vous par «avis / avertissements»?
ASCIIThenANSI
@ASCIIThenANSI Avertissements en raison de littéraux de caractères non cités: PHP Remarque: Utilisation de la constante non définie o - supposé «o» dans /tmp/pcg-48388.php sur la ligne 2. On peut les rediriger vers / dev / null.
TimWolla
Est-ce que cela rompt le programme?
ASCIIThenANSI
@ASCIIThenANSI Non, cela fonctionne bien s'ils sont redirigés vers /dev/null.
TimWolla
Ensuite, c'est OK de l'avoir tant que le programme continue de fonctionner correctement et qu'ils sont redirigés vers /dev/null.
ASCIIThenANSI
1

Python 2, 536 509 448 441 octets

Appelez via a(); les mouvements doivent être saisis dans le formulaire piece,destination(c.-à-d. 1,4); quittez avec Ctrl-C. Si quelqu'un peut voir plus de potentiel de golf, je suis à l'écoute.

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
la source
1

SpecBAS - 718 octets

SpecBAS est une version mise à jour de Sinclair / ZX BASIC qui peut s'exécuter en dehors d'un émulateur. (Toujours interprété).

J'ai utilisé certaines des nouvelles fonctionnalités pour réduire la taille autant que possible.

La ligne 12 met en place une expression régulière pour rechercher des morceaux "pris en sandwich" en utilisant IF en ligne et la ligne 18 utilise la nature enveloppante de INC (plutôt que de dire 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

Sortie (impossible de copier à partir de la fenêtre de sortie, donc capture d'écran) entrez la description de l'image ici

entrez la description de l'image ici

Brian
la source
0

C #, 730 octets

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

J'imagine que d'autres améliorations sont possibles. D'un autre côté, j'ai interprété la INVALIDsortie comme mettant fin à l'exécution, donc je devrai peut-être résoudre ce problème pour être en parité avec les autres réponses.

Andrew
la source