给定标准下的棋盘,下有效棋步


11

程序播放白色。

示例stdin:

8 ║♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟ … ♟ ♟ ♟
6 ║… … … … … … … …
5 ║… … … … ♟ … … …
4 ║… … … … … … … …
3 ║… … ♘ … … … … …
2 ║♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙
1 ║♖ … ♗ ♕ ♔ ♗ ♘ ♖
——╚═══════════════
—— a b c d e f g h

标准输出示例:

8 ║♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟ … ♟ ♟ ♟
6 ║… … … … … … … …
5 ║… … … … ♟ … … …
4 ║… … … … ♙ … … …
3 ║… … ♘ … … … … …
2 ║♙ ♙ ♙ ♙ … ♙ ♙ ♙
1 ║♖ … ♗ ♕ ♔ ♗ ♘ ♖
——╚═══════════════
—— a b c d e f g h

任何有效的举动都可以。“ En passant”和castling被忽略。如果没有有效的动作,可以显示错误消息或不打印任何内容。

票数最多的答案将获胜。


我的意思是由于该语言的某些内置功能失败而导致的标准错误消息。这样没关系吗 —该程序可以采取任何法律措施是否强制性的?也许应该让小板和典当的特殊动作带有一些额外的奖励?
停止转动逆时针

2
@leftaroundabout:只要有城堡,就可以移动小车,因此至少可以跳过逻辑。
hammar 2012年

2
……再想一想,“被动”举动需要有关先前做出的举动的信息,而这不能仅从棋子的位置推断出来,所以我认为可以放心了。但是,可以从棋子的等级推断出是否可以进行双倍先动,因此您可能需要将其包括在内。
hammar 2012年

@hammar:你是对的,我还没想到。一种情况,双举也并不重要:当您可以走两步时也可以走一步,因此只有当您处于支票状态时,这才变得很重要,并且双举是唯一覆盖国王的举动。同样,即使不需要使用所有举动,您仍然需要考虑到黑色可以解决任何问题。
停止转动逆时针

9
辞职算是合法举动吗?:)
gnibbler 2012年

Answers:


16

我并不是在抱怨投票,而是为了公平起见……我在这里的解决方案实际上并不是那么好。除了缺乏Unicode支持外,Ugoren的效果更好。如果您现在才遇到这个问题,请务必在投票前先查看所有答案!
无论如何。

Haskell,893 888 904 952(无铸造)

862(无典当双动)

(您没有指定这是否应该是代码高尔夫球,但在我看来应该如此)

χ=w⋈b;w="♙♢♤♔♕♖♗♘";b="♟♦♠♚♛♜♝♞"
μ=t⤀ζ++((\(x,y)->(x,-y))⤀)⤀μ;q c|((_,m):_)<-((==c).fst)☂(χ⋎μ)=m
t(x:y:l)=(d x,d y):t l;t _=[];d c=fromEnum c-78
ζ=["NM","NL","MMOM","MMMNMONMNOOMONOO",σ⋈δ,σ,δ,"MLOLPMPOOPMPLOLM"]
σ=l>>=(\c->'N':c:c:"N");δ=[l⋎l,reverse l⋎l]>>=(>>=(\(l,r)->[l,r]))
l="GHIJKLMOPQRSTU"
α c|c∊"♢♤"='♙'|c∊"♦♠"='♟'|c∊χ=c;π('♙':_)=6;π _=1
(⋎)=zip;(⤀)=map;(∊)=elem;(✄)=splitAt;(☂)=filter;(⋈)=(++)
φ r@(x,y)p a
 |x>7=φ(0,y+1)p a
 |y>7=[]
 |c<-a✠r=(c⌥r)p a y⋈φ(x+1,y)p a
(c⌥r)p a y
 |c==p!!0=(a☈r)c χ++const(y==π p)☂(a☈r)(p!!1)χ++(a☈r)(p!!2)('…':w)
 |c∊p=(a☈r)c χ
 |True=[]
a✠(x,y)=a!!y!!(x*2);o(x,y)=x>=0&&x<8&&y>=0&&y<8
(n➴a)(x,y)|(u,m:d)<-y✄a,(l,_:r)<-(x*2)✄m=u⋈(l⋈(n:r):d)
(a☈r@(x,y))c b=(α c➴('…'➴a)r)⤀((\r->o r&&not((a✠r)∊b))☂((\(ξ,υ)->(x+ξ,y+υ))⤀q c))
main=interact$unlines.uncurry((⋈).zipWith((⋈).(:" ║"))['8','7'..]
 .head.((all(any('♔'∊)).φ(0,0)b)☂).φ(0,0)w.(drop 3⤀)).(8✄).lines

