Напишіть найкоротшу гру алака


10

Алак був винайдений математиком А. К. Дьюдней і описаний у своїй книзі "Планіверс" 1984 року. Правила Алака прості:

Alak - гра для двох гравців, що грається на одновимірній дошці з одинадцятьма слотами на ній. Кожен слот може вмістити не більше однієї штуки за один раз. Є два види творів, "х" та "о". x належать одному гравцеві, o - іншому. Початкова конфігурація плати:

      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натомість вона захоплена.
    • Якщо у вас є лише одна штука, гра закінчується, тому що ви не можете захопити лише одну частину.

Нехай починаються ігри! Я з нетерпінням чекаю, що ви придумаєте.


Коментарі чистими, оскільки вони застаріли. Будь ласка, повідомте мене про будь-які коментарі, які слід залишити без відповіді.
Дверна ручка

Відповіді:


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

Якщо я щось неправильно трактував, будь ласка, повідомте мене!


Я перевірив це, він працює добре, і нічого не залишилося. Хороша робота!
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

Що ви маєте на увазі під "повідомленнями / попередженнями"?
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)

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вихід як закінчення виконання, тому, можливо, мені потрібно буде виправити це питання, щоб відповідати іншим відповідям.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.