编写最短的alak游戏


10

Alak由数学家AK Dewdney发明,并在1984年的著作Planiverse中进行了描述。Alak的规则很简单:

Alak是在具有11个插槽的一维板上玩的两人游戏。每个插槽一次最多只能容纳一个。有两种,“ x”和“ o”。x属于一个玩家,o属于另一玩家。该单板的初始配置为:

      xxxx___oooo

玩家轮流移动。在每个回合中,每个玩家只能移动一次。玩家在转牌时无法通过。玩家可以将自己的任何一块游戏移至其右侧或左侧的下一个未占用的插槽,这可能涉及跳过占用的插槽。玩家不能将棋子从棋盘的一侧移开。

如果移动产生了一种模式,对手的棋子在两侧被动子的两个棋子颜色包围(中间没有闲置的空白插槽),则这些棋子被从棋盘上移开。

游戏的目标是删除对手的所有棋子,然后游戏结束。删除所有的一个也将结束游戏,因为对手无法用一个包围你,因此无论如何都会输掉几步。

我在网上找到了这个游戏,想知道:可以打高尔夫球吗?

高尔夫规则

  • 您的代码必须遵循游戏中的所有规则,处理捕获,正确移动等(唯一的例外是您不必添加机器人,但必须以某种方式控制两个玩家,并且一个玩家必须是人类。)
  • 输入必须在图块X到图块Y处移动,或者退出。例如,您可以1 4说“将此块从图块1移动到图块4”。quit将结束该程序,尽管使用Control- C是可以接受的。您还必须检查移动是否无效(通过走出木板或移动到您不得不越过空闲的空间才能到达或发送不是一对磁贴或的消息quit)。
  • 玩家赢得的和无效的输出必须是P1 WINSP2 WINSINVALID分别。(所有这些都是7个字符。)
  • 输出必须显示板。这就是全部。
  • 是否使用任何辅助工具(如编号的瓷砖或其他物件)都没关系。
  • 该挑战在以下情况下结束:

    • 一个答案可获得50票
    • 3个星期内,一个答案仍然是票数最高的答案,并且在那时没有其他答案发布

并且挑战至少有3个答案(所以有一些真正的竞争)。

游戏规则

  • 左边的玩家必须先开始。
  • 一次只有一块占据一个正方形。您可以向左或向右移动片段,直到碰到一个空位。木板不包裹,您不能在未占用的区域中移动。例如:
    • xoo__o。在这里,x向右移动会将板更改为_oox_o
    • xxooo_。在这里,最左边的x可以移动到yield _xooox,它捕获os,离开_x___x
    • x__oox。在此,o不捕获s(仍然存在间隙)。无法捕获,因为您无法在闲置空间中移动。在x左侧只能移动一分格,因为没有其他部分之间(离开_x_oox)。
  • 如果组被对手的棋子包围,则可以一次捕获多个相邻棋子。例如,从x_oox_xoox将同时捕获os和_x__x
  • 如果在移动之后,首先要捕获对手的棋子,然后再检查是否应删除自己的棋子。举两个例子:
    • o_oxxoxox_。首先,o捕获第二个ox_x_,因此第一个x保留在板上。
    • o_ooxoxoo_。这次,没有o捕获到,因此x捕获了。
    • 如果只有一件,则游戏结束,因为您不能仅凭一件就捕捉到。

让游戏开始!我期待看到您的想法。


评论已删除,因为它们已过时。如果有任何评论应删除,请通知我。
Doorknob

Answers:


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<2printf(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-在第2行的/tmp/pcg-48388.php中假定为'o'。可以将其重定向到/ dev / null。
TimWolla 2015年

这会破坏程序吗?
ASCIIThenANSI

@ASCIIThenANSI不,它被重定向到时,它的工作正常/dev/null
TimWolla 2015年

然后,只要程序继续正常运行,就可以将其重定向到/dev/null
ASCIIThenANSI,2015年

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输出解释为结束执行,因此我可能需要解决该问题才能与其他答案保持一致。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.