アラクの最短のゲームを書く


10

Alakは数学者AK Dewdneyによって発明され、1984年の本Planiverseに記載されています。アラクのルールは簡単です:

Alakは、11スロットの1次元ボードでプレイする2人用のゲームです。各スロットは一度に最大で1つの部品を保持できます。「x」と「o」の2種類のピースがあります。xは1つのプレーヤーに属し、oはもう1つのプレーヤーに属します。ボードの初期構成は次のとおりです。

      xxxx___oooo

プレイヤーは順番に移動します。各ターンで、各プレイヤーは一度に1つの駒のみを移動できます。プレーヤーは自分のターンに追い越すことはできません。プレーヤーは自分の駒のいずれか1つを次の空いているスロットの右または左に移動できます。これには、空いているスロットを飛び越える必要がある場合があります。プレーヤーは、駒をボードの側面から移動することはできません。

移動によって、対戦相手の駒が両側に2つの駒の可動子の色で囲まれているパターンが作成された場合(空いている空白のスロットが介在しない)、それらの囲まれた駒はボードから削除されます。

ゲームの目的は、対戦相手の駒をすべて取り除くことです。この時点でゲームは終了します。all-but-oneを削除すると、ゲームも終了します。これは、対戦相手が1つの駒であなたを囲むことができないため、とにかく数回の移動で常に負けるからです。

私はこのゲームをオンラインで見つけ、疑問に思っていました:ゴルフはできますか?

ゴルフのルール

  • コードは、ゲーム内のすべてのルール、キャプチャの処理、適切な移動などに従う必要があります(ボットを追加する必要はありませんが、両方のプレイヤーを何らかの方法で制御し、一方のプレイヤーを人間にする必要があります)。
  • 入力は、タイルXのタイルをYに移動するか、終了する必要があります。たとえば、1 4「この作品をタイル1からタイル4に移動」と言うことができます。- をquit使用しても、プログラムは終了します。また、移動が無効であるかどうかを確認する必要があります(ボードの外に出るか、空いているスペースを横切ってタイルのペアでないメッセージを送信または送信する必要がある場所に移動するか、)。ControlCquit
  • 優勝選手と無効なため出力がでなければならないP1 WINSP2 WINSINVALIDそれぞれ。(これらはすべて7文字です。)
  • 出力はボードを示す必要があります。それだけで十分です。
  • 番号付きのタイルやその他のピースなどの補助具を使用するかどうかは関係ありません。
  • チャレンジは次の場合に終了します。

    • 1つの回答で50票を獲得
    • 3週間、1つの回答が上位投票されたままになり、その期間に他の回答は投稿されませんでした

チャレンジには少なくとも3つの答えがあります(そのため、実際の競争があります)。

ゲームのルール

  • 左側のプレーヤーが最初にスタートする必要があります。
  • 一度に正方形を占めるのは1個だけです。それが空いているスペースにぶつかるまで、ピースを左または右に移動します。ボードは折り返されず、占有されていない領域を移動することはできません。例えば:
    • xoo__o。ここで、x移動権はボードをに変更し_oox_oます。
    • xxooo_。ここで、左端xはyield _xoooxに移動し、os をキャプチャしてを残し_x___xます。
    • x__oox。ここでは、osはキャプチャされていません(まだギャップがあります)。空いているスペースを移動できないため、キャプチャはできません。x間には他の部分(残しがないので、左側のは、1つのスペースを移動することができます_x_oox)。
  • グループが対戦相手の駒に囲まれている場合、複数の隣接する駒を一度にキャプチャできます。例えばx_ooxには_xoox、両方のキャプチャしますo秒とにつながります_x__x
  • 移動後の場合は、最初に相手の駒をキャプチャしてから、自分の駒を削除する必要があるかどうかを確認します。2つの例を見てみましょう。
    • o_oxxoxox_。1つ目oは2つ目がキャプチャされるox_x_ため、1 つ目はxボードに残ります。
    • o_ooxoxoo_。今回は、osはキャプチャされないため、x代わりにがキャプチャされます。
    • ピースが1つしかない場合は、1つではキャプチャできないため、ゲームは終了します。

ゲームを始めよう!あなたが思いつくものを見るのを楽しみにしています。


コメントは廃止されたため、削除されました。元に戻す必要があるコメントがあれば通知してください。
ドアノブ

回答:


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 2015

あなたは置き換えることによって、数バイトを保存することができprintf("INVALID");puts("INVALID");o<2||x<2o<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 2015年

@ASCIIThenANSI引用符で囲まれていない文字リテラルによる警告:PHP通知:未定義の定数oの使用-2行目の/tmp/pcg-48388.phpで「o」を想定しています。/dev/nullにリダイレクトできます。
TimWolla

それはプログラムを壊しますか?
ASCIIThenANSI 2015年

@ASCIIThenANSIいいえ、リダイレクトされて正常に機能し/dev/nullます。
TimWolla

その後、プログラムが適切に機能し続け、それらがにリダイレクトされる限り、それは問題ありません/dev/null
ASCIIThenANSI 2015年

1

Python 2、536 509 448441バイト

経由で呼び出し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出力を実行の終了として解釈したので、他の回答と同等になるようにその問題を修正する必要があるかもしれません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.