当您安装了GHC(例如作为Haskell平台的一部分)后,您可以

$ runhaskell def0.hs < examplechessboard.txt
8 ║♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟ … ♟ ♟ ♟
6 ║… … … … … … … …
5 ║… ♘ … … ♟ … … …
4 ║… … … … … … … …
3 ║… … … … … … … …
2 ║♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙
1 ║♖ … ♗ ♕ ♔ ♗ ♘ ♖
——╚═══════════════
—— a b c d e f g h

现在这很疯狂:)我将检查一下:)
Hristo Hristov 2012年

知道如何测试这种超赞吗?Ideone.com无法处理...
Hristo Hristov

@HristoHristov:奇怪,它在Ideone上不起作用。可能与非ASCII字符有关。
停止转动逆时针

是的,这是ideone的问题
Hristo Hristov

14
恭喜,您已成功使Haskell看起来像APL。:-)
Ilmari Karonen 2012年

11

C,734个 672 640字符

字符数没有可移动的空格。
我使用的文件格式不是要求的,而是简化的ASCII。
我需要添加Unicode字符支持,这将花费一些字符。

char*r=" kpnbrq  KPNBRQ $ ,&)$wxy()879()8(6:GI(",B[256],*b=B,i;
e(x,d,m,V,c,r,n,p){
    for(r=0,p=b[x];m/++r;){
        n=x+d*r;
        if(p==2+8*(d<0)||n&136||!(b[n]?r=8,8^p^b[n]^8&&c&65^64:c&65^65)
            ? r=m,0
            : V?v(n,x):b[n]==1)
            return b[x]=0,b[n]=p%8-2||n/16%7?p:p+4;
    }
    return d>0&&e(x,-d,m,V,c);
}
d(x,v,m,i)char*m;{
    return(i=*m-40)?e(x,i%64,b[x]%8-2?b[x]&4?7:1:(x/16-1)%5|i%2?1:2,v,i)||d(x,v,m+1):0;
}
v(t,f){
    bcopy(B,b+=128,128);
    b[t]=b[f];b[f]=0;
    i=a(1,63);
    b=B;
    return!i;
}
a(c,n){
    return b[i=n*2-n%8]&&b[i]/8==c&&d(i,!c,r+r[b[i]%8+15]-10)||n--&&a(c,n);
}
main(){
    for(;gets(b);b+=8)for(;*b;b++)*b=strchr(r,*b)-r;b=B;
    for(i=64*!a(0,63);i<64;i++%8-7||puts(""))putchar(r[b[i*2-i%8]]);
}

输入/输出文件格式:
必须为正好8个字符的正好8行。pnbrqk用于白色,PNBRQK黑色,空格

RNBQKBNR
PPPP PPP

 n  P


pppppppp
r bqkbnr

逻辑很简单:
对于每个白色块的每个可能动作,请尝试每个黑色块的每个可能动作。
如果没有黑棋抓住白王,​​那么白棋是有效的。

板子保持为char[256],视为16x16矩阵,仅使用左上角的8x8。位置和运动矢量保存在8位整数(x:4,y:4)中。额外的位允许使用简单的算术(new_pos = old_pos + steps*direction),并易于检测棋盘边缘(&0x88魔术)。 r[]编码三件事:

  1. 前15个字节将内部段码(K = 1,P = 2,N = 3,B = 4,R = 5,Q = 6)映射为字母。
  2. 接下来的6个字节将内部段代码映射到最后一部分的偏移量(K和Q相同,B是它们的尾部)。
  3. 后16个字节编码所有片段的运动,如'('+vector

功能:

  1. main读取白板,将字母转换为内部代码,调用a以查找白色棋子,然后打印白板。
  2. a递归地循环遍历64个正方形。对于每个正确的颜色(参数c),它找到该块的运动规则并调用d
  3. d递归地循环遍历编码的运动规则,该运动规则是向量列表,并e要求每个向量。它给出e了原始位置,向量和范围限制(B之上的块为7,二等兵为2,否则为1)。
  4. e测试沿着矢量的所有运动。如果可以移动(即棋子向前移动,在棋盘内,未被阻塞,棋子对角捕获),请检查以下两项。对于白色动作,运行v以验证该动作。对于黑棋,检查是否捕获了白王。如果为true,则在棋盘上进行移动。
  5. v验证白色举动。它将板复制到一边,执行测试以进行移动,然后a再次调用以查找黑色移动。

