Напиши самую короткую игру алака

10

Алак был изобретен математиком А. К. Дьюдни и описан в его книге Planiverse 1984 года. Правила Алака просты:

Алак - это игра для двух игроков на одномерной доске с одиннадцатью слотами. Каждый слот может содержать не более одного куска одновременно. Есть два вида фигур: «х» и «о». Х принадлежат одному игроку, О - другому. Начальная конфигурация платы:

      xxxx___oooo

Игроки ходят по очереди. На каждом ходу каждый игрок может перемещать только одну фигуру, один раз. Игрок не может отказаться от своего хода. Игрок может переместить любую из своих фигур в следующий незанятый слот вправо или влево, что может включать перепрыгивание через занятые слоты. Игрок не может сдвинуть фигуру со стороны доски.

Если ход создает рисунок, в котором фигуры противника с обеих сторон окружены двумя фигурами цвета движителя (без промежуточной пустой ячейки), то эти окруженные фигуры удаляются с доски.

Цель игры состоит в том, чтобы убрать все фигуры противника, после чего игра заканчивается. Удаление «все, кроме одного» также завершает игру, так как противник не может окружить вас одним куском, и в любом случае он всегда проигрывает в течение нескольких ходов.

Я нашел эту игру онлайн и подумал: а можно ли играть в гольф?

Правила игры в гольф

  • Ваш код должен соответствовать всем правилам игры, обработке захватов, правильному перемещению и т. Д. (Единственное исключение - вам не нужно добавлять бота, но вы должны как-то контролировать обоих игроков, а один игрок должен быть человеком).
  • Ввод должен быть перемещением фигуры на плитке X на плитку 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, которая захватывает os, оставляя _x___x.
    • x__oox, Здесь os не фиксируются (все еще есть разрыв). Захват невозможен, потому что вы не можете перемещаться по незанятым пространствам. xСлева может двигаться только одно место, потому что нет никаких других частей между (выезд _x_oox).
  • Несколько смежных фигур могут быть захвачены одновременно, если группа окружена фигурами противника. Например, от x_ooxдо _xooxбудет захватывать оба oс и в результате _x__x.
  • Если после хода вы сначала захватываете фигуры противника , прежде чем проверять, следует ли удалить свою фигуру. Возьмите два примера:
    • o_oxxк oxox_. Сначала oзахватывается второй , ox_x_поэтому первый xостается на доске.
    • o_ooxк oxoo_. На этот раз ни один из os не захвачен, поэтому xвместо этого захватывается.
    • Если у вас есть только одна фигура, игра заканчивается, потому что вы не можете захватить только одну фигуру.

Пусть игра начнется! Я с нетерпением жду встречи с тем, что вы придумали.

ASCIIThenANSI
источник
Комментарии удалены, так как они устарели. Пожалуйста, сообщите мне о любых комментариях, которые должны быть восстановлены.
Дверная ручка

Ответы:

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

Если я что-то неправильно понял, пожалуйста, дайте мне знать!

BrainSteel
источник
Я проверил это, он работает хорошо, и ничего не осталось. Отличная работа!
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
TimWolla
источник
Что вы подразумеваете под «уведомлениями / предупреждениями»?
ASCIIThenANSI
@ASCIIThenANSI Предупреждения из-за не заключенных в кавычки символьных литералов: Примечание 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)
sirpercival
источник
1

SpecBAS - 718 байт

SpecBAS - это обновленная версия Sinclair / ZX BASIC, которая может работать вне эмулятора. (Все еще интерпретируется).

Использовали некоторые из новых функций, чтобы уменьшить размер, насколько я мог.

В строке 12 задается регулярное выражение для поиска «зажатых» кусочков с использованием встроенного 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вывод как завершение выполнения, поэтому мне может потребоваться исправить эту проблему, чтобы соответствовать другим ответам.

Эндрю
источник