Mainkan gerakan catur yang valid, diberikan papan di stdin

11

Program diputar putih.

Contoh stdin:

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

Contoh stdout:

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

Setiap langkah yang sah tidak masalah. "En passant" dan castling diabaikan. Tidak masalah untuk menampilkan pesan kesalahan atau mencetak apa pun jika tidak ada langkah yang valid.

Jawaban dengan suara terbanyak menang.

Hristo Hristov
sumber
Maksud saya pesan kesalahan standar yang disebabkan oleh kegagalan beberapa fungsi bawaan bahasa. Jadi tidak apa-apa? - Apakah wajib bahwa program dapat melakukan tindakan hukum? Mungkin castling dan pion gerakan khusus harus dibuat opsional dengan bonus?
Berhenti menyalakan serangan balik
2
@leftaroundabout: Kapan pun Anda bisa kastil, Anda bisa memindahkan benteng saja, jadi Anda bisa melewatkan logika untuk itu setidaknya.
hammar
2
... dan memikirkannya lagi, gerakan "en passant" memerlukan informasi tentang apa yang telah dilakukan sebelumnya, yang tidak dapat disimpulkan hanya dari posisi bagian-bagian itu, jadi saya kira mungkin aman untuk menjatuhkannya. Namun, apakah langkah pertama ganda tersedia dapat disimpulkan dari pion, jadi Anda mungkin ingin memasukkan itu.
hammar
@hammar: Anda benar, saya belum memikirkan hal itu. Gerakan ganda juga tidak penting, kecuali untuk satu kasus: ketika Anda bisa melakukan dua langkah, Anda juga bisa pergi satu, jadi itu hanya menjadi penting ketika Anda berada di kontrol dan gerakan ganda adalah satu-satunya langkah yang mencakup raja. Juga, bahkan ketika Anda tidak perlu dapat menggunakan setiap gerakan, Anda masih perlu mempertimbangkan bahwa hitam dapat menjawab dengan segala kemungkinan.
Berhenti menyalakan serangan balik
9
Apakah pengunduran diri dihitung sebagai langkah hukum? :)
gnibbler

Jawaban:

16

Saya tidak mengeluh tentang upvotes, tetapi untuk bersikap adil ... solusi saya di sini sebenarnya tidak terlalu bagus. Ugoren lebih baik, selain kekurangan dukungan unicode. Pastikan untuk melihat semua jawaban sebelum memberikan suara, jika Anda baru saja menemukan pertanyaan ini!
Bagaimanapun.

Haskell, 893 888 904 952 (tanpa castling)

862 (tanpa pion gerakan ganda)

(Anda tidak menentukan apakah ini seharusnya kode golf, tetapi menurut saya memang seharusnya demikian)

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

Ketika Anda telah menginstal GHC (misalnya sebagai bagian dari platform Haskell ), Anda dapat melakukannya dengan adil

$ runhaskell def0.hs < examplechessboard.txt
8 ║♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟ … ♟ ♟ ♟
6 ║… … … … … … … …
5 ║… ♘ … … ♟ … … …
4 ║… … … … … … … …
3 ║… … … … … … … …
2 ║♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙
1 ║♖ … ♗ ♕ ♔ ♗ ♘ ♖
——╚═══════════════
—— a b c d e f g h
tidak lagi mengaktifkan counterclockwis
sumber
Sekarang ini gila :) Saya akan memeriksanya :)
Hristo Hristov
Adakah yang tahu cara menguji keangkeran ini? Ideone.com tidak bisa mengatasinya ...
Hristo Hristov
@HristoHristov: aneh itu tidak bekerja di Ideone. Mungkin ada hubungannya dengan karakter non-ASCII.
Berhenti menyalakan serangan balik
ya, ini adalah masalah dengan ideone
Hristo Hristov
14
Selamat, Anda berhasil membuat Haskell terlihat seperti APL. :-)
Ilmari Karonen
11

C, 734 672 640 karakter

Karakter dihitung tanpa spasi kosong yang bisa dilepas.
Format file yang saya gunakan tidak seperti yang diminta, tetapi ASCII yang disederhanakan.
Saya perlu menambahkan dukungan karakter Unicode, akan dikenakan biaya beberapa karakter.

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

Format file input / output:
Harus persis 8 baris dengan tepat 8 karakter. pnbrqkdigunakan untuk potongan putih, PNBRQKuntuk potongan hitam, ruang untuk ruang:

RNBQKBNR
PPPP PPP

 n  P


pppppppp
r bqkbnr

Logikanya cukup sederhana:
Untuk setiap gerakan yang mungkin dari setiap bagian putih, coba setiap gerakan yang mungkin dari setiap bagian hitam.
Jika tidak ada gerakan hitam yang menangkap raja putih, gerakan putih itu valid.

Papan dipertahankan sebagai char[256], diperlakukan sebagai matriks 16x16, di mana hanya 8x8 kiri atas yang digunakan. Posisi dan vektor pergerakan disimpan dalam bilangan bulat 8-bit ( x:4,y:4). Bit tambahan memungkinkan menggunakan aritmatika sederhana ( new_pos = old_pos + steps*direction), dengan deteksi mudah tepi papan ( &0x88melakukan keajaiban). r[]mengkodekan tiga hal:

  1. 15 byte pertama memetakan kode bagian internal (K = 1, P = 2, N = 3, B = 4, R = 5, Q = 6) ke huruf.
  2. 6 byte berikutnya memetakan kode bagian internal ke offset di bagian terakhir (K dan Q adalah sama, B adalah ekornya).
  3. 16 byte terakhir menyandikan pergerakan semua bagian, sebagai '('+vector.

