Chơi một nước cờ hợp lệ, đưa ra một bảng trên stdin


11

Chương trình chơi trắng.

Ví dụ stdin:

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

Ví dụ tiêu chuẩn:

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

Bất kỳ di chuyển hợp lệ là ok. "En passant" và castling bị bỏ qua. Bạn có thể hiển thị thông báo lỗi hoặc in không có gì nếu không có động thái hợp lệ.

Câu trả lời có nhiều phiếu nhất sẽ thắng.


Tôi có nghĩa là một thông báo lỗi tiêu chuẩn gây ra bởi sự thất bại của một số chức năng tích hợp của ngôn ngữ. Vậy có ổn không? - Có bắt buộc chương trình có thể thực hiện bất kỳ động thái hợp pháp nào không? Có lẽ nên di chuyển đặc biệt castling và cầm đồ với một số tiền thưởng?
đã ngừng quay ngược chiều

2
@leftaroundabout: Bất cứ khi nào bạn có thể lâu đài, bạn chỉ có thể di chuyển các tân binh thay vào đó, vì vậy bạn có thể bỏ qua logic cho điều đó ít nhất.
hammar

2
... Và nghĩ thêm về nó, động tác "en passant" yêu cầu thông tin về những động tác trước đó đã được thực hiện, không thể suy ra từ vị trí của các quân cờ, vì vậy tôi đoán có thể an toàn khi bỏ nó. Tuy nhiên, liệu bước di chuyển đầu tiên có sẵn có thể được suy ra từ cấp bậc của con tốt hay không, vì vậy bạn có thể muốn bao gồm điều đó.
hammar

@hammar: bạn nói đúng, tôi đã không nghĩ về điều đó. Di chuyển kép cũng không quan trọng, ngoại trừ một trường hợp: khi bạn có thể đi hai bước bạn cũng có thể đi một bước, vì vậy nó chỉ trở nên quan trọng khi bạn kiểm tra và di chuyển kép là di chuyển duy nhất bao trùm nhà vua. Ngoài ra, ngay cả khi bạn không cần phải có thể sử dụng mọi di chuyển, bạn vẫn cần xem xét rằng màu đen có thể trả lời với bất kỳ khả năng nào.
đã ngừng quay ngược chiều

9
Là từ chức được tính là một động thái hợp pháp? :)
gnibbler

Câu trả lời:


16

Tôi không phàn nàn về upvote, nhưng công bằng mà nói ... giải pháp của tôi ở đây không thực sự tuyệt vời đến thế. Ugoren là tốt hơn, ngoài việc thiếu hỗ trợ unicode. Hãy chắc chắn xem tất cả các câu trả lời trước khi bỏ phiếu, nếu bạn chỉ gặp câu hỏi này ngay bây giờ!
Dù sao.

Haskell, 893 888 904 952 (không đúc)

862 (không có di chuyển kép cầm đồ)

(Bạn đã không xác định nếu đây được coi là mã golf, nhưng đối với tôi nó nên như vậy)

χ=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

Khi bạn đã cài đặt GHC (ví dụ như một phần của nền tảng Haskell ), bạn có thể làm chỉ

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

Bây giờ điều này thật điên rồ :) Tôi sẽ kiểm tra xem :)
Hristo Hristov

Bất kỳ ý tưởng làm thế nào để kiểm tra sự tuyệt vời này? Ideone.com không thể xử lý nó ...
Hristo Hristov

@HristoHristov: lạ là nó không hoạt động trên Ideone. Có lẽ phải làm với các ký tự không phải ASCII.
đã ngừng quay ngược chiều

vâng, đây là vấn đề với ideone
Hristo Hristov

14
Xin chúc mừng, bạn đã quản lý để làm cho Haskell trông giống như APL. :-)
Ilmari Karonen

11

C, 734 672 640 ký tự

Nhân vật được tính mà không có khoảng trắng có thể tháo rời.
Định dạng tệp tôi sử dụng không theo yêu cầu, nhưng đơn giản hóa ASCII.
Tôi cần thêm hỗ trợ ký tự Unicode, nó sẽ tốn một số characets.

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]]);
}

Định dạng tệp đầu vào / đầu ra:
Phải chính xác 8 dòng có chính xác 8 ký tự. pnbrqkđược sử dụng cho các mảnh màu trắng, PNBRQKcho các mảnh màu đen, không gian cho không gian:

RNBQKBNR
PPPP PPP

 n  P


pppppppp
r bqkbnr

Logic khá đơn giản:
Đối với mỗi lần di chuyển có thể của từng mảnh trắng, hãy thử từng di chuyển có thể của từng mảnh đen.
Nếu không có di chuyển màu đen nào bắt được vua trắng, thì di chuyển trắng là hợp lệ.

Bảng được duy trì dưới dạng char[256], được coi là ma trận 16x16, trong đó chỉ sử dụng 8 x 8 trên cùng bên trái. Vị trí và vectơ chuyển động được giữ trong số nguyên 8 bit ( x:4,y:4). Bit thêm cho phép sử dụng số học đơn giản ( new_pos = old_pos + steps*direction), với sự phát hiện dễ dàng của cạnh bảng ( &0x88thực hiện phép thuật). r[]mã hóa ba điều:

  1. 15 byte đầu tiên ánh xạ mã mảnh nội bộ (K = 1, P = 2, N = 3, B = 4, R = 5, Q = 6) thành chữ cái.
  2. 6 byte tiếp theo ánh xạ mã mảnh nội bộ thành phần bù trong phần cuối (K và Q giống nhau, B là đuôi của chúng).
  3. 16 byte cuối cùng mã hóa chuyển động của tất cả các mảnh, như '('+vector.