最后,一个对可能的动作进行适当压缩编码的解决方案!而且速度非常快。您是否不认为可以添加Unicode包装器,但仍比我的代码短?
停止旋转逆时针

@leftaroundabout,我想我可以。主要问题是我在Linux命令行中工作,在该命令行中看不到Unicode,因此调试它会很烦人。我还有一个版本可以节省大约40个字节(我将很快更新),因此我有很多字符可以使用。
ugoren

@ugoren:当然,任何现代的Linux发行版都可以立即支持UTF-8吗?
2012年

@han,我正在Windows上工作,并通过SSH连接到Linux,Unicode无法正常工作。我可以写文件并在Windows中打开,但是这不再有趣了。
ugoren

可以用gcc编译吗?我正在将Geany for Windows与MinGW一起使用,它将编译出许多错误和警告,但不会编译/运行。例如:C:\ Users \ xxx \ AppData \ Local \ Temp \ ccpBG9zy.o:codegolfchess.c :(。text + 0x2d8):未定义对“ bcopy” collect2的引用:ld返回1退出状态
rpd 2012年

5

Python 2.6中,886 - 1425个字符

我的初始版本(修订版)以886个字符输入,但不完全符合规范(它没有检查是否避免将死;它甚至没有考虑黑色碎片的可能移动)。

现在可以了(我已经修复了原来的几个错误)。las,这要付出一些代价:目前为1425,但仍然没有什么改进的余地。这个版本在处理边缘情况方面应该比上一个版本更加可靠。

#-*-coding:utf8-*-
import sys;e=enumerate
B,W=["♟","♜","♞","♝","♛","♚"],["♙","♖","♘","♗","♕","♔"]
R={"♙":[11,42],"♖":[28],"♘":[31],"♗":[8],"♕":[8,28],"♔":[1,21]}
def F(w):return sum([[(i,j)for j,p in e(o)if p==w]for i,o in e(Z)],[])
def G(x,y):
 P=Z[x][y];D=P in W;L=[]
 for o in R[P]if D else R[unichr(ord(P.decode('utf8'))-6).encode('utf8')]:
  r,k="%02d"%o        
  for g,h in[[(-1,-1),(1,1),(-1,1),(1,-1)],[[(1,-1),(1,1)],[(-1,-1),(-1,1)]][D],[(-1,0),(1,0),(0,-1),(0,1)],[(-2,-1),(-2,1),(-1,-2),(-1,2),(1,-2),(1,2),(2,-1),(2,1)],[(-1,0)]][int(r)]:
   J=0
   for i in range(int(k)):
    T=x+(i+1)*g;U=y+(i+1)*h
    if T<0 or T>7 or U<0 or U>7:break
    M=Z[T][U]
    if not J:L.append((T,U,P,M))
    else:break
    if r in"02"and(M in W+B):
     J=1
     if not((D and M in B)or(not D and M in W)):L.pop()
    elif(r=="1"and not((D and M in B)or(not D and M in W)))or(r=="4"and((i==1 and x!=6)or M!="…")):L.pop()
 return L  
Z=[[y for y in l[5:].split()]for l in sys.stdin.readlines()[:-2]]
Q=[]
for p in R:
 for i,j in F(p):
  for M,L,c,_ in G(i,j):
   O=Z[M][L];Z[i][j]="…";Z[M][L]=c;E=[];map(E.extend,map(F,B))
   if not any(any(1 for _,_,_,I in G(v,h)if I==["♔","♚"][c in B])for v,h in E):Q.append((i,j,M,L,c))
   Z[i][j]=c;Z[M][L]=O
(x,y,X,Y,p)=Q[0];Z[x][y]="…";Z[X][Y]=p
for i,h in e(Z):print`8-i`+' ║'+' '.join(h)
print"——╚"+"═"*16+"\n—— a b c d e f g h"

输入和输出示例:

#输入

8♝………♞
7♟♟……♟
6║…………………………
5║♟
4║♛♛♛
3…………………………
2………………
1║♖♗♘
——╚═══════════════
-abcdefgh
#输出

8♝………♞
7♟♟……♟
6║…………………………
5║♟
4║♛♛♛
3║♙………
2♙♙……
1║♖♗♘
——╚════════════════
-abcdefgh

它是886个字节,但只有854个字符。(由于有许多非ASCII运算符,我的程序有1kB以上的空间!)—您是否还要添加支票检查功能?
停止转动逆时针

@leftaroundabout:我已经添加了国王检查(这迫使我也要考虑黑色的可能移动,并添加很多字符...)。哦,好了,这个版本应该在边缘情况下更可靠(据我测试)。
ChristopheD
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.