Fungsi:

  1. mainmembaca papan, mengonversi surat ke kode internal, panggilan auntuk menemukan gerakan putih, mencetak papan.
  2. aloop rekursif atas 64 kotak. Untuk setiap bagian dari warna yang tepat (parameter c), ia menemukan aturan gerakan untuk bagian dan panggilan d.
  3. dberulang secara berulang atas aturan gerakan yang disandikan, yang merupakan daftar vektor, menyerukan emasing-masing. Ini memberikan eposisi asli, vektor dan batas jangkauan (7 untuk potongan di atas B, 2 untuk pion peringkat kedua, 1 jika tidak).
  4. emenguji semua gerakan sepanjang vektor. Jika langkah dimungkinkan (mis. Pion bergerak maju, di dalam papan, tidak diblokir, menangkap pion secara diagonal), periksa salah satu dari dua hal. Untuk gerakan putih, jalankan vuntuk memvalidasi gerakan. Untuk gerakan hitam, periksa apakah raja putih ditangkap. Jika benar, gerakan dimainkan di papan tulis.
  5. vmemvalidasi langkah putih. Ini menyalin papan samping, mengeksekusi gerakan untuk menguji, dan memanggil alagi, untuk mencari gerakan hitam.
ugoren
sumber
Akhirnya, solusi dengan pengkodean terkompresi yang tepat dari gerakan yang mungkin! Dan itu cepat sekali. Tidakkah Anda pikir Anda bisa menambahkan pembungkus Unicode dan masih lebih pendek dari kode saya?
Berhenti menghidupkan counterclock
@leftaroundabout, saya kira saya bisa. Masalah utama adalah saya bekerja di baris perintah Linux, di mana Anda tidak dapat melihat Unicode, jadi debugging itu akan mengganggu. Saya juga memiliki versi yang menyimpan sekitar 40 byte lebih (saya akan segera memperbarui), jadi saya punya banyak karakter untuk dikerjakan.
ugoren
@ugoren: Tentunya setengah jalan distribusi Linux modern mendukung UTF-8 di luar kotak?
han
@han, saya bekerja di Windows dan terhubung ke Linux oleh SSH, dan Unicode tidak berfungsi. Saya dapat menulis ke file dan membuka di Windows, tetapi itu tidak menarik lagi.
ugoren
Apakah ini dikompilasi dengan gcc? Saya menggunakan Geany untuk Windows dengan MinGW dan itu akan dikompilasi dengan banyak kesalahan dan peringatan tetapi tidak akan membangun / menjalankan.eg: C: \ Users \ xxx \ AppData \ Local \ Temp \ ccpBG9zy.o: codegolfchess.c :(. teks + 0x2d8): referensi tidak ditentukan untuk `bcopy 'collect2: ld mengembalikan 1 status keluar
rpd
5

Python 2.6, 886 - 1425 karakter

Versi awal saya (dalam revisi) datang pada 886 karakter tetapi tidak memenuhi spesifikasi sepenuhnya (itu tidak memeriksa untuk menghindari skakmat; bahkan tidak mempertimbangkan kemungkinan gerakan potongan hitam).

Sekarang ya (dan saya sudah memperbaiki beberapa bug di aslinya). Sayangnya ini datang dengan biaya karakter: 1425 untuk saat ini, tetapi masih ada sedikit ruang untuk perbaikan. Versi ini harus lebih solid dalam menangani kasus tepi daripada yang sebelumnya.

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

Contoh input dan output:

# MEMASUKKAN

8 ║♜ ♞ ♝… ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟… ♟ ♟ ♟
6 ║ ... ... ... ... ... ... ... ...
5 ║ ... ... ... ... ♟ ... ... ...
4 ║ ... ... ... ... ... ... ♙ ♛
3 ║ ... ... ... ... ... ♙ ... ...
2 ║♙ ♙ ♙ ♙ ♙… ♙…
1 ║♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖
——╚═══════════════
-- ABCD EFGH
# OUTPUT

8 ║♜ ♞ ♝… ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟… ♟ ♟ ♟
6 ║ ... ... ... ... ... ... ... ...
5 ║ ... ... ... ... ♟ ... ... ...
4 ║ ... ... ... ... ... ... ♙ ♛
3 ║ ... ... ... ... ... ♙ ♙ ...
2 ║♙ ♙ ♙ ♙ ♙………
1 ║♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖
——╚════════════════
-- ABCD EFGH
ChristopheD
sumber
Ini 886 byte, tetapi hanya 854 karakter. (Program saya memiliki lebih dari 1kB, terima kasih kepada banyak operator non-ASCII!) - Apakah Anda akan menambahkan pemeriksaan untuk mengambil raja belum?
Berhenti menghidupkan counterclockwis
@leftaroundabout: Saya telah menambahkan cek raja (yang memaksa saya juga memperhitungkan kemungkinan gerakan hitam, dan menambahkan banyak karakter ...). Oh well, versi ini harus lebih solid di sekitar tepi kasus (sejauh yang saya uji).
ChristopheD