Chức năng:

  1. mainđọc bảng, chuyển đổi chữ cái thành mã nội bộ, gọi ađể tìm di chuyển màu trắng, in bảng.
  2. avòng lặp đệ quy trên 64 ô vuông. Đối với mỗi phần của màu bên phải (tham số c), nó tìm quy tắc chuyển động cho phần và cuộc gọi d.
  3. dcác vòng lặp đệ quy trên quy tắc di chuyển được mã hóa, đó là một danh sách các vectơ, gọi echo mỗi cái. Nó đưa ra evị trí ban đầu, vectơ và giới hạn phạm vi (7 cho các mảnh trên B, 2 cho các con tốt thứ hạng thứ hai, 1 nếu không).
  4. ekiểm tra tất cả các chuyển động dọc theo một vectơ. Nếu di chuyển là có thể (tức là cầm đồ di chuyển về phía trước, trong bảng, không bị chặn, cầm đồ bắt chéo), kiểm tra một trong hai điều. Đối với di chuyển màu trắng, chạy vđể xác nhận di chuyển. Đối với di chuyển màu đen, kiểm tra nếu vua trắng bị bắt. Nếu đúng, di chuyển được chơi trên bảng.
  5. vxác nhận một động thái trắng. Nó sao chép bảng sang một bên, thực hiện di chuyển để kiểm tra và gọi alại, để tìm kiếm di chuyển màu đen.

Cuối cùng, một giải pháp với mã hóa nén thích hợp của các động thái có thể! Và nó rất nhanh. Bạn có nghĩ rằng bạn có thể thêm một trình bao bọc Unicode và vẫn ngắn hơn mã của tôi không?
đã ngừng quay ngược chiều

@leftaroundabout, tôi đoán là tôi có thể. Vấn đề chính là tôi đang làm việc trong một dòng lệnh Linux, nơi bạn không thể thấy Unicode, vì vậy việc gỡ lỗi sẽ gây khó chịu. Tôi cũng có một phiên bản tiết kiệm thêm khoảng 40 byte (tôi sẽ cập nhật sớm), vì vậy tôi có rất nhiều ký tự để làm việc.
ugoren

@ugoren: Chắc chắn bất kỳ bản phân phối Linux hiện đại nửa vời nào cũng hỗ trợ UTF-8?
han

@han, Tôi đang làm việc trên Windows và kết nối với Linux bằng SSH và Unicode không hoạt động. Tôi có thể ghi vào một tệp và mở trong Windows, nhưng nó không còn thú vị nữa.
ugoren

Điều này sẽ biên dịch với gcc? Tôi đang sử dụng Geany cho Windows với MinGW và nó sẽ biên dịch với một loạt các lỗi và cảnh báo nhưng nó sẽ không xây dựng / run.eg: C: \ Users \ xxx \ AppData \ Local \ Temp \ ccpBG9zy.o: codegolfchess.c :(. text + 0x2d8): tham chiếu không xác định đến `bcopy 'coll2: ld trả về 1 trạng thái thoát
rpd

5

Python 2.6, 886 - 1425 ký tự

Phiên bản ban đầu của tôi (trong các phiên bản) có 886 ký tự nhưng không hoàn toàn thỏa mãn thông số kỹ thuật (nó không kiểm tra để tránh người kiểm tra; thậm chí còn không xem xét các chuyển động có thể có của các mảnh màu đen).

Bây giờ nó đã (và tôi đã sửa một số lỗi trong bản gốc). Than ôi điều này đi kèm với một chi phí trong các nhân vật: 1425 bây giờ, nhưng vẫn còn rất ít chỗ để cải thiện. Phiên bản này sẽ chắc chắn hơn rất nhiều trong việc xử lý các trường hợp cạnh sau đó là phiên bản trước.

#-*-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"

Ví dụ đầu vào và đầu ra:

# ĐẦU VÀO

8 ║♜ ♞ ♝ ♝
7 ♟ ♟ ♟ Nhận ♟ ♟
6 ║
5 ║
4 ║
3 ║
2 ║♙ ♙ ♙
1 ║♖ ♘ ♗ ♕ ♔ ♗ ♘
Giáo dục
Giáo sư abcdefgh
# ĐẦU RA

8 ║♜ ♞ ♝ ♝
7 ♟ ♟ ♟ Nhận ♟ ♟
6 ║
5 ║
4 ║
3 ║
2 ║♙ ♙ ♙
1 ║♖ ♘ ♗ ♕ ♔ ♗ ♘
Giáo dục
Giáo sư abcdefgh

Đó là 886 byte, nhưng chỉ có 854 ký tự. (Chương trình của tôi có hơn 1kB, nhờ có nhiều nhà khai thác không phải ASCII!) - Bạn sẽ thêm kiểm tra để lấy vua chưa?
đã ngừng quay ngược chiều

@leftaroundabout: Tôi đã thêm séc vua (điều này buộc tôi cũng phải tính đến các chuyển động có thể có của màu đen và thêm rất nhiều ký tự ...). Ồ, phiên bản này sẽ chắc chắn hơn xung quanh các trường hợp cạnh (theo như tôi đã thử nghiệm).
BarsheD
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.